<?php
require_once dirname(__DIR__) . '/finance_expense_lib.php';
finance_expense_migrate($conn);

function expense_test_assert(bool $condition, string $message): void {
  if (!$condition) throw new RuntimeException($message);
}

$suffix = date('YmdHis') . random_int(1000, 9999);
$accountKey = 'AGENT:__expense_test_' . $suffix;
$typeName = '__expense_test_type_' . $suffix;
$expenseId = 0;
$typeId = 0;
$mainBefore = (float)($conn->query("SELECT balance FROM collection_accounts WHERE account_key='MAIN'")->fetch_assoc()['balance'] ?? 0);

try {
  $stmt = $conn->prepare("INSERT INTO collection_accounts(account_key,account_type,account_ref,account_name,balance) VALUES(?,'agent',?,?,500.00)");
  $ref = '__expense_test_' . $suffix;
  $name = 'صندوق اختبار المدفوعات';
  $stmt->bind_param('sss', $accountKey, $ref, $name);
  expense_test_assert($stmt->execute(), 'تعذر إنشاء صندوق الاختبار.');
  $stmt->close();

  $record = finance_expense_record($conn, [
    'type_name'=>$typeName,'account_key'=>$accountKey,'amount'=>125.25,
    'spent_at'=>date('Y-m-d'),'reference'=>'TEST-'.$suffix,'note'=>'automated expense test','created_by'=>0,'channel'=>'test',
  ]);
  expense_test_assert(!empty($record['ok']), 'فشل تسجيل القيد: '.($record['error'] ?? 'unknown'));
  $expenseId = (int)$record['id'];

  $expense = $conn->query("SELECT expense_type_id,expense_status,collection_account_key FROM expenses WHERE id={$expenseId}")->fetch_assoc();
  $typeId = (int)($expense['expense_type_id'] ?? 0);
  expense_test_assert($typeId > 0, 'لم يُربط القيد بنوع ديناميكي.');
  expense_test_assert(($expense['expense_status'] ?? '') === 'POSTED', 'حالة القيد الجديد غير صحيحة.');
  expense_test_assert(($expense['collection_account_key'] ?? '') === $accountKey, 'لم يُحفظ الصندوق المختار.');
  $agentAfter = (float)$conn->query("SELECT balance FROM collection_accounts WHERE account_key='".$conn->real_escape_string($accountKey)."'")->fetch_assoc()['balance'];
  $mainAfter = (float)$conn->query("SELECT balance FROM collection_accounts WHERE account_key='MAIN'")->fetch_assoc()['balance'];
  expense_test_assert(abs($agentAfter - 374.75) < 0.001, 'رصيد صندوق النسخة بعد الخصم غير صحيح.');
  expense_test_assert(abs($mainAfter - ($mainBefore - 125.25)) < 0.001, 'الرصيد الرئيسي بعد الخصم غير صحيح.');
  $ledgerCount = (int)$conn->query("SELECT COUNT(*) c FROM collection_ledger_entries WHERE expense_id={$expenseId} AND entry_type='EXPENSE' AND status='POSTED'")->fetch_assoc()['c'];
  expense_test_assert($ledgerCount === 2, 'القيد المزدوج للصندوق الرئيسي وصندوق النسخة غير مكتمل.');

  $reverse = finance_expense_reverse($conn, $expenseId, 0);
  expense_test_assert(!empty($reverse['ok']) && (int)$reverse['reversed'] === 2, 'فشل عكس القيد المزدوج.');
  $agentRestored = (float)$conn->query("SELECT balance FROM collection_accounts WHERE account_key='".$conn->real_escape_string($accountKey)."'")->fetch_assoc()['balance'];
  $mainRestored = (float)$conn->query("SELECT balance FROM collection_accounts WHERE account_key='MAIN'")->fetch_assoc()['balance'];
  expense_test_assert(abs($agentRestored - 500.00) < 0.001, 'لم يُستعد رصيد صندوق النسخة بعد العكس.');
  expense_test_assert(abs($mainRestored - $mainBefore) < 0.001, 'لم يُستعد الرصيد الرئيسي بعد العكس.');
  $duplicateReverse = finance_expense_reverse($conn, $expenseId, 0);
  expense_test_assert(empty($duplicateReverse['ok']), 'سمح النظام بعكس القيد مرتين.');

  echo "PASS: dynamic type, atomic double debit, audit reversal, and duplicate protection\n";
} finally {
  if ($expenseId > 0) {
    $conn->query("DELETE FROM collection_ledger_entries WHERE expense_id={$expenseId}");
    $conn->query("DELETE FROM expenses WHERE id={$expenseId}");
  }
  if ($typeId > 0) $conn->query("DELETE FROM expense_types WHERE id={$typeId}");
  $conn->query("DELETE FROM collection_accounts WHERE account_key='".$conn->real_escape_string($accountKey)."'");
}
