<?php
declare(strict_types=1);

mysqli_report(MYSQLI_REPORT_OFF);
require_once __DIR__ . '/../db_bootstrap.php';
require_once __DIR__ . '/../billing_cycle_lib.php';

$conn = ensure_db(true);
if (!($conn instanceof mysqli)) {
  fwrite(STDERR, "FAIL db_not_ready\n");
  exit(1);
}
billing_cycle_migrate($conn);

$testKey = 'EXCYCLE-' . date('YmdHis') . '-' . bin2hex(random_bytes(3));
$subscriberId = 0;
$cycleId = 0;
$failures = [];

function exceptional_cycle_assert(bool $condition, string $label, array &$failures): void {
  echo ($condition ? 'PASS ' : 'FAIL ') . $label . PHP_EOL;
  if (!$condition) $failures[] = $label;
}

try {
  $speedRs = $conn->query("SELECT speed_name,price FROM speeds WHERE price>0 ORDER BY id ASC LIMIT 1");
  $speed = $speedRs ? $speedRs->fetch_assoc() : null;
  if (!$speed) throw new RuntimeException('لا توجد سرعة مسعرة صالحة للاختبار.');
  $speedName = (string)$speed['speed_name'];

  $stmt = $conn->prepare("INSERT INTO subscribers
    (username,full_name,phone,speed,speed_name,package,package_name,status,is_deleted,ppp_username,ppp_password,billing_paused,billing_state,created_at,updated_at)
    VALUES (?,?,?,?,?,'مفتوحة','مفتوحة','نشط',0,'','',0,'CURRENT',NOW(),NOW())");
  if (!$stmt) throw new RuntimeException($conn->error);
  $username = strtolower($testKey);
  $fullName = 'مشترك اختبار الدورة الاستثنائية';
  $phone = '0000000000';
  $stmt->bind_param('sssss', $username, $fullName, $phone, $speedName, $speedName);
  if (!$stmt->execute()) throw new RuntimeException($stmt->error);
  $subscriberId = (int)$stmt->insert_id;
  $stmt->close();

  $settingsBefore = billing_get_settings($conn);
  $token = hash('sha256', $testKey);
  $created = billing_create_exceptional_cycle($conn, 0, 'اختبار دورة استثنائية', $token, [$subscriberId]);
  $cycleId = (int)($created['cycle_id'] ?? 0);
  exceptional_cycle_assert(!empty($created['ok']) && (int)($created['created'] ?? 0) === 1, 'إنشاء فاتورة استثنائية واحدة', $failures);

  $invoiceRs = $conn->query("SELECT * FROM invoices WHERE subscriber_id={$subscriberId} AND exceptional_cycle_id={$cycleId} LIMIT 1");
  $invoice = $invoiceRs ? $invoiceRs->fetch_assoc() : null;
  exceptional_cycle_assert(
    is_array($invoice)
      && strtoupper((string)($invoice['cycle_type'] ?? '')) === 'EXCEPTIONAL'
      && (string)($invoice['invoice_type'] ?? '') === 'BASE',
    'الفاتورة الاستثنائية ترث مسار الفاتورة الأساسية',
    $failures
  );
  exceptional_cycle_assert(
    str_starts_with((string)($invoice['generation_key'] ?? ''), 'EXCEPTIONAL:' . $cycleId . ':'),
    'مفتاح التوليد مستقل عن الدورة التلقائية',
    $failures
  );

  $cycleRs = $conn->query("SELECT * FROM billing_exceptional_cycles WHERE id={$cycleId} LIMIT 1");
  $cycle = $cycleRs ? $cycleRs->fetch_assoc() : null;
  exceptional_cycle_assert(
    is_array($cycle)
      && (int)($cycle['grace_days'] ?? -1) === (int)$settingsBefore['grace_days']
      && (int)($cycle['limit_after_days'] ?? -1) === (int)$settingsBefore['limit_after_days']
      && (int)($cycle['cut_after_days'] ?? -1) === (int)$settingsBefore['cut_after_days'],
    'تثبيت لقطة المهل الحالية داخل الدورة الاستثنائية',
    $failures
  );

  $again = billing_create_exceptional_cycle($conn, 0, 'لن تنشأ مرة ثانية', $token, [$subscriberId]);
  $countRs = $conn->query("SELECT COUNT(*) c FROM invoices WHERE subscriber_id={$subscriberId} AND exceptional_cycle_id={$cycleId}");
  $invoiceCount = $countRs ? (int)($countRs->fetch_assoc()['c'] ?? 0) : 0;
  exceptional_cycle_assert(!empty($again['idempotent']) && $invoiceCount === 1, 'منع التكرار عند إعادة إرسال الطلب', $failures);

  $settingsAfter = billing_get_settings($conn);
  exceptional_cycle_assert($settingsBefore === $settingsAfter, 'عدم تعديل إعدادات الدورة التلقائية', $failures);
} catch (Throwable $e) {
  $failures[] = $e->getMessage();
  echo 'FAIL exception: ' . $e->getMessage() . PHP_EOL;
} finally {
  if ($subscriberId > 0) {
    @$conn->query("DELETE FROM billing_action_requests WHERE subscriber_id={$subscriberId}");
    @$conn->query("DELETE FROM subscriber_credit_ledger WHERE subscriber_id={$subscriberId}");
    @$conn->query("DELETE FROM subscriber_credit_accounts WHERE subscriber_id={$subscriberId}");
    @$conn->query("DELETE FROM invoices WHERE subscriber_id={$subscriberId}");
    @$conn->query("DELETE FROM subscribers WHERE id={$subscriberId}");
  }
  if ($cycleId > 0) @$conn->query("DELETE FROM billing_exceptional_cycles WHERE id={$cycleId}");
}

if ($failures) {
  fwrite(STDERR, 'FAILED ' . count($failures) . ': ' . implode(' | ', $failures) . PHP_EOL);
  exit(1);
}
echo "ALL EXCEPTIONAL BILLING CYCLE TESTS PASSED\n";
