<?php

require_once __DIR__ . '/agent_schema.php';
require_once __DIR__ . '/agent_activity_lib.php';

if (!function_exists('ua_agent_ledger_effect')) {
  function ua_agent_ledger_effect(string $direction, float $amount): float {
    $direction = strtoupper($direction);
    if ($direction === 'DEBIT') return abs($amount);
    if ($direction === 'CREDIT') return -abs($amount);
    return $amount;
  }
}

if (!function_exists('ua_agent_ledger_balance')) {
  function ua_agent_ledger_balance(mysqli $conn, int $agentId): float {
    ua_agent_schema_migrate($conn);
    $agentId = (int)$agentId;
    $r = @$conn->query("SELECT COALESCE(SUM(
      CASE
        WHEN direction='DEBIT' THEN ABS(amount)
        WHEN direction='CREDIT' THEN -ABS(amount)
        ELSE amount
      END
    ),0) balance FROM agent_ledger_entries WHERE agent_id={$agentId} AND status IN ('POSTED','REVERSED')");
    if ($r && ($row = $r->fetch_assoc())) return round((float)$row['balance'], 2);
    return 0.0;
  }
}

if (!function_exists('ua_agent_ledger_post')) {
  function ua_agent_ledger_post(mysqli $conn, array $data, bool $manageTransaction = true): array {
    ua_agent_schema_migrate($conn);
    $agentId = (int)($data['agent_id'] ?? 0);
    $direction = strtoupper(trim((string)($data['direction'] ?? '')));
    $entryType = substr(trim((string)($data['entry_type'] ?? '')), 0, 50);
    $amount = round((float)($data['amount'] ?? 0), 2);
    $key = substr(trim((string)($data['idempotency_key'] ?? '')), 0, 191);
    if ($agentId <= 0 || !in_array($direction, ['DEBIT','CREDIT','ADJUSTMENT','REVERSAL'], true) || $entryType === '' || $key === '') {
      return ['ok'=>false,'error'=>'بيانات قيد المعتمد غير مكتملة.'];
    }
    if ($amount == 0.0 && !in_array($entryType, ['OPENING_ZERO','AUDIT'], true)) {
      return ['ok'=>false,'error'=>'قيمة القيد يجب ألا تكون صفراً.'];
    }

    $existing = @$conn->query("SELECT * FROM agent_ledger_entries WHERE idempotency_key='" . $conn->real_escape_string($key) . "' LIMIT 1");
    if ($existing && $existing->num_rows) {
      return ['ok'=>true,'duplicate'=>true,'entry'=>$existing->fetch_assoc(),'error'=>''];
    }

    try {
      if ($manageTransaction) $conn->begin_transaction();
      $agent = @$conn->query("SELECT id,credit_limit FROM agents WHERE id={$agentId} AND archived_at IS NULL FOR UPDATE");
      if (!$agent || !$agent->num_rows) throw new RuntimeException('المعتمد غير موجود أو مؤرشف.');
      $agentRow = $agent->fetch_assoc();

      $before = ua_agent_ledger_balance($conn, $agentId);
      $effect = ua_agent_ledger_effect($direction, $amount);
      $after = round($before + $effect, 2);
      $creditLimit = $agentRow['credit_limit'] !== null ? round((float)$agentRow['credit_limit'], 2) : null;
      $allowCreditOverride = !empty($data['allow_credit_override']);
      if ($direction === 'DEBIT' && $creditLimit !== null && $after > $creditLimit && !$allowCreditOverride) {
        throw new RuntimeException('تجاوزت العملية حد ائتمان المعتمد البالغ ' . number_format($creditLimit, 2) . '.');
      }
      $uuid = trim((string)($data['entry_uuid'] ?? '')) ?: ua_agent_uuid();
      $currency = substr(trim((string)($data['currency'] ?? 'SYP')), 0, 12);
      $subscriberId = (int)($data['subscriber_id'] ?? 0) ?: null;
      $invoiceId = (int)($data['invoice_id'] ?? 0) ?: null;
      $paymentId = (int)($data['payment_id'] ?? 0) ?: null;
      $saleId = (int)($data['sale_id'] ?? 0) ?: null;
      $voucherId = (int)($data['voucher_id'] ?? 0) ?: null;
      $sourceType = substr(trim((string)($data['source_type'] ?? '')), 0, 50);
      $sourceId = substr(trim((string)($data['source_id'] ?? '')), 0, 120);
      $instanceId = substr(trim((string)($data['source_instance_id'] ?? '')), 0, 80);
      $reversesId = (int)($data['reverses_entry_id'] ?? 0) ?: null;
      $description = substr(trim((string)($data['description'] ?? '')), 0, 500);
      $meta = ua_agent_json($data['metadata'] ?? []);
      $occurredAt = (string)($data['occurred_at'] ?? date('Y-m-d H:i:s'));
      $actorType = substr(trim((string)($data['created_by_type'] ?? 'admin')), 0, 30);
      $actorId = (int)($data['created_by_id'] ?? 0) ?: null;

      $stmt = $conn->prepare("INSERT INTO agent_ledger_entries
        (entry_uuid,agent_id,direction,entry_type,amount,currency,balance_before,balance_after,subscriber_id,invoice_id,payment_id,sale_id,voucher_id,source_type,source_id,source_instance_id,idempotency_key,reverses_entry_id,status,description,metadata_json,occurred_at,posted_at,created_by_type,created_by_id)
        VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,'POSTED',?,?,?,NOW(),?,?)");
      if (!$stmt) throw new RuntimeException($conn->error);
      $types = 'sissdsdd' . str_repeat('i', 5) . str_repeat('s', 4) . 'i' . str_repeat('s', 4) . 'i';
      $stmt->bind_param(
        $types,
        $uuid,$agentId,$direction,$entryType,$amount,$currency,$before,$after,$subscriberId,$invoiceId,$paymentId,
        $saleId,$voucherId,$sourceType,$sourceId,$instanceId,$key,$reversesId,$description,$meta,$occurredAt,$actorType,$actorId
      );
      if (!$stmt->execute()) throw new RuntimeException($stmt->error);
      $entryId = (int)$stmt->insert_id;
      $stmt->close();
      @$conn->query("UPDATE agents SET balance_cached={$after}, balance={$after}, last_activity_at='" . $conn->real_escape_string($occurredAt) . "' WHERE id={$agentId}");
      if ($manageTransaction) $conn->commit();
      return ['ok'=>true,'duplicate'=>false,'entry'=>['id'=>$entryId,'entry_uuid'=>$uuid,'balance_before'=>$before,'balance_after'=>$after],'error'=>''];
    } catch (Throwable $e) {
      if ($manageTransaction) @$conn->rollback();
      return ['ok'=>false,'error'=>$e->getMessage()];
    }
  }
}

if (!function_exists('ua_agent_ledger_reverse')) {
  function ua_agent_ledger_reverse(mysqli $conn, int $entryId, string $reason, array $actor = [], bool $manageTransaction = true): array {
    ua_agent_schema_migrate($conn);
    $entryId = (int)$entryId;
    $r = @$conn->query("SELECT * FROM agent_ledger_entries WHERE id={$entryId} AND status='POSTED' LIMIT 1");
    if (!$r || !$r->num_rows) return ['ok'=>false,'error'=>'القيد الأصلي غير موجود أو معكوس.'];
    $old = $r->fetch_assoc();
    $direction = (string)$old['direction'];
    $reverseDirection = $direction === 'DEBIT' ? 'CREDIT' : ($direction === 'CREDIT' ? 'DEBIT' : 'REVERSAL');
    $key = 'REVERSAL:' . $entryId;
    if ($manageTransaction) $conn->begin_transaction();
    $posted = ua_agent_ledger_post($conn, [
      'agent_id'=>(int)$old['agent_id'],
      'direction'=>$reverseDirection,
      'entry_type'=>'REVERSAL',
      'amount'=>(float)$old['amount'],
      'idempotency_key'=>$key,
      'reverses_entry_id'=>$entryId,
      'source_type'=>'ledger_entry',
      'source_id'=>(string)$entryId,
      'description'=>$reason,
      'metadata'=>['original_entry_uuid'=>$old['entry_uuid']],
      'created_by_type'=>$actor['type'] ?? 'admin',
      'created_by_id'=>$actor['id'] ?? null,
    ], false);
    if (!$posted['ok']) {
      if ($manageTransaction) $conn->rollback();
      return $posted;
    }
    @$conn->query("UPDATE agent_ledger_entries SET status='REVERSED' WHERE id={$entryId}");
    if ($manageTransaction) $conn->commit();
    return $posted;
  }
}
