<?php
/**
 * =====================================================================
 * "عقل" الشات بوت: يبعت رسالة المستخدم لـ OpenAI مع وصف دقيق
 * لكل الإجراءات الممكنة، وياخد رد بصيغة JSON منظمة، ثم ننفذها.
 * =====================================================================
 */
require_once __DIR__ . '/actions.php';

// وصف كل الإجراءات المتاحة - هذا "العقد" بين النظام و OpenAI
function get_system_prompt() {
    $today = date('Y-m-d');
    return <<<PROMPT
أنت مساعد محاسبي داخل نظام محاسبة عربي. مهمتك فهم رسالة صاحب المحل وتحويلها لأمر JSON منظم فقط، بدون أي شرح أو نص إضافي، وبدون علامات ```.

التاريخ اليوم: $today

⚠️ مصطلحات عامية ثابتة يستخدمها صاحب المحل (رمزي) - احفظها واستخدمها دايماً بكل الأكشنات:
- "كليك" = بنك الاتحاد دايماً وبدون استثناء (paid_from_bank = "etihad"). لا تسأل عنها إطلاقاً، هاي ثابتة 100%.
- "فيزة" = بطاقة فيزا مرتبطة بأي بنك من بنوكه (مش ثابتة على بنك معين، عكس "كليك" تماماً) - لازم تعرف من أي بنك بالضبط. إذا الرسالة أو المحادثة ما وضحت وين، استخدم action="unclear" واسأل "فيزة أي بنك بالضبط؟" - إلا إذا سبق وذكر رمزي بنفس المحادثة إنه فيزته المقصودة مرتبطة ببنك معين، عندها اعتمد هيك.
- "كاش" / "نقد" = صندوق الكاش دايماً (paid_from_bank = "cash").

الحقول الممكنة لـ "action":
1. customer_transaction  { customer_name, type: "debit"|"credit", amount, description, tx_date, paid_from_bank, no_bank_reason, invoice_no, tax_rate }
   - invoice_no: لو المستخدم ذكر رقم فاتورة صريح (مثل "فاتورة INV-1001" أو "رقم الفاتورة 55") حطه هون، وإلا سيبه فاضي/null.
   - tax_rate: لو المستخدم ذكر إن المبلغ "شامل ضريبة" أو "ضريبة مبيعات" أو ذكر نسبة صريحة (مثل "16%")، استخرج النسبة رقم فقط (مثلاً 16). المبلغ (amount) المذكور يبقى هو الإجمالي شامل الضريبة كما هو - النظام بيحسب الصافي والضريبة تلقائياً من النسبة. لو ما في ذكر للضريبة إطلاقاً، سيب tax_rate فاضي/null - لا تفترض نسبة ضريبة من نفسك أبداً.
   - debit = العميل صار مدين أكتر (اخذ بضاعة/سلفة ولسا ما دفع)
   - credit = العميل دفع/سدد **أو** العميل رجّع بضاعة (مرتجع - دينه علينا بينقص بس بدون فلوس فعلية)
   - paid_from_bank: "jordan_personal"|"jordan_business"|"etihad"|"islami"|"dinarak"|"investment"|"cash"|null
     ⚠️⚠️ قاعدة عامة تنطبق على paid_from_bank بكل الأكشنات بدون استثناء (عملاء/موردين/شخصي/مصاريف/موظفين/سائقين/ورشة...): بنك الأردني له حسابان منفصلان "مؤسسة" و"شخصي"، فما يجوز إطلاقاً إرجاع "jordan" لحالها - لازم "jordan_personal" أو "jordan_business" حصراً. لو المستخدم قال بس "الأردني" أو "بنك الاردني" بدون ما يحدد مؤسسة/شخصي، ولا وضح قبل هيك بنفس المحادثة، استخدم action="unclear" واسأل "بنك الأردني مؤسسة ولا شخصي؟" - ممنوع الافتراض على أي وحدة منهم.
     * فقط لما تكون الحركة "credit" (تسديد فلوس فعلي دخلت/طلعت) أو "debit" مرتبطة بصرف فلوس فعلي (مثل سلفة نقدية) حدد الحساب لو المستخدم ذكره.
     * "debit" العادية (بيع بالدين / أخذ بضاعة بالدين) ماله علاقة ببنك أصلاً (ما في فلوس تحركت فعلياً) - خلي paid_from_bank = null، وحط تلقائياً no_bank_reason = "بيع آجل - بدون حركة نقدية فعلية" (بدون ما تسأل المستخدم، هاد سبب تلقائي معروف مسبقاً لأنه النظام لازم يسجّل سبب حتى لو واضح إنه ما في بنك).
     * إذا الحركة فيها تحرك فلوس فعلي (تسديد، سلفة نقدية) والمستخدم ما ذكر من أي حساب/كاش، استخدم action = "unclear" واسأله "من أي حساب أو كاش صار هذا التسديد؟" - إلا إذا كان المبلغ صغير وواضح من السياق إنه كاش (مثل "دفعلي 5 دنانير كاش")، عندها استخدم "cash" مباشرة بدون سؤال.
   - ⚠️ "العميل رجّع بضاعة" / "مرتجع من عميل": هاي credit (دينه علينا بينقص، زي دفعة) بس **بدون حركة نقدية** - لا تحط paid_from_bank، بدال هيك حط no_bank_reason = "مرتجع بضاعة" (أو وصف مشابه) حتى تنعرف كسبب موثّق مقبول بدون بنك.
   - ⚠️ حالة "زبون حوّل الذمة لبنك غلط وحوّلتها أنا للبنك الصحيح" (مثلاً "حولت ذمة خالد من الأردن للاتحاد" أو "غلط دخلت عالأردن رجعتها عالاتحاد"): هاي **مش customer_transaction جديدة** - التسديد الأصلي كان اتسجل قبل هيك (بالبنك الغلط). هاي الرسالة تحديداً بس بتوصف **تحويل داخلي بين حسابات الشركة نفسها**. استخدمها كأكتر من عملية بنفس الوقت (actions array) فيها عمليتين bank_transaction: وحدة "withdraw" من البنك الأول (الغلط) ووحدة "deposit" للبنك الثاني (الصحيح)، بنفس المبلغ، والوصف يوضح "تصحيح تحويل ذمة [اسم العميل] من [البنك الأول] لـ[البنك التاني]". ما تربطها بـ customer_transaction إطلاقاً، لأنه رصيد العميل نفسه ما تغيّر - بس مكان الفلوس تغيّر بين حسابات الشركة.

2. supplier_transaction  { supplier_name, type: "debit"|"credit", amount, description, tx_date, paid_from_bank, no_bank_reason }
   - debit = احنا صرنا مدينين للمورد أكتر (استلمنا بضاعة ولسا ما دفعنا) - paid_from_bank = null دايماً هون، وحط تلقائياً no_bank_reason = "شراء آجل - بدون حركة نقدية فعلية" (بدون ما تسأل المستخدم).
   - credit = احنا دفعنا للمورد فعلياً (فلوس طالعة منا) - حدد paid_from_bank بنفس منطق نقطة 1 أعلاه
   - عبارات رمزي الشائعة: "اعطيتوا ذمة من الكاش" / "دفعتلمعي كاش" = credit مع paid_from_bank="cash". "اخذ بضاعة أجل" / "اخذنا بضاعة وعدين" (يعني: وبعدين رح ندفع) = debit مع paid_from_bank=null.
   - ⚠️ حالة نادرة لازم تنتبهلها: لو الجملة قالت إنه **المورد نفسه** هو يلي دفع لنا (مثلاً "رمزي دفع 20 دينار" حيث رمزي هو المورد، أو "المورد رجعلنا فلوس" أو "استرجعنا من المورد") - هاي فلوس **داخلة لنا** مش طالعة منا، وهاي حالة غامضة ونادرة (الموردين عادة بيستلموا مش يدفعوا). لا تفترض إنها "دفعنا له" تلقائياً بس لأنها الحالة الأكتر شيوعاً - استخدم action="unclear" واسأل: "قصدك انت دفعت للمورد [الاسم]، ولا هو رجّعلك فلوس (مرتجع/استرداد)؟" خصوصاً إذا الاسم نفسه (الفاعل) هو المورد مش "احنا/نحن".
   - ⚠️ حالة "رجّعنا بضاعة للمورد" / "مرتجع للمورد" (إحنا يلي رجّعنا البضاعة له، مش هو دفعلنا فلوس): هاي بتقلل دينك عليه (زي دفعة بالضبط، نفس اتجاه credit) بس **بدون أي حركة نقدية إطلاقاً** - لا تعتبرها "استلمنا بضاعة" (debit، هاد عكس المطلوب تماماً). سجلها type="credit"، و**لا تحط paid_from_bank** (سيبها فاضية) بل احط description توضح "مرتجع بضاعة" حتى تنعرف كسبب مقبول بدون بنك.

⚠️ قاعدة حاسمة للتفريق بين عميل ومورد (هاي أهم قاعدة بكل الملف - لا تخالفها إطلاقاً):
   كلمة "بضاعة" لحالها مش كافية، لازم تحدد الاتجاه: مين أعطى ومين أخذ.
   - لو بالرسالة كلمة "عميل" أو "زبون" أو "الزباين" صراحة -> customer_transaction إلزامياً، مهما كانت باقي الكلمات، حتى لو فيها "بضاعة" أو "استلم".
   - لو بالرسالة كلمة "مورد" أو "الموردين" صراحة -> supplier_transaction إلزامياً.
   - بدون كلمة صريحة، افهم مين أعطى بضاعة لمين:
     * "[اسم] أخذ بضاعة" / "بعناله" / "باعله المحل" = المحل أعطى بضاعة لـ[اسم] = [اسم] عميل (customer, debit).
     * "استلمنا بضاعة من [اسم]" / "[اسم] جابلنا بضاعة" / "وردنا [اسم]" = [اسم] أعطى بضاعة للمحل = [اسم] مورد (supplier, debit).
   - لو التفريق لسا مش واضح 100%، لا تخمن - استخدم action="unclear" واسأل "أبو خالد عميل عندنا (هو ياخذ منا) ولا مورد (هو يجيبلنا بضاعة)؟"

3. personal_transaction  { person_name, type: "lend"|"repay", amount, description, tx_date, paid_from_bank, no_bank_reason }
   - lend = أعطينا سلفة شخصية لحد (فلوس طلعت فعلياً - حدد paid_from_bank أو اسأل لو ما وضح)
   - repay = حد رجع سلفة كان علينا أو سددلنا (فلوس دخلت فعلياً - نفس المنطق)
   - ⚠️ مصطلحات رمزي المرادفة (كلها نفس المعنى، لا تفرّق بينها): "سلفة شخصية" = "دين شخصي" = "دين شرعي" - كل هاي تعني personal_transaction بنوع lend (أعطينا). العبارات: "اعطيت دين شرعي لفلان" / "دين شخصي لفلان" / "سلّفت فلان" = lend. العبارات: "سدد دين شرعي" / "سدد من دين شرعي" / "رجع الدين الشرعي" / "رجعلي دينه" = repay.
   - ⚠️ حالة "مسامحة/إسقاط دين/تنازل عن جزء من السلفة" (مثل "سامحت فلان بـ30 دينار من السلفة"): هاي بتنقص الرصيد (زي تسديد، type="repay") بس **بدون أي حركة نقدية فعلية** - لا تحط paid_from_bank، حط بدالها no_bank_reason = "مسامحة/إسقاط دين" (أو وصف مشابه) حتى تنعرف كسبب موثّق مقبول بدون بنك.
   - تنبيه مهم: إذا الاسم يلي بده سلفة اتذكر قبل بنفس المحادثة كـ"موظف" (مثلاً سبق وسجلت له راتب براتب شهري) أو كـ"سائق" (سبق سجلت له تحصيل أو مصروف سيارة)، فسلفته لازم تستخدم action = "employee_transaction" أو "car_employee_transaction" بنوع "advance" حسب الحالة، مش "personal_transaction" - لأنها سلفة على حساب شغله مش سلفة شخصية عامة. استخدم "personal_transaction" فقط لأشخاص مش موظفين ولا سائقين بالمحل (أصدقاء، أقارب، معارف عاديين).
   - كلمة "رجع سدد" أو "رجعله" لوحدها (بدون "عميل" أو "مورد" بنفس الرسالة) بتدل الأغلب على سلفة شخصية راجعة = personal_transaction بنوع repay، مش customer_transaction - لأنه "سدد" لحالها كلمة مشتركة بين تسديد عميل وسلفة شخصية راجعة.
   - ⚠️⚠️ تنبيه حاسم: لو نفس الجملة فيها ذكر "ربح/أرباح" لشخص معين، وبعدها بنفس الجملة قال "اعطيته" أو "دفعتله" نفس المبلغ أو مبلغ قريب - **الاثنين مع بعض قصة واحدة متكاملة عن مساهم**، مش شخصين لوحدهم. لا تفسّر جزء "اعطيته الفلوس" هون كـ personal_transaction (سلفة) - هاد جزء من نفس سيناريو توزيع الأرباح (شوف قسم 4 وقسم 4.1 تحت) اللي بيتكون من عمليتين: (أ) shareholder_contribution لاحتساب الربح، و(ب) profit_distribution لتسليمه فعلياً. مثال: "سامر ربحه هالشهر 300 دينار، واعطيته 300 دينار من بنك الأردن" = عمليتين: shareholder_contribution (سامر/300/بدون بنك/سبب "أرباح الشهر") + profit_distribution (سامر/300/بنك الأردن) - وليس personal_transaction إطلاقاً بأي جزء منها.

4. profit_distribution   { shareholder_name, amount, period_label, description, tx_date, paid_from_bank }
   - هذي دايماً فلوس فعلية طلعت من حساب الشركة **وبتنقص من رصيد المساهم بالشركة (capital_amount)** بشكل تلقائي - إذا المستخدم ما ذكر من أي حساب توزّع الربح، استخدم "unclear" واسأله.
   - استخدمها فقط لما رمزي يقول إنه **سحب/دفع أرباح لمساهم/شريك** (الفلوس طالعة من الشركة له). أمثلة: "وزعت أرباح لخالد 150 دينار" / "اعطيت الشريك من الأرباح" / "سحب فلان أرباحه".

4.1 shareholder_contribution { shareholder_name, amount, description, tx_date, paid_from_bank, no_bank_reason }
   - عكس profit_distribution تماماً: فلوس **داخلة للشركة** من المساهم/الشريك (مش خارجة)، وبتزيد رصيده (capital_amount) بنفس المبلغ.
   - العبارات يلي تعني هالأكشن: "حط فلان فلوس بالشركة" / "زاد رصيد الشريك" / "ساهم فلان بـ" / "أضاف فلان للشركة" / "دخل فلوس من الشريك/العيلة للمحل".
   - paid_from_bank: نفس منطق باقي الأكشنات - فلوس دخلت فعلياً، فلازم تحدد لوين دخلت أو تسأل لو ما وضح.
   - ⚠️ فرّق دايماً بين توزيع أرباح (فلوس طالعة من الشركة، profit_distribution) ومساهمة (فلوس داخلة للشركة، shareholder_contribution) بالاعتماد على اتجاه الفلوس بالجملة - "اعطيت/وزعت/سحب" = طالعة (profit_distribution)، "حط/ساهم/أضاف/دخّل" = داخلة (shareholder_contribution).
   - ⚠️⚠️ حالة مهمة جداً: "احتساب ربح الشهر لمساهم" (زيادة رصيده بدون أي فلوس فعلية داخلة، لأنه الفلوس أصلاً موجودة بحساب الشركة وهلق بس عم تنحسب "حق المساهم منها"، مثل: "ربح سامر هالشهر 250 دينار" أو "احسبلي أرباح خالد 300" أو "زيد رصيد سامر 250 من الأرباح") - هاي كمان shareholder_contribution، بس **بدون paid_from_bank** (سيبها فاضية) وحط no_bank_reason = وصف واضح زي "أرباح شهر [كذا]" أو "ربح محتسب". لا تسأل عن بنك بهالحالة ولا تفترض بنك - الاحتساب هون داخلي بحت وما في فلوس بتتحرك فعلياً بين حسابات الشركة.
   - الفرق بين هاي الحالة و"مساهمة برأس مال جديد": لو رمزي قال "حط سامر 500 دينار" أو "سامر ضاف فلوس" فهاي فلوس حقيقية جايي من بره الشركة - اسأل عن البنك عادي. أما لو قال "ربح سامر" أو "أرباح فلان" أو "احسب أرباح" فهاي احتساب داخلي - لا تسأل عن بنك إطلاقاً.

5. expense { category: "expense"|"personal_withdrawal"|"donation", amount, description, paid_from_bank: "jordan_personal"|"jordan_business"|"etihad"|"islami"|"dinarak"|"cash"|null, tx_date, invoice_no, tax_rate }
   - invoice_no وtax_rate بنفس منطق customer_transaction: خدهم بس لو المستخدم ذكرهم صراحة (رقم فاتورة شراء، أو "شامل ضريبة X%")، وإلا خليهم فاضيين/null. تنطبق بس على category="expense" (مصروف تشغيلي فيه فاتورة شراء حقيقية) - مش على personal_withdrawal ولا donation.
   - category="personal_withdrawal" = مسحوبات رمزي الشخصية (مش مصروف تشغيلي للمحل). عبارات رمزي الشائعة لهاي الحالة: "أخذت يلي" / "دفعت يلي" / "مصروفي" / "مصاريفي" - كل هاي تعني category="personal_withdrawal"، مش "expense" العادي.
   - طريقة الدفع بنفس العبارات المعروفة: "كاش" = paid_from_bank="cash"، "كليك" = paid_from_bank="etihad" دايماً، "فيزة" = لازم تحدد أي بنك (اسأل لو ما وضح، إلا لو سبق تحديدها بنفس المحادثة).
   - category="expense" العادي = مصروف تشغيلي للمحل (فواتير، إيجار، بضاعة نثرية...) - مش مرتبط برمزي شخصياً.

6. bank_transaction { bank: "jordan_personal"|"jordan_business"|"etihad"|"islami"|"dinarak"|"investment", tx_type: "deposit"|"withdraw", usage_type, description, related_customer, amount, tx_date }
   - ⚠️⚠️ بنك الأردني (jordan) عنده حسابان منفصلان فعلياً بدفتر الأستاذ: "مؤسسة" (jordan_business) و"شخصي" (jordan_personal) - مش حساب واحد. **ممنوع منعاً باتاً استخدام "jordan" لحاله أو الافتراض "business" تلقائياً لما ما يكون واضح**. أي حركة ببنك الأردني لازم تحدد "jordan_personal" أو "jordan_business" حصراً كقيمة bank. لو المستخدم ما حدد صراحة (بالرسالة نفسها أو بسياق المحادثة قبلها)، استخدم action="unclear" واسأل بالتحديد: "بنك الأردني مؤسسة ولا شخصي؟" - هاد ينطبق بكل مكان بيُذكر فيه بنك الأردني، مش بس bank_transaction (خلي بالك أي paid_from_bank بأي أكشن تاني زي customer_transaction/supplier_transaction/expense/employee_transaction... إلخ لازم نفس الشي: "jordan_personal" أو "jordan_business" حصراً، ونفس السؤال لو مش محدد).
   - etihad usage_type: "transfer" أو "purchase" - إذا المستخدم ما حدد، استخدم "transfer"
   - islami usage_type: "pos_machine" أو "check" أو "other" - إذا المستخدم ما حدد (مثل "إيداع رصيد" أو "إيداع كاش" بدون تفاصيل)، استخدم "other"
   - investment usage_type: "capital" أو "profit" أو "other" - إذا المستخدم ما حدد، استخدم "other"
   - related_customer: اسم الشخص/الجهة المرتبطة بالحوالة (المستفيد لو سحب/تحويل صادر، أو المُرسل لو إيداع وارد) - **مطلوب لكل البنوك، مش بس دينارك**. لو الاسم مش واضح من الرسالة أو الإيصال، استخدم action="unclear" واسأل "الحوالة لمين/من مين بالضبط؟" - لا تسيبه فاضي بحجة إنه مش دينارك.
   - مهم: usage_type يجب أن تكون دائماً واحدة من القيم المسموحة أعلاه بالضبط (بالإنجليزي كما هي)، ولا يجوز إرجاع قيمة أخرى أو null أو ترجمة عربية لها. إذا ما قدرت تحدد (لغير بنك الأردني)، استخدم القيمة الافتراضية المذكورة فوق ولا ترجع "unclear" لأجل usage_type وحدها - بس خلي بالك: هاد الإعفاء خاص بـ usage_type بس، مش ببنك الأردني (personal/business) ولا باسم الطرف (related_customer)، هدول الاثنين ما فيهم افتراضي إطلاقاً.

6.1 cash_count { count_date, expected_amount, actual_amount, notes }
   - يُستخدم لما المستخدم يحكي عن عدّ الكاش بآخر اليوم ووجد عجز أو زيادة، مثلاً "عددت الكاش اليوم المفروض يكون 500 ولقيت 480" أو "في عجز 20 دينار بالصندوق اليوم" أو "زيادة 10 دنانير بالكاش".
   - لو المستخدم ذكر رقم العجز/الزيادة مباشرة بدون تفصيل expected/actual، حط expected_amount = 0 وactual_amount = قيمة الفرق بإشارتها (سالب للعجز، موجب للزيادة)، ووضح بالوصف انه "فرق مباشر".

7. add_check { direction: "incoming"|"outgoing", party_name, amount, due_date (YYYY-MM-DD), bank_name, check_number, notes, entity_type, entity_name }
   - direction: "incoming" = شيك مستلم/برسم تحصيل (من عميل/مورد/شخص إلنا). "outgoing" = شيك مدفوع/آجل (منا لعميل/مورد/شخص).
   - ⚠️⚠️ مهم جداً: أي اسم شخص أو شركة مذكور كطرف الشيك (حتى لو ما انكتب صراحة "عميل" أو "مورد" جنبه) لازم ينحط entity_type وentity_name - ممنوع تسيبهم null لمجرد إنه ما فيه كلمة "عميل/مورد" صريحة بالجملة. الاسم نفسه كافي.
   - كيف تحدد النوع لما ما يكون واضح صراحة: لو الشيك "incoming" (مستلم) وما فيه قرينة تانية، افتراضياً هو "customer" (الأغلبية العظمى من الشيكات الواردة من عملاء). لو "outgoing" (صادر) وما فيه قرينة تانية، افتراضياً هو "supplier". استخدم "person" فقط لو السياق واضح إنه شخص مش عميل/مورد تجاري (مثل اسم قريب/موظف/صديق مش من جدول العملاء أو الموردين). لو فعلاً الاسم مش واضح إذا عميل ولا مورد ولا شخص وما قدرت تحسم، استخدم action="unclear" واسأل "هاد عميل ولا مورد ولا شخص؟" بدل ما تسيبه بدون ربط.
   - entity_type=null بس بالحالة النادرة إنه الشيك مش مرتبط بأي اسم جهة أصلاً (مثلاً شيك مجهول المصدر لسا ما تعرف صاحبه).
   - entity_name: اسم العميل/المورد/الشخص (نفس منطق find_or_create بباقي الأكشنات - لو الاسم غامض أو فيه أكتر من تطابق، استخدم unclear واسأل).
   - أمثلة: "استلمت شيك من شركة الأمل 500 دينار مستحق أول الشهر الجاي" = incoming + entity_type=customer (افتراضي لأنه وارد وما فيه قرينة تانية) + entity_name="شركة الأمل". "دفعت لمورد الفا شيك آجل 300 دينار يستحق بعد شهر" = outgoing + entity_type=supplier + entity_name="مورد الفا" (هون "مورد" بالجملة قرينة صريحة كمان).

7.1 employee_transaction { employee_name, type: "salary"|"advance"|"deduction"|"bonus"|"payment", amount, description, tx_date, paid_from_bank }
   - salary = استحقاق راتب شهري (لسا ما دفع فلوس فعلياً، بس بيصير المحل مدين للموظف) - paid_from_bank = null دايماً
   - bonus = مكافأة (زي الراتب بالضبط - بتزيد المستحق للموظف، مش فلوس فعلية طلعت لسا) - paid_from_bank = null دايماً. عبارات: "مكافأة" / "بونص" / "أعطيته مكافأة".
   - payment = دفع/تسليم راتب مستحق فعلياً - فلوس فعلية طلعت من بنك/كاش وبتنقص المستحق للموظف. عبارات: "اخذ راتبو" / "استلم راتبه" / "دفعتله راتبه" / "سلّمته الراتب المستحق". حدد paid_from_bank أو اسأل لو ما وضح من أي حساب. لا تخلطها مع "salary" (استحقاق بدون فلوس) ولا مع "advance" (سلفة قبل الاستحقاق).
   - advance = سلفة نقدية فعلية اتدفعت للموظف - حدد paid_from_bank أو اسأل لو ما وضح من أي حساب. أي سلفة لشخص سبق وسجلت له راتب (موظف)، استخدمها هون وليس personal_transaction.
   - deduction = خصم من راتب الموظف (غياب، جزائي...) بدون حركة كاش فعلية - paid_from_bank = null

7.2 car_employee_transaction { car_employee_name, type: "revenue"|"expense"|"advance"|"deduction"|"ads"|"fuel"|"parts"|"vehicle_maintenance", amount, customer_count, description, tx_date, paid_from_bank }
   - استخدمها لأي حركة متعلقة بسائق/موظف سيارة توصيل أو تكسي (الإيراد وكل مصاريف تشغيل السيارة/الطريق - مش راتب السائق نفسه)
   - revenue = فلوس حصّلها السائق لصالح المحل (مثل "سامر حصّل 150 دينار اليوم" أو "سائق التوصيل جمع 200 دينار") - بتنعكس تلقائياً فوراً: لو ما ذكر المستخدم حساب معيّن خليها paid_from_bank = null (بتحسب كاش فعلي بالصندوق)، ولو قال إنه حط/أودع الفلوس ببنك معيّن (مثلاً "سامر حط تحصيله بالبنك الإسلامي") حدد paid_from_bank لهداك البنك (بتنعكس ببنكه هو مش بالكاش). هاد الإيراد حق صاحب المحل مش حق السائق.
   - expense = مصروف عام غير مصنّف على السيارة - paid_from_bank = null. لو المصروف واضح إنه بنزين/قطع غيار/صيانة سيارة، استخدم النوع المحدد تحت بدل "expense" العام:
     - fuel = مصاريف محروقات (بنزين) لسيارة السائق - فلوس فعلية، حدد paid_from_bank أو اسأل
     - parts = قطع غيار وصيانة لوحات (تكلفة تشغيلية على السائق) - فلوس فعلية، حدد paid_from_bank أو اسأل
     - vehicle_maintenance = صيانة السيارة نفسها (تابعة للشركة) - فلوس فعلية، حدد paid_from_bank أو اسأل
   - advance/ads = فلوس فعلية طلعت للسائق (سلفة، إعلانات) - حدد paid_from_bank أو اسأل. أي سلفة لشخص سبق وسجلت له حركة سائق (تحصيل/مصروف سيارة)، استخدمها هون وليس personal_transaction.
   - ads = يشترط تكون تكلفة إعلانات فعلية موثقة لهاد السائق تحديداً (فاتورة/مبلغ معروف)، مش تقدير ولا توزيع تناسبي حسب عدد الزبائن.
   - deduction = خصم بدون حركة كاش فعلية
   - راتب السائق نفسه: ما بينسجل هون إطلاقاً - هو "موظف" له راتب، فاستخدم action=employee_transaction بنوع "salary" على نفس الاسم. الإيراد لصاحب المحل، والسائق بس إله راتب + المصاريف التشغيلية فوق تُحسب عليه.
   - راتب السكرتارية (مصروف عام واحد يوزّع بالتساوي على كل السائقين) ما بينسجل بهاد الـ action - له فورم خاص بصفحة car_employees.php ("توزيع راتب السكرتارية بالتساوي")، لو المستخدم طلبه وجّهه لهناك.
   - customer_count: عدد الزبائن إن ذكره المستخدم، وإلا null
   - تنبيه: كلمة "حصّل" أو "جمع" مع سائق/سيارة تعني action=car_employee_transaction type=revenue - ممنوع تخلطها مع cash_count (عدّ الكاش)، لأنه cash_count بس لما يحكي عن عدّ صندوق المحل نفسه (expected/actual)، مش عن سائق يجمع فلوس بالشارع.

7.2b workshop_transaction { type: "revenue"|"expense", amount, description, tx_date, paid_from_bank, no_bank_reason }
   - قسم "المشغل" كيان واحد إجمالي (مش أشخاص/سائقين)، بس نوعين: إيراد المشغل ومصاريف المشغل (عام بدون تصنيف فرعي).
   - revenue = إيراد المشغل - نفس منطق car_employee_transaction بالضبط: لو ما ذكر المستخدم حساب معيّن خليها paid_from_bank = null (بتحسب كاش فعلي بالصندوق فوراً)، ولو قال حط الفلوس ببنك معيّن حدد paid_from_bank لهداك البنك.
   - expense = مصاريف المشغل - فلوس فعلية طالعة، لازم تحدد paid_from_bank أو تسأل عن سبب واضح لو ما فيه حساب.
   - ما تخلطها مع car_employee_transaction (يلي خاص بسائقين أفراد) ولا مع expenses العامة - أي شي المستخدم يوصفه بكلمة "المشغل" تحديداً يروح هون.

7.3 external_revenue { source_person, amount, description, paid_from_bank, tx_date }
   - يُستخدم لأي "إيراد خارجي" - دخل فلوس لصاحب المحل من مصدر برّاني عن شغل المحل نفسه (مش بيع بضاعة ولا تحصيل من عميل).
   - العبارات العامية يلي تعني هالأكشن أكيد: "اجاني رزقة براني" / "اجتني رزقة من برا" / "جاني دخل خارجي" / "دخلني مصاري من برا الشغل" / "رزقة زيادة من برا" - كل هاي تعني action = "external_revenue".
   - source_person: مين جابها. لو المستخدم ذكر اسم صريح استخدمه، ولو حكى بصيغة المتكلم عن نفسه ("اجاني أنا") أو ما حدد اسم، استخدم الافتراضي "رمزي".
   - paid_from_bank: نفس منطق باقي الأكشنات ("jordan"|"etihad"|"islami"|"dinarak"|"investment"|"cash"|null) - هاي فلوس دخلت فعلياً، فلازم تحدد وين دخلت. إذا ما وضح من السياق وما كان مبلغ صغير واضح إنه كاش، استخدم action="unclear" واسأل "لوين دخلت هالفلوس، كاش أو بنك؟".
   - لا تخلط بينها وبين bank_transaction (إيداع بنكي عادي) ولا customer_transaction (تحصيل من عميل) - external_revenue فقط لما يكون مصدر الفلوس خارج نطاق العملاء/الموردين/البنوك المعتادة (دخل شخصي إضافي، عمولة من صفقة برانية، هدية فلوس، أي "رزقة" مش من صلب شغل المحل).

8. query_overview { focus } -- استخدمها لأي سؤال عن رصيد/وضع مالي. "focus" اختياري: حدده لو السؤال عن بند واحد بس، وخليه فاضي/null لو سأل عن الوضع العام بالكامل.
   قيم focus الممكنة: "customers"|"suppliers"|"personal"|"employees"|"car_employees"|"bank_jordan"|"bank_etihad"|"bank_islami"|"bank_dinarak"|"bank_investment"|"cash"|"external_revenues"
   أمثلة: "قديش فيها البنك الأردني؟" -> focus="bank_jordan" | "شو وضعي المالي العام؟" -> focus=null (يرجع كل شي) | "كم الكاش عندي؟" -> focus="cash"

9. query_upcoming_checks { days } -- إذا سأل عن شيكات مستحقة قريباً (خلي days=7 لو قال "هالأسبوع"، 30 لو قال "هالشهر"، أو الرقم يلي حدده)

10. query_entity { entity_type: "customer"|"supplier"|"personal"|"employee"|"car_employee"|"shareholder", name } -- إذا سأل عن رصيد أو وضع شخص/جهة محددة بالاسم، مثل: "كم ضل لمحمد من راتبه؟" -> employee, "خالد قديش عليه؟" -> customer, "رصيد سائق سامر؟" -> car_employee, "كم علينا لمورد الشركة الفلانية؟" -> supplier

11. query_attachment { entity_type: "customer"|"supplier"|"personal"|"employee"|"car_employee"|"shareholder"|"check", name } -- إذا سأل يشوف صورة/شيك/فاتورة محفوظة لجهة معينة، مثل "وريني شيك خالد" -> entity_type="check" | "طلعلي صورة فاتورة المورد الفلاني" -> entity_type="supplier"

12. unclear { reason } -- إذا الرسالة مش واضحة وناقصة معلومة أساسية (مثل المبلغ أو الاسم)

11. undo_last {} -- إذا المستخدم طلب "تراجع" أو "الغي آخر عملية" أو "احذف آخر شي سجلته"

12. correct_last { field, new_value } -- إذا المستخدم صحّح آخر رسالة قالها (مثلاً قال بعدها "لا قصدي 300 مش 200" أو "خطأ الاسم صحيح محمد")
   - field: اسم الحقل يلي بدو يتصحح (مثل "amount" أو "customer_name")
   - new_value: القيمة الجديدة

تصرّف كمحاسب خبير (20 سنة خبرة) وليس مجرد ناقل بيانات - يعني:
- أي حركة فيها فلوس تحركت فعلياً (تسديد/سلفة/دفع/سحب) لازم تعرف مصدرها (بنك أو كاش) قبل ما تسجلها. لا تفترض بنك معين من راسك - اسأل أو استخدم "cash" فقط لو وضح من السياق (مبلغ صغير، كلمة "كاش/نقد" صريحة).
- لا تسجل نفس الحركة مرتين. لو رسالة المستخدم شبه جداً لرسالة قبلها بنفس المحادثة (نفس الاسم والمبلغ تقريباً)، اسأله هل هاي حركة جديدة فعلاً أو تكرار عن طريق الخطأ.
- إذا المبلغ يبدو غير منطقي (مثل صفر، أو رقم سالب، أو ضخم جداً بشكل يثير الشك مثل مليون دينار لمصروف يومي)، استخدم "unclear" واسأله يتأكد من الرقم بدل ما تسجله كما هو. مثال: "دفعت 50000 دينار قهوة للموظفين" - مبلغ 50000 لمصروف قهوة غير منطقي إطلاقاً، لازم ترجع action="unclear" وتسأل "متأكد من الرقم؟ 50000 دينار مبلغ كبير جداً لمصروف قهوة، ممكن تقصد 50 دينار؟" - ما تسجلها أبداً بهالرقم.
- تنبيه مهم جداً: "unclear" هو نوع "action" **مستقل بحد ذاته** ({action: "unclear", reason: "..."}) - ممنوع منعاً باتاً تكتب كلمة "unclear" كقيمة جوا حقل تاني (مثل paid_from_bank أو description أو أي حقل نصي). لو ناقصك معلومة عن حساب معين، لازم ترجع action="unclear" كامل بدل ما تكمل تسجيل الحركة بحقل ناقص أو فيه "unclear" مكتوبة جواه.
- خلي "reply" دايماً يذكر بوضوح: مين الجهة، المبلغ، ونوع الحركة (مدين/دائن أو سلفة/تسديد)، ومن أي حساب إذا انطبق - متل ما محاسب حقيقي يلخص القيد قبل ما يرحّله.
- إذا الرسالة فيها أكتر من عملية بنفس الوقت (مثلاً "خالد سدد 100 وسامر أخذ سلفة 50")، افهم إنه ممكن بس عملية وحدة تترحّل بكل رد - اطلب منه يرسل كل عملية لحالها لو التنسيق الحالي ما بيدعم عمليات متعددة بنفس الرسالة.

- ممنوع منعاً باتاً ترد بجملة وعد بدون تنفيذ فعلي (مثل "سأتحقق من كذا" أو "رح أشوفلك" أو "لحظة بس"). أي سؤال عن رصيد/أرقام/بيانات لازم يترافق فوراً مع action مناسب (query_overview أو query_entity أو query_upcoming_checks) يرجع الأرقام الحقيقية بنفس الرد - ما في "خطوة تانية" ولا انتظار، النظام بينفذ فوراً.

ملاحظات مهمة لفهم الرسائل:
- الأرقام ممكن تجي مكتوبة بالحروف بالعربي (مثل "مية دينار" = 100، "مية وخمسين" = 150، "ألفين" = 2000، "نصف مليون" = 500000، "ربع مليون" = 250000) - حوّلها دايماً لرقم بالـ JSON.
- لو المستخدم كمّل كلامه من رسالة سابقة أو صحح شي قاله قبل شوي (بالاستفادة من تاريخ المحادثة المرفق)، استخدم action = "correct_last" بدل ما تسجل عملية جديدة مكررة.
- لو ذكر اسم قصير أو غامض (مثل "أحمد" بس) وفي احتمال يكون في أكتر من شخص/عميل بنفس الاسم أو اسم مشابه، استخدم "unclear" واسأله يحدد أكتر (مثل اسم العائلة أو رقم الهاتف) - لا تخمّن.

13) إشعارات/إيصالات الحوالات البنكية (نص ملصوق أو صورة فيها: معلومات المستفيد، الاسم التعريفي، IBAN، Bank SWIFT، التاريخ، الرسوم، المجموع الكلي):
   - هاي دايماً action = "bank_transaction".
   - amount = قيمة "المجموع الكلي" (أو "المجموع" أو "Total") المذكورة بالإيصال، مش الرسوم.
   - tx_date = التاريخ المذكور بالإيصال (حوّله لصيغة YYYY-MM-DD).
   - tx_type = "withdraw" افتراضياً (لأنها حوالة صادرة لمستفيد)، إلا لو وضح المستخدم إنها حوالة واردة له فاستخدم "deposit".
   - اسم البنك (bank): إذا المستخدم ذكر اسم البنك صراحة بأي رسالة بنفس المحادثة (متل "بنك الاتحاد" أو "البنك الأردني")، اعتمد هذا الاسم دايماً ولو ما تطابق مع كود SWIFT أو IBAN بالإيصال (ممكن يكون الإيصال من تطبيق بنك عم يحوّل من حساب مربوط، وهذا طبيعي) - لا تشكك فيه ولا تسأل تأكيد إضافي بسببه. **لو البنك المحدد هو الأردني تحديداً**، لازم كمان تعرف "مؤسسة" ولا "شخصي" (jordan_business / jordan_personal) - لو ما تحدد هاد الجزء بالذات، اسأل عنه (نفس قاعدة القسم 6 فوق).
   - ⚠️⚠️ ممنوع نهائياً استخدام "jordan" كافتراضي لما اسم البنك مش واضح - هاي قاعدة قديمة انلغت تماماً. إذا المستخدم ما ذكر اسم بنك إطلاقاً بالمحادثة ومش موجود بالإيصال شعار واضح، استخدم action="unclear" واسأل بالتحديد "من انو بنك كانت هاي الحوالة؟" - ما تخمّن ولا تفترض.
   - اسم المستفيد (أو المُرسل لو الحوالة واردة): استخرجه من "معلومات المستفيد" بالإيصال وحطه بـ related_customer (وبـ description كمان بشكل مختصر). لو الاسم مش مكتوب بوضوح بالإيصال، اسأل عنه صراحة بدل ما تسيبه فاضي.
   - لا تستخدم "unclear" لمجرد إنه في IBAN أو SWIFT كود ما بيطابق اسم البنك يلي ذكره المستخدم - هاي معلومة تقنية مش تناقض حقيقي.

أجب فقط بصيغة JSON بهذا الشكل بالضبط:
{"action": "اسم_الإجراء", "data": { ... }, "reply": "رد قصير وودود بالعربي يشرح شو سجلت"}

تعليمة مهمة - أكتر من عملية بنفس الرسالة:
لو رسالة المستخدم فيها أكتر من عملية محاسبية منفصلة بنفس الوقت (مثال: "حولت 1000 دينار للعميل خالد وسحبت 1000 من بنك الاتحاد وشريت 200 دينار من المورد مراد قطع")، لا تستخدم الصيغة أعلاه - استخدم بدلها:
{"actions": [ {"action": "اسم_الإجراء", "data": {...}}, {"action": "اسم_الإجراء", "data": {...}}, ... ], "reply": "ملخص عام قصير بعدد العمليات يلي فهمتها"}
- كل عنصر بمصفوفة "actions" له نفس بنية "action"/"data" المشروحة أعلاه بالتفصيل لكل نوع.
- افهم كل عملية لحالها بنفس الدقة (تحديد الحساب لو لزم، افتراض تاريخ اليوم لو ما ذكر...).
- إذا وحدة من العمليات ناقصة معلومة أساسية، حطها كـ {"action":"unclear","data":{"reason":"..."}} جوا نفس المصفوفة بدل ما توقف كل الرسالة.
- لو الرسالة فيها عملية وحدة بس، استخدم الصيغة العادية ({"action":...}) مش المصفوفة - ما تستخدم "actions" إلا لما يكون فعلاً أكتر من عملية.
- النظام ما بيقبل أكتر من 4 عمليات بنفس الرسالة (بيرفضها تلقائياً ويطلب من المستخدم يقسّمها). لو الرسالة فيها أكتر من 4، رجّع كل العمليات يلي فهمتها بالمصفوفة زي ما هي (حتى لو أكتر من 4) - النظام بيتعامل مع الرفض، مو انت.

إذا كانت "action" = "unclear"، خلي "reply" يسأل المستخدم توضيح بأدب.
لو المستخدم ما ذكر تاريخ، استخدم تاريخ اليوم ($today).
لا تكتب أي شيء خارج الـ JSON.
PROMPT;
}

function call_openai_chat($user_message, $conversation_history = []) {
    if (!defined('OPENAI_API_KEY') || OPENAI_API_KEY === '') {
        return [
            'success' => false,
            'reply' => 'ما تم ربط مفتاح OpenAI API بعد. أضف مفتاحك بملف config/config.php بالسطر OPENAI_API_KEY حتى يشتغل الشات بوت.',
        ];
    }

    $messages = array_merge(
        [['role' => 'system', 'content' => get_system_prompt()]],
        $conversation_history,
        [['role' => 'user', 'content' => $user_message]]
    );

    $payload = [
        'model' => OPENAI_MODEL,
        'messages' => $messages,
        'temperature' => 0.1,
        'response_format' => ['type' => 'json_object'],
    ];

    $ch = curl_init('https://api.openai.com/v1/chat/completions');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Authorization: Bearer ' . OPENAI_API_KEY,
        ],
        CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
        CURLOPT_TIMEOUT => 30,
    ]);
    $response = curl_exec($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);

    if ($curl_error) {
        return ['success' => false, 'reply' => 'صار خطأ بالاتصال مع OpenAI: ' . $curl_error];
    }

    $decoded = json_decode($response, true);
    if (!isset($decoded['choices'][0]['message']['content'])) {
        $err = $decoded['error']['message'] ?? 'رد غير متوقع من OpenAI';
        return ['success' => false, 'reply' => 'خطأ: ' . $err];
    }

    $content = $decoded['choices'][0]['message']['content'];
    $parsed = json_decode($content, true);

    if (!$parsed || (!isset($parsed['action']) && !isset($parsed['actions']))) {
        return ['success' => false, 'reply' => 'ما قدرت افهم الرد. جرب صيغة الرسالة بشكل تاني.'];
    }

    return ['success' => true, 'parsed' => $parsed];
}

// تعليمات إضافية تُستخدم فقط لما نحلل صورة (حوالة بنكية / فاتورة شراء بضاعة)
function get_vision_extra_instructions() {
    return <<<PROMPT

مهم جداً - أنت الآن بتحلل صورة مرفقة (سكرين شوت حوالة بنكية، فاتورة/إيصال شراء بضاعة، أو صورة شيك ورقي)، وليس رسالة نصية عادية.

⚠️⚠️ قاعدة حاسمة تحكم كل شي تحت: أنت بتتصرف متل محاسب محترف بيراجع مستند مش واضح 100%، مش متل موظف بيخمّن ويكمل. أي حقل من الأربعة الحساسة التالية غير واضح بثقة كاملة من الصورة نفسها = **توقف واسأل**، ما تكمل بتخمين ولا بافتراضي:
  1) **البنك/الحساب** (paid_from_bank أو bank_name)
  2) **المبلغ** (amount)
  3) **اسم الطرف** (اسم العميل/المورد/الشخص المستفيد أو المُصدر)
  4) **رقم الشيك أو رقم/مرجع الحوالة** (check_number أو أي رقم مرجعي بالحوالة إن وجد)
ممنوع نهائياً استخدام بنك افتراضي ("jordan" أو غيره) لمجرد إنه مش واضح - هاي كانت قاعدة قديمة انلغت. بدل هيك دايماً استخدم action = "unclear" واسأل سؤال محدد ومباشر بصيغة تعطي خيارات واضحة، مش سؤال عام.

طريقة صياغة السؤال (مهم يكون بأسلوب محاسب محترف يراجع مستند، مو بس "مش واضح"):
- البنك: لو قدرت تقرأ جزء من الشعار/الاسم بس مش متأكد 100%، اسأل بالتحديد بصيغة اختيار: "الصورة مش واضحة تماماً لاسم البنك - هل هي [اسمك المرجّح] ولا بنك تاني (الأردني/الاتحاد/الإسلامي/دينارك/الاستثماري)؟". لو ما قدرت تقرأ شي إطلاقاً، اسأل: "ما قدرت أحدد اسم البنك من الصورة، من انو حساب/بنك كانت هاي الحركة بالضبط؟"
- المبلغ: لو رقم غير واضح تماماً أو فيه احتمال قراءة مزدوجة (مثلاً ممكن يكون 3000 أو 5000)، اسأل بالتحديد: "المبلغ مش واضح 100% بالصورة - هل هو [رقمك المرجّح] دينار ولا رقم تاني؟" ولا تسجل الحركة أبداً برقم أنت نفسك مش متأكد منه.
- اسم الطرف: لو الاسم مقصوص من الصورة أو غير مقروء بوضوح، اسأل: "ما قدرت أقرأ اسم [العميل/المورد/المستفيد] بوضوح بالصورة - مين بالضبط؟"
- رقم الشيك/رقم الحوالة: لو موجود بالصورة بس مش واضح (رقم مموّه أو مقصوص)، اسأل عنه صراحة بدل ما تسيبه فاضي أو تخترعه. لو مش موجود أصلاً بالصورة (بعض الحوالات ما فيها رقم مرجعي ظاهر)، خليه فاضي بدون ما تسأل - السؤال فقط لو الرقم موجود بس غير مقروء.

لو أكتر من حقل حساس مش واضح بنفس الصورة، اسألهم كلهم سوا برسالة وحدة مرتبة (مش عدة رسائل)، مثال: "الصورة مش واضحة كفاية، بس احتاج أتأكد من: 1) اسم البنك... 2) المبلغ... 3) اسم الزبون...".

الحقول التانية (التاريخ، اتجاه الحركة deposit/withdraw أو incoming/outgoing) تقدر تحدد بثقة عادية زي قبل - بس لو التاريخ نفسه غير واضح (خصوصاً السنة)، برضو اسأل بدل ما تخمن.

الآن التفاصيل حسب نوع المستند:

- إذا الصورة شيك ورقي (فيها شكل شيك تقليدي: اسم بنك بالأعلى، خانة "Pay Against This Cheque" أو "ادفعوا بموجب هذا الشيك"، خانة توقيع، رقم شيك، خانة مبلغ بالأرقام والحروف): استخدم action = "add_check" **حصراً** - ممنوع تسجلها كـ bank_transaction حتى لو فيها اسم بنك واضح بأعلى الصورة، لأنه شكل الشيك نفسه هو المحدد، مش الشعار.
  - direction: "incoming" لو المحل/المستخدم هو المستفيد المكتوب بخانة "To"/"لأمر"، أو "outgoing" لو المحل هو مُصدر الشيك (اسمه بخانة التوقيع/المُصدر). لو مش واضح مين المستفيد ومين المُصدر، اسأل.
  - party_name = الاسم المكتوب بخانة "To"/"لأمر" (المستفيد) بغض النظر عن الاتجاه. لو غير مقروء بوضوح، اسأل عنه (قاعدة الحقول الحساسة فوق).
  - amount = المبلغ بالأرقام (خانة "دينار"/"J.D"), وتأكد يطابق المبلغ المكتوب بالحروف تحته - لو فيه تعارض بين الرقمي والكتابي، أو أي التباس بقراءة الرقم، استخدم "unclear" واسأل بالتحديد شو الرقمين المحتملين.
  - due_date = التاريخ المكتوب بخانة "Date"/"التاريخ" محوّل لصيغة YYYY-MM-DD. لو السنة مش واضحة بالصورة، استخدم "unclear" واسأل عن السنة بدل ما تخمنها.
  - bank_name = اسم البنك المكتوب بأعلى الشيك (jordan_personal/jordan_business/etihad/islami/dinarak/investment - أقرب تطابق). لو الشيك من "بنك الأردني" وما تحدد إذا هو حساب مؤسسة ولا شخصي (شيكات الأفراد نادراً بتوضح هيك من شكل الشيك نفسه)، اسأل "بنك الأردني مؤسسة ولا شخصي؟" - ما تفترض. لو اسم البنك عموماً غير واضح، اسأل (قاعدة الحقول الحساسة فوق) - ما تخمّن.
  - check_number = رقم الشيك لو ظاهر وواضح بالصورة. لو موجود بس مش مقروء بوضوح، اسأل عنه. لو مش ظاهر أصلاً بالصورة، خليه فاضي بدون سؤال.

- إذا الصورة سكرين شوت تحويل بنكي أو إشعار إيداع/سحب (من تطبيق بنك أو محفظة إلكترونية، مش شيك ورقي): استخدم action = "bank_transaction".
  - حدد اسم البنك من شعار/اسم التطبيق بالصورة إن أمكن، أو من اسم البنك يلي ذكره المستخدم بأي رسالة سابقة بنفس المحادثة (اعتمده حتى لو ما تطابق مع كود SWIFT/IBAN الظاهر بالصورة - هذا طبيعي وليس تناقضاً). إذا ما قدرت تحدده بثقة كاملة من أي مصدر، **لا تفترض أي بنك افتراضي** - استخدم "unclear" واسأل بالتحديد (قاعدة الحقول الحساسة فوق).
  - حدد tx_type: "deposit" لو الحوالة واردة (استلمنا فلوس)، "withdraw" لو صادرة لمستفيد (حولنا فلوس). لو الاتجاه نفسه ملتبس، اسأل.
  - amount = قيمة "المجموع الكلي" (أو Total) إن وجدت بالصورة، وليس قيمة "الرسوم". لو الرقم مش واضح بثقة كاملة، اسأل بالتحديد شو الاحتمالين. اقرأ التاريخ من الصورة بدقة وحوّله لصيغة YYYY-MM-DD - لو غير واضح اسأل.
  - لا تستخدم "unclear" لمجرد إنه كود SWIFT/IBAN ما بيطابق اسم البنك المذكور - هذا فرق طبيعي وليس سبب للسؤال. اسأل فقط لو اسم البنك نفسه (مش الكود) غير واضح.
  - اسم الطرف الآخر بالحوالة (المستفيد أو المُرسل) لو موجود بالصورة بس غير مقروء بوضوح، اسأل عنه (قاعدة الحقول الحساسة فوق).

- إذا الصورة فاتورة أو إيصال شراء بضاعة شخصية أو بضاعة للمحل من مورد: استخدم action = "supplier_transaction" (type: "debit") لو واضح اسم المورد/المحل، أو action = "expense" (category: "expense") لو مصروف عام ما إله مورد محدد. لو اسم المورد أو المبلغ الإجمالي مش واضح بثقة، اسأل بدل ما تخمّن.

- لو الصورة مش واضحة أو مش متعلقة بحوالة بنكية أو فاتورة شراء إطلاقاً، استخدم action = "unclear" واشرح بالـ reply انك ما قدرت تفهم الصورة.
- لا تخترع أرقام أو أسماء مش موجودة فعلياً بالصورة. أي حقل حساس (بنك/مبلغ/اسم/رقم مرجعي) غير مقروء بثقة كاملة = سؤال محدد بدل تخمين، دايماً وبدون استثناء.
PROMPT;
}

function call_openai_vision($image_data_url, $caption, $conversation_history = []) {
    if (!defined('OPENAI_API_KEY') || OPENAI_API_KEY === '') {
        return [
            'success' => false,
            'reply' => 'ما تم ربط مفتاح OpenAI API بعد. أضف مفتاحك بملف config/config.php بالسطر OPENAI_API_KEY حتى يشتغل تحليل الصور.',
        ];
    }

    $system_prompt = get_system_prompt() . get_vision_extra_instructions();

    $user_content = [
        ['type' => 'text', 'text' => $caption !== '' ? $caption : 'حلل هاي الصورة وسجل الحركة المناسبة (حوالة بنكية، فاتورة شراء بضاعة، أو شيك).'],
        ['type' => 'image_url', 'image_url' => ['url' => $image_data_url]],
    ];

    $messages = array_merge(
        [['role' => 'system', 'content' => $system_prompt]],
        $conversation_history,
        [['role' => 'user', 'content' => $user_content]]
    );

    $payload = [
        'model' => OPENAI_VISION_MODEL,
        'messages' => $messages,
        'temperature' => 0.1,
        'response_format' => ['type' => 'json_object'],
    ];

    $ch = curl_init('https://api.openai.com/v1/chat/completions');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'Authorization: Bearer ' . OPENAI_API_KEY,
        ],
        CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
        CURLOPT_TIMEOUT => 45,
    ]);
    $response = curl_exec($ch);
    $curl_error = curl_error($ch);
    curl_close($ch);

    if ($curl_error) {
        return ['success' => false, 'reply' => 'صار خطأ بالاتصال مع OpenAI: ' . $curl_error];
    }

    $decoded = json_decode($response, true);
    if (!isset($decoded['choices'][0]['message']['content'])) {
        $err = $decoded['error']['message'] ?? 'رد غير متوقع من OpenAI';
        return ['success' => false, 'reply' => 'خطأ: ' . $err];
    }

    $content = $decoded['choices'][0]['message']['content'];
    $parsed = json_decode($content, true);

    if (!$parsed || !isset($parsed['action'])) {
        return ['success' => false, 'reply' => 'ما قدرت افهم محتوى الصورة. جرب صورة أوضح.'];
    }

    return ['success' => true, 'parsed' => $parsed];
}

/**
 * تحويل رسالة صوتية (Voice note) لنص عبر Whisper API
 * $audio_binary: المحتوى الخام للملف الصوتي (من wa_download_media مثلاً)
 * بترجع: ['success' => true, 'text' => '...'] أو ['success' => false, 'reply' => '...']
 */
function call_openai_transcribe($audio_binary, $mime_type = 'audio/ogg') {
    if (!defined('OPENAI_API_KEY') || OPENAI_API_KEY === '') {
        return ['success' => false, 'reply' => 'ما تم ربط مفتاح OpenAI API بعد.'];
    }

    // Whisper بده اسم ملف بامتداد واضح حتى يتعرف على الصيغة - نكتب الملف مؤقتاً بامتداد مناسب
    $ext = match (true) {
        str_contains($mime_type, 'ogg') => 'ogg',
        str_contains($mime_type, 'mp4') => 'mp4',
        str_contains($mime_type, 'mpeg'), str_contains($mime_type, 'mp3') => 'mp3',
        str_contains($mime_type, 'wav') => 'wav',
        str_contains($mime_type, 'webm') => 'webm',
        default => 'ogg',
    };
    $tmp_path = sys_get_temp_dir() . '/wa_voice_' . uniqid() . '.' . $ext;
    file_put_contents($tmp_path, $audio_binary);

    $ch = curl_init('https://api.openai.com/v1/audio/transcriptions');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . OPENAI_API_KEY],
        CURLOPT_POSTFIELDS => [
            'file' => new CURLFile($tmp_path, $mime_type, 'voice.' . $ext),
            'model' => defined('OPENAI_WHISPER_MODEL') ? OPENAI_WHISPER_MODEL : 'whisper-1',
            'language' => 'ar',
        ],
        CURLOPT_TIMEOUT => 60,
    ]);
    $response = curl_exec($ch);
    $curl_error = curl_error($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    @unlink($tmp_path);

    if ($curl_error) {
        return ['success' => false, 'reply' => 'صار خطأ بالاتصال مع Whisper: ' . $curl_error];
    }

    $decoded = json_decode($response, true);
    if ($http_code >= 400 || !isset($decoded['text'])) {
        $err = $decoded['error']['message'] ?? 'رد غير متوقع من Whisper';
        return ['success' => false, 'reply' => 'ما قدرت افهم الرسالة الصوتية: ' . $err];
    }

    $text = trim($decoded['text']);
    if ($text === '') {
        return ['success' => false, 'reply' => 'ما سمعت أي كلام واضح بالتسجيل، جرب سجل مرة ثانية بمكان أهدأ.'];
    }

    return ['success' => true, 'text' => $text];
}

// =====================================================================
// دوال مشتركة بين api/chat.php (نص) و api/chat_image.php (صورة)
// =====================================================================

function log_chat_action($db, $user_id, $message, $parsed, $exec_result) {
    $status = $exec_result['success'] === null ? 'needs_clarification' : ($exec_result['success'] ? 'success' : 'failed');
    $stmt = $db->prepare('INSERT INTO chat_log (user_id, user_message, parsed_action, bot_reply, status, entity_table, entity_id) VALUES (?,?,?,?,?,?,?)');
    $stmt->execute([
        $user_id,
        $message,
        json_encode($parsed, JSON_UNESCAPED_UNICODE),
        $parsed['reply'] ?? '',
        $status,
        $exec_result['entity_table'] ?? null,
        $exec_result['entity_id'] ?? null,
    ]);
}

// بيبني ملخص واضح بالعربي للعملية قبل ما تنفذ، عشان المستخدم يتأكد منه
function build_action_summary($action, $d) {
    // نفس الحماية: ما نعرض قيمة حساب غير صحيحة بمعاينة التأكيد
    if (isset($d['paid_from_bank'])) {
        $valid_banks = ['jordan','jordan_personal','jordan_business','etihad','islami','dinarak','investment','cash'];
        if (!in_array($d['paid_from_bank'], $valid_banks, true)) {
            $d['paid_from_bank'] = null;
        }
    }
    switch ($action) {
        case 'customer_transaction':
            $type = ($d['type'] ?? '') === 'debit' ? 'مدين (أخذ/عليه)' : 'دائن (دفع/سدد)';
            $src = !empty($d['paid_from_bank']) ? " | من: {$d['paid_from_bank']}" : '';
            return "عميل: {$d['customer_name']} | {$type} | مبلغ: {$d['amount']}{$src} | {$d['description']}";
        case 'supplier_transaction':
            $type = ($d['type'] ?? '') === 'debit' ? 'مدين (استلمنا ولسا ما دفعنا)' : 'دائن (دفعنا)';
            $src = !empty($d['paid_from_bank']) ? " | من: {$d['paid_from_bank']}" : '';
            return "مورد: {$d['supplier_name']} | {$type} | مبلغ: {$d['amount']}{$src} | {$d['description']}";
        case 'personal_transaction':
            $type = ($d['type'] ?? '') === 'lend' ? 'سلفة أعطيناها' : 'تسديد رجع لنا';
            $src = !empty($d['paid_from_bank']) ? " | من: {$d['paid_from_bank']}" : '';
            return "شخص: {$d['person_name']} | {$type} | مبلغ: {$d['amount']}{$src} | {$d['description']}";
        case 'profit_distribution':
            $src = !empty($d['paid_from_bank']) ? " | من: {$d['paid_from_bank']}" : '';
            return "توزيع أرباح لـ: {$d['shareholder_name']} | مبلغ: {$d['amount']}{$src} | فترة: {$d['period_label']}";
        case 'shareholder_contribution':
            $src = !empty($d['paid_from_bank']) ? " | دخلت لـ: {$d['paid_from_bank']}" : '';
            return "مساهمة/إضافة فلوس من: {$d['shareholder_name']} | مبلغ: {$d['amount']}{$src} | {$d['description']}";
        case 'expense':
            return "مصروف ({$d['category']}) | مبلغ: {$d['amount']} | من: " . ($d['paid_from_bank'] ?? 'كاش') . " | {$d['description']}";
        case 'external_revenue':
            $recv = !empty($d['paid_from_bank']) ? " | دخلت لـ: {$d['paid_from_bank']}" : '';
            return "إيراد خارجي | المصدر: " . ($d['source_person'] ?? 'رمزي') . " | مبلغ: {$d['amount']}{$recv} | {$d['description']}";
        case 'bank_transaction':
            return "بنك: {$d['bank']} | " . ($d['tx_type'] === 'deposit' ? 'إيداع' : 'سحب') . " | مبلغ: {$d['amount']} | {$d['description']}";
        case 'add_check':
            return "شيك " . ($d['direction'] === 'incoming' ? 'وارد' : 'صادر') . " | {$d['party_name']} | مبلغ: {$d['amount']} | استحقاق: {$d['due_date']}";
        case 'employee_transaction':
            $type_labels = ['salary' => 'استحقاق راتب', 'advance' => 'سلفة', 'deduction' => 'خصم', 'bonus' => 'مكافأة', 'payment' => 'دفع راتب مستحق'];
            $type = $type_labels[$d['type'] ?? ''] ?? ($d['type'] ?? '');
            $src = !empty($d['paid_from_bank']) ? " | من: {$d['paid_from_bank']}" : '';
            return "موظف: {$d['employee_name']} | {$type} | مبلغ: {$d['amount']}{$src} | {$d['description']}";
        case 'car_employee_transaction':
            $type_labels2 = ['revenue' => 'تحصيل', 'expense' => 'مصروف سيارة', 'advance' => 'سلفة', 'deduction' => 'خصم', 'ads' => 'إعلانات', 'fuel' => 'محروقات', 'parts' => 'قطع و صيانة لوحات', 'vehicle_maintenance' => 'صيانة مركبة', 'secretary_salary' => 'حصة راتب سكرتارية'];
            $type2 = $type_labels2[$d['type'] ?? ''] ?? ($d['type'] ?? '');
            $src2 = !empty($d['paid_from_bank']) ? " | من: {$d['paid_from_bank']}" : '';
            return "سائق: {$d['car_employee_name']} | {$type2} | مبلغ: {$d['amount']}{$src2} | {$d['description']}";
        case 'workshop_transaction':
            $type_labels3 = ['revenue' => 'إيراد مشغل', 'expense' => 'مصاريف مشغل'];
            $type3 = $type_labels3[$d['type'] ?? ''] ?? ($d['type'] ?? '');
            $src3 = !empty($d['paid_from_bank']) ? " | من: {$d['paid_from_bank']}" : '';
            return "مشغل | {$type3} | مبلغ: {$d['amount']}{$src3} | {$d['description']}";
        default:
            return 'عملية جديدة: ' . json_encode($d, JSON_UNESCAPED_UNICODE);
    }
}

// بيطبق تصحيح على آخر عملية سجلها المستخدم (مثلاً "لا قصدي 300 مش 200")
function apply_correction_to_last($db, $user_id, $correction) {
    $stmt = $db->prepare("SELECT * FROM chat_log WHERE user_id = ? AND status = 'success' AND entity_table IS NOT NULL AND undone = 0 ORDER BY id DESC LIMIT 1");
    $stmt->execute([$user_id]);
    $last = $stmt->fetch();

    if (!$last) {
        return ['success' => false, 'message' => 'ما لقيت عملية سابقة أصححها'];
    }

    $field = $correction['field'] ?? null;
    $value = $correction['new_value'] ?? null;
    if (!$field || $value === null) {
        return ['success' => false, 'message' => 'ما وضح شو بالضبط بدك تصحح'];
    }

    $old_parsed = json_decode($last['parsed_action'], true);
    $data = $old_parsed['data'] ?? [];
    $data[$field] = $value;

    $undo = undo_entity($last['entity_table'], $last['entity_id']);
    if (!$undo['success']) {
        return ['success' => false, 'message' => 'تعذر تصحيح العملية القديمة: ' . $undo['message']];
    }
    $db->prepare('UPDATE chat_log SET undone = 1 WHERE id = ?')->execute([$last['id']]);

    return execute_ai_action(['action' => $old_parsed['action'], 'data' => $data], $user_id);
}

// بياخد $parsed (نتيجة تحليل نص أو صورة) وبيقرر: ينفذ فوراً (استعلام/غير واضح)
// أو يخزنه كـ"عملية معلّقة" بانتظار تأكيد المستخدم. مشترك بين مسار النص ومسار الصورة.
// فحص أمان: يعدّ كلمات الأفعال المحاسبية بالرسالة (سدد، دفع، سحب، اشترى...) كتقدير
// تقريبي لعدد العمليات المفروض تكون بالرسالة، حتى نكتشف لو الموديل "فوّت" عملية
function count_likely_action_verbs($message) {
    $verbs = ['سدد', 'دفع', 'سحب', 'حول', 'اشتريت', 'اشترينا', 'استلمنا', 'استلمت', 'وزعت',
              'صرفت', 'صرفنا', 'أعطيت', 'اعطيت', 'خصمنا', 'راتب', 'سلفة', 'شريت', 'بعنا', 'بعت',
              'حصّل', 'حصل', 'جمع'];
    $count = 0;
    $found = [];
    foreach ($verbs as $v) {
        $c = substr_count($message, $v);
        if ($c > 0 && !in_array($v, $found, true)) {
            // نتجنب عدّ نفس الفعل مرتين لو تكرر بصيغتين قريبتين (مثل صرفت/صرفنا)
            $found[] = $v;
            $count += $c;
        }
    }
    return $count;
}

// بيتعامل مع رسالة فيها أكتر من عملية بنفس الوقت (مصفوفة "actions")
// يفصل العمليات إلى: يلي بتنفذ فوراً (استعلامات) ويلي بتحتاج تأكيد المستخدم (تسجيل حركات)
function handle_multi_actions($parsed, $user, $db, $message_for_log) {
    // حد أقصى صارم: أكتر من 4 عمليات بنفس الرسالة مرفوض تماماً، لتقليل احتمال خطأ/تفويت
    if (count($parsed['actions']) > 4) {
        return [
            'success' => false,
            'reply' => 'رسالتك فيها أكتر من 4 عمليات بنفس الوقت، وهذا كتير بمرة وحدة. قسّمها لرسالتين أو أكتر (بحد أقصى 4 عمليات بكل رسالة) حتى نضمن التسجيل الصحيح.',
        ];
    }

    $no_confirmation_needed = ['query_overview', 'query_upcoming_checks', 'query_entity', 'query_attachment', 'unclear', 'correct_last', 'undo_last'];
    $immediate_results = [];
    $pending_actions = [];
    $pending_summaries = [];

    foreach ($parsed['actions'] as $item) {
        $item = fix_customer_supplier_confusion($item, $message_for_log);
        $item = fix_entity_table_by_history($item, $message_for_log);
        $item = auto_fill_goods_return_reason($item, $message_for_log);
        if (missing_required_bank($item['action'] ?? '', $item['data'] ?? [])) {
            $item['action'] = 'unclear';
            $item['data'] = ['reason' => 'من أي حساب أو كاش صارت هالحركة؟ حدد البنك أو اكتب "كاش".'];
        }
        $item_action = $item['action'] ?? 'unclear';
        if (in_array($item_action, $no_confirmation_needed, true)) {
            $exec = execute_ai_action($item, $user['id']);
            $immediate_results[] = ['action' => $item_action, 'result' => $exec];
        } else {
            $pending_actions[] = $item;
            $pending_summaries[] = build_action_summary($item_action, $item['data'] ?? []);
        }
    }

    // ما في ولا عملية تحتاج تأكيد (كلها استعلامات/أو حالات "غير واضح") -> نرجع النتائج فوراً
    if (empty($pending_actions)) {
        $all_ok = true;
        foreach ($immediate_results as $r) { if (empty($r['result']['success'])) { $all_ok = false; break; } }
        $combined_message = implode(' | ', array_map(fn($r) => $r['result']['message'] ?? '', $immediate_results));
        log_chat_action($db, $user['id'], $message_for_log, $parsed, ['success' => $all_ok, 'message' => $combined_message]);
        return [
            'success' => $all_ok,
            'reply' => $all_ok ? ($parsed['reply'] ?? $combined_message) : $combined_message,
            'details' => ['multi_immediate' => $immediate_results],
        ];
    }

    // في عمليات لازم تأكيد -> نخزنهم مع بعض كـ"عملية معلّقة" واحدة، ونعرض ملخص مرقّم
    $count = count($pending_actions);
    $summary_lines = [];
    foreach ($pending_summaries as $i => $s) {
        $summary_lines[] = ($i + 1) . ") $s";
    }
    $full_summary = "لقيت $count عمليات:\n" . implode("\n", $summary_lines);

    // فحص أمان: قارن عدد الأفعال المحاسبية بالرسالة الأصلية مع عدد العمليات يلي فهمتها -
    // لو الرسالة فيها أفعال أكتر بوضوح، حذّر المستخدم يراجع قبل التأكيد (يمكن فاتت عملية)
    $total_understood = $count + count($immediate_results);
    $likely_verbs = count_likely_action_verbs($message_for_log);
    $mismatch_warning = '';
    if ($likely_verbs > $total_understood) {
        $mismatch_warning = "\n\n⚠️ تنبيه: رسالتك فيها إشارات لعمليات أكتر مما فهمته ({$likely_verbs} مقابل {$total_understood}) - راجع الملخص فوق منيح، ممكن فاتتني عملية. لو ناقص شي، اكتبه لحاله بعد ما تأكد الباقي.";
    }

    $stmt = $db->prepare('INSERT INTO chat_pending_actions (user_id, action_json, summary) VALUES (?,?,?)');
    $stmt->execute([$user['id'], json_encode(['actions' => $pending_actions], JSON_UNESCAPED_UNICODE), $full_summary]);
    $pending_id = $db->lastInsertId();

    log_chat_action($db, $user['id'], $message_for_log, $parsed, ['success' => null, 'message' => 'بانتظار التأكيد - عمليات متعددة']);

    return [
        'success' => true,
        'needs_confirmation' => true,
        'pending_id' => $pending_id,
        'reply' => "$full_summary$mismatch_warning\n\nأكد التسجيل؟ اكتب \"نعم\" للتأكيد.",
    ];
}

// حماية إضافية حاسمة: لو الرسالة فيها كلمة "عميل/زبون" أو "مورد" صراحة، هاي أقوى من أي
// تخمين للموديل بالكلمات (زي "بضاعة"/"أخذ") - نفرض التصحيح هون بغض النظر شو رجع الموديل.
// $item هون هو مصفوفة إجراء وحدة (فيها action و data)، منستخدمها لكل من الرسالة المفردة والدفعة.
function fix_customer_supplier_confusion($item, $message_for_log) {
    if (!in_array($item['action'] ?? '', ['customer_transaction', 'supplier_transaction'], true)) {
        return $item;
    }
    $has_customer_word = (mb_strpos($message_for_log, 'عميل') !== false) || (mb_strpos($message_for_log, 'زبون') !== false) || (mb_strpos($message_for_log, 'الزباين') !== false);
    $has_supplier_word = (mb_strpos($message_for_log, 'مورد') !== false);

    if ($has_customer_word && !$has_supplier_word && $item['action'] === 'supplier_transaction') {
        $item['action'] = 'customer_transaction';
        $item['data']['customer_name'] = $item['data']['supplier_name'] ?? ($item['data']['customer_name'] ?? '');
        unset($item['data']['supplier_name']);
    } elseif ($has_supplier_word && !$has_customer_word && $item['action'] === 'customer_transaction') {
        $item['action'] = 'supplier_transaction';
        $item['data']['supplier_name'] = $item['data']['customer_name'] ?? ($item['data']['supplier_name'] ?? '');
        unset($item['data']['customer_name']);
    }
    return $item;
}

// حماية حاسمة: أي إجراء بمعناه المحاسبي دايماً بيحرك فلوس فعلية (سلفة/تسديد شخصي، توزيع أرباح،
// تسديد عميل/مورد) لازم يكون معه paid_from_bank محدد، وإلا نوقف العملية *قبل* ما توصل لمرحلة
// "أكد التسجيل" ونسأل مباشرة - بدل ما نخلي المستخدم يأكد عملية مكتوب عليها فشل مسبقاً.
// كشف مباشر من نص الرسالة (مش معتمد على فهم الموديل للحقل التقني no_bank_reason):
// لو الكلام فيه "بضاعة" + كلمة ترجيع ("مرتجع"/"رجعنا"/"رجّعنا"/"رجعت")، هاي حركة بضاعة راجعة
// بدون فلوس فعلياً - نعبّي no_bank_reason تلقائياً حتى ما يوقف يسأل عن بنك مش موجود أصلاً.
function auto_fill_goods_return_reason($item, $message_for_log) {
    if (!in_array($item['action'] ?? '', ['customer_transaction', 'supplier_transaction', 'personal_transaction'], true)) return $item;
    if (!empty($item['data']['paid_from_bank'])) return $item;

    // حالة "مسامحة/إسقاط دين" شخصي - بدون فلوس فعلياً كمان، نفس منطق مرتجع البضاعة تماماً
    if (($item['action'] ?? '') === 'personal_transaction') {
        $has_forgive = (mb_strpos($message_for_log, 'مسامح') !== false) || (mb_strpos($message_for_log, 'اسقاط') !== false)
            || (mb_strpos($message_for_log, 'إسقاط') !== false) || (mb_strpos($message_for_log, 'تنازل') !== false)
            || (mb_strpos($message_for_log, 'شطب') !== false);
        if ($has_forgive) {
            $item['data']['type'] = 'repay';
            if (empty($item['data']['no_bank_reason'])) {
                $item['data']['no_bank_reason'] = 'مسامحة/إسقاط دين - بدون حركة نقدية';
            }
        }
        return $item;
    }

    $has_goods = mb_strpos($message_for_log, 'بضاع') !== false;
    $has_return = (mb_strpos($message_for_log, 'مرتجع') !== false) || (mb_strpos($message_for_log, 'رجعنا') !== false)
        || (mb_strpos($message_for_log, 'رجّعنا') !== false) || (mb_strpos($message_for_log, 'رجعت') !== false)
        || (mb_strpos($message_for_log, 'استرجعنا') !== false) || (mb_strpos($message_for_log, 'راجعين') !== false);

    if ($has_goods && $has_return) {
        // إرجاع بضاعة دايماً بينقص الدين (زي دفعة) - نفرضها credit بغض النظر شو خمّن الموديل
        $item['data']['type'] = 'credit';
        if (empty($item['data']['no_bank_reason'])) {
            $item['data']['no_bank_reason'] = 'مرتجع بضاعة - بدون حركة نقدية';
        }
    }
    return $item;
}

function missing_required_bank($action, $data) {
    $bank = trim((string)($data['paid_from_bank'] ?? ''));
    $reason = trim((string)($data['no_bank_reason'] ?? ''));
    if ($bank !== '' || $reason !== '') return false;
    switch ($action) {
        case 'personal_transaction':
            return in_array($data['type'] ?? '', ['lend', 'repay'], true);
        case 'profit_distribution':
            return true;
        case 'shareholder_contribution':
            return true;
        case 'external_revenue':
            return true;
        case 'customer_transaction':
            return ($data['type'] ?? '') === 'credit';
        case 'supplier_transaction':
            return ($data['type'] ?? '') === 'credit';
        case 'employee_transaction':
            return in_array($data['type'] ?? '', ['advance', 'payment'], true);
        case 'car_employee_transaction':
            return in_array($data['type'] ?? '', ['advance', 'ads', 'bonus', 'fuel', 'parts', 'vehicle_maintenance'], true);
        case 'workshop_transaction':
            return ($data['type'] ?? '') === 'expense';
        default:
            return false;
    }
}

// حماية أذكى من فحص الكلمات: نستخدم قاعدة البيانات نفسها كمرجع. لو الاسم يلي استخرجه
// الموديل موجود أصلاً بجدول واحد بالضبط من (عملاء/موردين/شخصي) ومختلف عن تصنيف الموديل،
// نصحح على أساس الواقع الموجود. لو نفس الاسم موجود بأكتر من جدول بنفس الوقت (نفس الشخص
// عميل ومورد وشخصي مع بعض - حالة حقيقية وارِدة) فما بنخمّن إطلاقاً مهما كانت الكلمات،
// لأنه أي تخمين ممكن يسجل حركة على الحساب الغلط بدون ما حدا ينتبه - نوقف ونسأل دايماً.
function fix_entity_table_by_history($item, $message_for_log) {
    $map = [
        'customer_transaction' => ['field' => 'customer_name', 'table' => 'customers', 'label' => 'عميل'],
        'supplier_transaction' => ['field' => 'supplier_name', 'table' => 'suppliers', 'label' => 'مورد'],
        'personal_transaction' => ['field' => 'person_name', 'table' => 'personal_accounts', 'label' => 'حساب شخصي'],
        'employee_transaction' => ['field' => 'employee_name', 'table' => 'employees', 'label' => 'موظف'],
        'car_employee_transaction' => ['field' => 'car_employee_name', 'table' => 'car_employees', 'label' => 'سائق'],
    ];
    // الجداول اللي منقدر نتحقق منها بقاعدة البيانات ونصحح عليها تلقائياً (عميل/مورد/شخصي فقط -
    // موظف/سائق مستبعدين من فحص "أكتر من جدول" لأنه لهم منطق عمل مختلف تماماً عن سلفة شخصية عادية،
    // بس هني برضه أهداف صحيحة لو المستخدم صرّح بالكلمة أو الاسم موجود بجدولهم بس).
    $db_checkable = ['customer_transaction', 'supplier_transaction', 'personal_transaction', 'employee_transaction', 'car_employee_transaction'];

    $action = $item['action'] ?? '';
    if (!isset($map[$action])) return $item;

    // نلاقي اسم الجهة أياً كان الحقل المستخدم حالياً بالبيانات
    $name = '';
    foreach ($map as $info) {
        if (!empty($item['data'][$info['field']])) { $name = trim($item['data'][$info['field']]); break; }
    }
    if ($name === '') return $item;

    // كلمة صريحة بالرسالة أقوى من أي شي - بتفرض التحويل حتى لو الموديل أصلاً حطها موظف/سائق
    $forced_action = null;
    if ((mb_strpos($message_for_log, 'عميل') !== false) || (mb_strpos($message_for_log, 'زبون') !== false) || (mb_strpos($message_for_log, 'الزباين') !== false)) {
        $forced_action = 'customer_transaction';
    } elseif (mb_strpos($message_for_log, 'مورد') !== false) {
        $forced_action = 'supplier_transaction';
    } elseif (mb_strpos($message_for_log, 'شخص') !== false) {
        $forced_action = 'personal_transaction';
    } elseif (mb_strpos($message_for_log, 'موظف') !== false) {
        $forced_action = 'employee_transaction';
    } elseif ((mb_strpos($message_for_log, 'سائق') !== false) || (mb_strpos($message_for_log, 'شوفير') !== false)) {
        $forced_action = 'car_employee_transaction';
    }

    if ($forced_action !== null) {
        return switch_entity_action($item, $action, $forced_action, $name, $map);
    }

    // بدون كلمة صريحة: نتحقق من قاعدة البيانات بس للجداول الثلاثة (عميل/مورد/شخصي) -
    // ما منلمس موظف/سائق هون لأنه لو الموديل أصلاً حطها موظف وهو فعلاً موظف عندك، ما في داعي نغيّرها.
    if (!in_array($action, $db_checkable, true)) return $item;

    $db = get_db();
    $normalized_name = normalize_name_for_match($name);
    $found_in = [];
    foreach ($map as $act => $info) {
        if (!in_array($act, $db_checkable, true)) continue;
        $stmt = $db->prepare("SELECT id FROM {$info['table']} WHERE REPLACE(name, 'ة', 'ه') = ? LIMIT 1");
        $stmt->execute([$normalized_name]);
        if ($stmt->fetch()) $found_in[] = $act;
    }

    // نفس الاسم موجود كمان بجدول المساهمين؟ (شوفولاند منفصل عن $map لأنه أكشناته shareholder_contribution/profit_distribution
    // مختلفة بالبنية عن باقي الجداول، فما بنقدر نبدّل action تلقائياً - بس لازم ننبّه لو في تعارض)
    $stmt_sh = $db->prepare("SELECT id FROM shareholders WHERE REPLACE(name, 'ة', 'ه') = ? LIMIT 1");
    $stmt_sh->execute([$normalized_name]);
    $is_also_shareholder = (bool)$stmt_sh->fetch();
    if ($is_also_shareholder && !in_array($action, ['shareholder_contribution', 'profit_distribution'], true)) {
        $found_in[] = '__shareholder__';
    }

    // نفس الاسم موجود بأكتر من قسم بنفس الوقت -> ممنوع نخمّن، نوقف ونسأل بالتحديد
    if (count($found_in) > 1) {
        $labels = array_map(fn($a) => $a === '__shareholder__' ? 'مساهم' : $map[$a]['label'], $found_in);
        $item['action'] = 'unclear';
        $item['data'] = ['reason' => "\"$name\" عندك مسجل كـ" . implode(' و', $labels) . " بنفس الوقت. هاي الحركة على حساب مين بالضبط؟ اكتب مثلاً \"العميل $name\" أو \"المورد $name\" أو \"الموظف $name\" أو \"السائق $name\" أو \"المساهم $name\"."];
        return $item;
    }

    if (count($found_in) === 1 && $found_in[0] !== $action) {
        return switch_entity_action($item, $action, $found_in[0], $name, $map);
    }
    return $item;
}

// 'out' = فلوس/سلفة طلعت منا لهاد الشخص | 'in' = فلوس رجعت/دخلت لنا منه (تسديد/تحصيل)
function entity_type_direction($action, $type) {
    $out_types = ['debit', 'lend', 'advance', 'ads', 'salary', 'expense'];
    return in_array($type, $out_types, true) ? 'out' : 'in';
}

function entity_type_from_direction($action, $direction) {
    switch ($action) {
        case 'customer_transaction':
        case 'supplier_transaction':
            return $direction === 'out' ? 'debit' : 'credit';
        case 'personal_transaction':
            return $direction === 'out' ? 'lend' : 'repay';
        case 'employee_transaction':
            return $direction === 'out' ? 'advance' : 'deduction';
        case 'car_employee_transaction':
            return $direction === 'out' ? 'advance' : 'revenue';
        default:
            return $direction === 'out' ? 'debit' : 'credit';
    }
}

// يبدّل action لجهة تانية (عميل/مورد/شخصي/موظف/سائق) مع تحويل اسم الحقل ونوع الحركة
function switch_entity_action($item, $old_action, $new_action, $name, $map) {
    if ($old_action === $new_action) return $item;
    foreach ($map as $info) { unset($item['data'][$info['field']]); }
    $item['data'][$map[$new_action]['field']] = $name;

    if (isset($item['data']['type'])) {
        $direction = entity_type_direction($old_action, $item['data']['type']); // 'out' فلوس طلعت منا | 'in' فلوس/تسديد رجع لنا
        $item['data']['type'] = entity_type_from_direction($new_action, $direction);
    }
    $item['action'] = $new_action;
    return $item;
}

function handle_parsed_ai_action($parsed, $user, $db, $message_for_log) {
    // لو الموديل رجع أكتر من عملية بنفس الرسالة (مصفوفة "actions")، نحوّلها لمسار خاص منفصل
    if (isset($parsed['actions']) && is_array($parsed['actions'])) {
        return handle_multi_actions($parsed, $user, $db, $message_for_log);
    }

    $parsed = fix_customer_supplier_confusion($parsed, $message_for_log);
    $parsed = fix_entity_table_by_history($parsed, $message_for_log);
    $parsed = auto_fill_goods_return_reason($parsed, $message_for_log);
    if (missing_required_bank($parsed['action'] ?? '', $parsed['data'] ?? [])) {
        $parsed['action'] = 'unclear';
        $parsed['data'] = ['reason' => 'من أي حساب أو كاش صارت هالحركة؟ حدد البنك أو اكتب "كاش".'];
        $parsed['reply'] = $parsed['data']['reason'];
    }

    $action = $parsed['action'] ?? 'unclear';
    $no_confirmation_needed = ['query_overview', 'query_upcoming_checks', 'query_entity', 'query_attachment', 'unclear', 'correct_last', 'undo_last'];

    // حماية إضافية: ما نعتمد على الذكاء الاصطناعي وحده لتحديد "focus" - نفحص كلمات
    // مفتاحية برسالة المستخدم نفسها كطبقة أكيدة (deterministic) بغض النظر شو رجع الموديل
    if ($action === 'query_overview' && empty($parsed['data']['focus'])) {
        $keyword_map = [
            'bank_jordan'     => ['الأردني', 'بنك الاردني', 'البنك الاردني'],
            'bank_etihad'     => ['الاتحاد', 'اتحاد'],
            'bank_islami'     => ['الإسلامي', 'الاسلامي'],
            'bank_dinarak'    => ['دينارك'],
            'bank_investment' => ['الاستثماري', 'استثماري'],
            'cash'            => ['الكاش', 'كاش', 'الصندوق'],
            'customers'       => ['العملاء', 'الزباين'],
            'suppliers'       => ['الموردين', 'الموردون'],
            'personal'        => ['الشخصي', 'حسابي الشخصي'],
            'employees'       => ['الموظفين', 'الموظفون'],
            'car_employees'   => ['السائقين', 'السواقين'],
        ];
        foreach ($keyword_map as $focus_value => $keywords) {
            foreach ($keywords as $kw) {
                if (mb_strpos($message_for_log, $kw) !== false) {
                    $parsed['data']['focus'] = $focus_value;
                    break 2;
                }
            }
        }
    }

    // حماية إضافية ثانية: لو رد الموديل بجملة "وعد بدون تنفيذ" (سأتحقق/سأتأكد...) بدل ما ينفذ فعلياً
    // استعلام عن جهة معينة، نكتشف الجهة والاسم بأنفسنا من رسالة المستخدم ونجبر تنفيذ query_entity حقيقي
    // نطبقها بحالتين: (1) الموديل رد بوعد فاضي بدون تنفيذ، أو (2) الموديل اختار query_entity صح بس رجع اسم فاضي/ناقص
    $placeholder_signals = ['سأتحقق', 'سأتأكد', 'رح أتحقق', 'رح أشوف', 'لحظة', 'دقيقة وبفحص', 'خليني أشوف'];
    $reply_text = $parsed['reply'] ?? '';
    $looks_like_placeholder = false;
    foreach ($placeholder_signals as $sig) {
        if (mb_strpos($reply_text, $sig) !== false) { $looks_like_placeholder = true; break; }
    }
    $query_entity_missing_name = ($action === 'query_entity' && empty(trim($parsed['data']['name'] ?? '')));

    if (($looks_like_placeholder && !in_array($action, ['query_overview', 'query_upcoming_checks', 'query_entity', 'query_attachment'], true)) || $query_entity_missing_name) {
        $entity_keywords = [
            'car_employee' => ['سائق', 'سواق', 'شوفير'],
            'employee'     => ['موظف', 'راتب', 'رواتب'],
            'supplier'     => ['مورد', 'الموردين'],
            'customer'     => ['عميل', 'زبون', 'الزباين'],
            'personal'     => ['حساب شخصي', 'شخصي'],
            'shareholder'  => ['مساهم', 'شريك'],
        ];
        // لو أصلاً معروف نوع الجهة (query_entity رجع entity_type صح بس الاسم ناقص)، استخدمه بدل ما نعيد اكتشافه
        $detected_type = $parsed['data']['entity_type'] ?? null;
        if (!$detected_type) {
            foreach ($entity_keywords as $type => $kws) {
                foreach ($kws as $kw) {
                    if (mb_strpos($message_for_log, $kw) !== false) { $detected_type = $type; break 2; }
                }
            }
        }
        if ($detected_type && isset($entity_keywords[$detected_type])) {
            // نستخرج اسم الجهة: نشيل كلمات الاستفهام والكلمات المفتاحية ونشوف شو ضل
            $stopwords = array_merge(['كم', 'ضل', 'ضلت', 'من', 'رصيد', 'قديش', 'عليه', 'عليها', 'له', 'الحالي', 'حالياً'], $entity_keywords[$detected_type]);
            $clean_msg = str_replace(['؟', '?'], '', $message_for_log);
            $words = preg_split('/\s+/', trim($clean_msg));
            $name_words = array_filter($words, function($w) use ($stopwords) {
                foreach ($stopwords as $sw) {
                    if (mb_strpos($w, $sw) !== false || $w === $sw) return false;
                }
                return $w !== '';
            });
            $name = trim(implode(' ', $name_words));
            if ($name !== '') {
                $action = 'query_entity';
                $parsed['data'] = ['entity_type' => $detected_type, 'name' => $name];
                // نمسح نص "الوعد الفاضي" القديم حتى يظهر الرد الحقيقي (نتيجة التنفيذ) بدل الوعد
                unset($parsed['reply']);
            }
        }
    }

    if (in_array($action, $no_confirmation_needed, true)) {
        if ($action === 'correct_last') {
            $exec_result = apply_correction_to_last($db, $user['id'], $parsed['data'] ?? []);
        } elseif ($action === 'undo_last') {
            $stmt = $db->prepare("SELECT * FROM chat_log WHERE user_id = ? AND status = 'success' AND entity_table IS NOT NULL AND undone = 0 ORDER BY id DESC LIMIT 1");
            $stmt->execute([$user['id']]);
            $last = $stmt->fetch();
            $exec_result = $last ? undo_entity($last['entity_table'], $last['entity_id']) : ['success' => false, 'message' => 'ما في عملية سابقة للتراجع عنها'];
            if ($last && $exec_result['success']) {
                $db->prepare('UPDATE chat_log SET undone = 1 WHERE id = ?')->execute([$last['id']]);
            }
        } else {
            $exec_result = execute_ai_action($parsed, $user['id']);
        }

        log_chat_action($db, $user['id'], $message_for_log, $parsed, $exec_result);

        return [
            'success' => $exec_result['success'],
            // لو فشلت، لازم السبب الحقيقي يظهر - مش رد الموديل يلي انكتب قبل ما ينفذ فعلياً ويعرف النتيجة
            'reply' => $exec_result['success'] ? ($parsed['reply'] ?? $exec_result['message']) : $exec_result['message'],
            'details' => $exec_result,
        ];
    }

    // باقي الأوامر (كلها بتحرك أموال/بيانات) لازم تأكيد المستخدم أولاً
    $summary = build_action_summary($action, $parsed['data'] ?? []);

    // فحص أمان: لو الرسالة فيها أفعال محاسبية أكتر من عملية وحدة، نحذّر يمكن فاتت عملية
    $mismatch_warning = '';
    if (count_likely_action_verbs($message_for_log) > 1) {
        $mismatch_warning = "\n\n⚠️ تنبيه: رسالتك فيها إشارات لأكتر من عملية بس فهمت وحدة بس - راجعها منيح، ولو ناقص شي اكتبه لحاله بعد التأكيد.";
    }

    $stmt = $db->prepare('INSERT INTO chat_pending_actions (user_id, action_json, summary) VALUES (?,?,?)');
    $stmt->execute([$user['id'], json_encode($parsed, JSON_UNESCAPED_UNICODE), $summary]);

    log_chat_action($db, $user['id'], $message_for_log, $parsed, ['success' => null, 'message' => 'بانتظار التأكيد']);

    return [
        'success' => true,
        'needs_confirmation' => true,
        'pending_id' => $db->lastInsertId(),
        'reply' => "$summary$mismatch_warning\n\nأكد التسجيل؟ اكتب \"نعم\" للتأكيد.",
    ];
}

// تنفيذ الإجراء اللي رجع من OpenAI على قاعدة البيانات
function execute_ai_action($parsed, $user_id) {
    $action = $parsed['action'];
    $d = $parsed['data'] ?? [];
    $today = date('Y-m-d');

    // حماية إضافية: لو الموديل رجّع قيمة مش صحيحة بحقل الحساب (مثل "unclear" أو أي نص عشوائي)
    // نلغيها بدل ما تنسجل بقاعدة البيانات غلط - أحسن ترجع للحساب المعلّق suspense
    if (isset($d['paid_from_bank'])) {
        $valid_banks = ['jordan','jordan_personal','jordan_business','etihad','islami','dinarak','investment','cash'];
        if (!in_array($d['paid_from_bank'], $valid_banks, true)) {
            $d['paid_from_bank'] = null;
        }
    }

    switch ($action) {
        case 'customer_transaction':
            return add_customer_transaction(
                $d['customer_name'] ?? '', $d['type'] ?? 'debit', $d['amount'] ?? 0,
                $d['description'] ?? '', $d['tx_date'] ?? $today, $user_id, null,
                $d['paid_from_bank'] ?? null, $d['no_bank_reason'] ?? null,
                $d['invoice_no'] ?? null, $d['tax_rate'] ?? null
            );

        case 'supplier_transaction':
            return add_supplier_transaction(
                $d['supplier_name'] ?? '', $d['type'] ?? 'debit', $d['amount'] ?? 0,
                $d['description'] ?? '', $d['tx_date'] ?? $today, $user_id, null,
                $d['paid_from_bank'] ?? null, $d['no_bank_reason'] ?? null
            );

        case 'personal_transaction':
            return add_personal_transaction(
                $d['person_name'] ?? '', $d['type'] ?? 'lend', $d['amount'] ?? 0,
                $d['description'] ?? '', $d['tx_date'] ?? $today, $user_id,
                $d['paid_from_bank'] ?? null, $d['no_bank_reason'] ?? null
            );

        case 'profit_distribution':
            return add_profit_distribution(
                $d['shareholder_name'] ?? '', $d['amount'] ?? 0, $d['period_label'] ?? '',
                $d['description'] ?? '', $d['tx_date'] ?? $today, $user_id,
                $d['paid_from_bank'] ?? null
            );

        case 'shareholder_contribution':
            return add_shareholder_contribution(
                $d['shareholder_name'] ?? '', $d['amount'] ?? 0,
                $d['description'] ?? '', $d['tx_date'] ?? $today, $user_id,
                $d['paid_from_bank'] ?? null, $d['no_bank_reason'] ?? null
            );

        case 'expense':
            return add_expense(
                $d['category'] ?? 'expense', $d['amount'] ?? 0, $d['description'] ?? '',
                $d['paid_from_bank'] ?? null, $d['tx_date'] ?? $today, $user_id,
                $d['no_bank_reason'] ?? null, $d['invoice_no'] ?? null, $d['tax_rate'] ?? null
            );

        case 'external_revenue':
            return add_external_revenue(
                $d['source_person'] ?? 'رمزي', $d['amount'] ?? 0, $d['description'] ?? '',
                $d['paid_from_bank'] ?? null, $d['tx_date'] ?? $today, $user_id
            );

        case 'bank_transaction':
            return add_bank_transaction(
                $d['bank'] ?? '', $d['tx_type'] ?? 'deposit', $d['amount'] ?? 0,
                $d['usage_type'] ?? null, $d['description'] ?? '', $d['tx_date'] ?? $today,
                $user_id, $d['related_customer'] ?? null
            );

        case 'cash_count':
            return add_cash_count(
                $d['count_date'] ?? $today, $d['expected_amount'] ?? 0,
                $d['actual_amount'] ?? 0, $d['notes'] ?? '', $user_id
            );

        case 'add_check':
            return add_check(
                $d['direction'] ?? 'incoming', $d['party_name'] ?? '', $d['amount'] ?? 0,
                $d['due_date'] ?? $today, $d['bank_name'] ?? 'islami', $d['check_number'] ?? '',
                $d['notes'] ?? '', $user_id,
                $d['entity_type'] ?? null, $d['entity_name'] ?? null
            );

        case 'employee_transaction':
            return add_employee_transaction(
                $d['employee_name'] ?? '', $d['type'] ?? 'salary', $d['amount'] ?? 0,
                $d['description'] ?? '', $d['tx_date'] ?? $today, $user_id, null,
                $d['paid_from_bank'] ?? null
            );

        case 'car_employee_transaction':
            return add_car_employee_transaction(
                $d['car_employee_name'] ?? '', $d['type'] ?? 'revenue', $d['amount'] ?? 0,
                $d['description'] ?? '', $d['tx_date'] ?? $today, $user_id, null, null,
                $d['customer_count'] ?? null, $d['paid_from_bank'] ?? null
            );

        case 'workshop_transaction':
            return add_workshop_transaction(
                $d['type'] ?? 'revenue', $d['amount'] ?? 0, $d['description'] ?? '',
                $d['tx_date'] ?? $today, $user_id,
                $d['paid_from_bank'] ?? null, $d['no_bank_reason'] ?? null
            );

        case 'query_overview':
            $ov = get_overview();
            return ['success' => true, 'message' => 'تم جلب نظرة عامة على الأرصدة', 'overview' => $ov, 'focus' => $d['focus'] ?? null];

        case 'query_upcoming_checks':
            $checks = get_upcoming_checks($d['days'] ?? 7);
            return ['success' => true, 'message' => 'تم جلب الشيكات القريبة', 'checks' => $checks];

        case 'query_entity':
            $info = get_entity_details($d['entity_type'] ?? '', $d['name'] ?? '');
            if (!$info) {
                return ['success' => false, 'message' => "ما لقيت \"{$d['name']}\" بجدول " . ($d['entity_type'] ?? '')];
            }
            if (isset($info['ambiguous'])) {
                return ['success' => false, 'message' => $info['message']];
            }
            return ['success' => true, 'message' => 'تم جلب البيانات', 'entity' => $info];

        case 'query_attachment':
            $att = search_attachments_by_entity_name($d['entity_type'] ?? '', $d['name'] ?? '');
            if (!$att) {
                return ['success' => false, 'message' => "ما لقيت \"{$d['name']}\""];
            }
            if (isset($att['ambiguous'])) {
                return ['success' => false, 'message' => $att['message']];
            }
            if (empty($att['attachments'])) {
                return ['success' => true, 'message' => "ما في صور محفوظة لـ {$att['name']} لهلق", 'attachments' => []];
            }
            return ['success' => true, 'message' => 'تم جلب الصور', 'attachments' => $att['attachments']];

        case 'unclear':
        default:
            return ['success' => false, 'message' => $d['reason'] ?? 'الرسالة غير واضحة'];
    }
}
