<?php
/**
 * سودانا — AgentEngine v2
 * شبكة الوكلاء — Cash In/Out — الوصول الريفي
 */
require_once __DIR__ . '/BankAdapter.php';

class AgentEngine {

    const AGENT_COMMISSION   = 0.005; // 0.5%
    const MIN_FLOAT_SDG      = 50000;
    const MAX_DAILY_LIMIT    = 5000000;

    // ── register(): تسجيل وكيل جديد ──────────────────────────
    public static function register(int $userId, array $data): array {
        require_once __DIR__ . '/SudannaPayEngine.php';
        try {
            $acc = SudannaPayEngine::getAccount($userId);
            if (!$acc) return ['ok'=>false,'error'=>'no_pay_account'];

            $existing = db()->prepare("SELECT id FROM sdpay_agents WHERE user_id=? LIMIT 1");
            $existing->execute([$userId]);
            if ($existing->fetch()) return ['ok'=>false,'error'=>'already_agent'];

            $agentCode = 'AGT' . strtoupper(substr(md5(uniqid()),0,8));
            db()->prepare(
                "INSERT INTO sdpay_agents
                 (user_id,agent_code,business_name,governorate,city,gps_lat,gps_lng,
                  daily_limit_sdg,commission_rate,status)
                 VALUES (?,?,?,?,?,?,?,?,?,'pending')"
            )->execute([
                $userId, $agentCode,
                trim($data['business_name'] ?? ''),
                $data['governorate'] ?? '',
                $data['city'] ?? '',
                $data['gps_lat'] ?? null,
                $data['gps_lng'] ?? null,
                self::MAX_DAILY_LIMIT,
                self::AGENT_COMMISSION,
            ]);

            return ['ok'=>true,'agent_code'=>$agentCode];
        } catch (Throwable $e) { return ['ok'=>false,'error'=>$e->getMessage()]; }
    }

    // ── processCashIn(): شحن محفظة عميل ──────────────────────
    public static function processCashIn(int $agentUserId, string $customerPhone, float $amount): array {
        require_once __DIR__ . '/SudannaPayEngine.php';
        try {
            // تحقق من الوكيل
            $agent = db()->prepare("SELECT * FROM sdpay_agents WHERE user_id=? AND status='active' LIMIT 1");
            $agent->execute([$agentUserId]);
            $ag = $agent->fetch();
            if (!$ag) return ['ok'=>false,'error'=>'agent_not_found'];

            // جلب حساب العميل بالهاتف
            $custAcc = SudannaPayEngine::getAccountByPhone($customerPhone);
            if (!$custAcc) {
                // إنشاء حساب تلقائياً
                $custUser = db()->prepare("SELECT id FROM users WHERE phone=? LIMIT 1");
                $custUser->execute([$customerPhone]);
                $cu = $custUser->fetch();
                if (!$cu) return ['ok'=>false,'error'=>'customer_not_found'];
                SudannaPayEngine::createAccount($cu['id']);
                $custAcc = SudannaPayEngine::getAccount($cu['id']);
            }

            // تحقق من الحد اليومي للوكيل
            $todayVol = db()->prepare(
                "SELECT COALESCE(SUM(amount_sdg),0) FROM sdpay_agent_transactions
                 WHERE agent_id=? AND type='cashin' AND DATE(created_at)=CURDATE()"
            );
            $todayVol->execute([$ag['id']]);
            if ((float)$todayVol->fetchColumn() + $amount > $ag['daily_limit_sdg'])
                return ['ok'=>false,'error'=>'agent_daily_limit_exceeded'];

            db()->beginTransaction();
            try {
                // ── تأكيد الإيداع من البنك ──────────────────────────────
                if (defined('CASH_IN_REQUIRES_BANK_CONFIRM') && CASH_IN_REQUIRES_BANK_CONFIRM) {
                    $bankConfirm = BankAdapter::confirmDeposit(
                        $data['bank_receipt_no'] ?? 'CASH_' . $txnRef,
                        $amount, $txnRef,
                        $ag['institution_id'] ?? 0
                    );
                    if (!($bankConfirm['confirmed'] ?? false) && !($bankConfirm['sandbox'] ?? false)) {
                        return ['ok'=>false,'error'=>'bank_deposit_not_confirmed','message'=>'لم يتم تأكيد الإيداع من البنك'];
                    }
                    // سجّل في cash_deposit_requests
                    try {
                        db()->prepare("INSERT INTO cash_deposit_requests (request_ref,user_id,agent_id,institution_id,amount_sdg,bank_txn_id,status,confirmed_at) VALUES (?,?,?,?,?,?,'confirmed',NOW())")
                           ->execute([$txnRef,$custAcc['user_id'],$ag['id'],$ag['institution_id']??0,$amount,$bankConfirm['bank_txn_id']??null]);
                    } catch (\Throwable $ignored) {}
                }
                // أضف للعميل
                db()->prepare("UPDATE sdpay_accounts SET balance_sdg=balance_sdg+? WHERE user_id=?")
                   ->execute([$amount, $custAcc['user_id']]);

                // عمولة الوكيل
                $commission = $amount * self::AGENT_COMMISSION;
                db()->prepare("UPDATE sdpay_accounts SET balance_sdg=balance_sdg+? WHERE user_id=?")
                   ->execute([$commission, $agentUserId]);

                // سجل معاملة الوكيل
                $txnRef = 'CIN'.date('YmdHis').substr(md5(uniqid()),0,6);
                db()->prepare(
                    "INSERT INTO sdpay_agent_transactions
                     (agent_id,type,customer_account,amount_sdg,commission_sdg,txn_ref,status)
                     VALUES (?,?,?,?,?,'completed', ?)"
                )->execute([$ag['id'],'cashin',$custAcc['account_no'],$amount,$commission,$txnRef]);

                // سجل Pay
                db()->prepare(
                    "INSERT INTO sdpay_transactions
                     (txn_ref,type,to_account,amount_sdg,fee_sdg,net_sdg,status,channel,narration)
                     VALUES (?,'cashin',?,?,0,?,'completed','agent','شحن نقدي عبر وكيل')"
                )->execute([$txnRef,$custAcc['account_no'],$amount,$amount]);

                db()->commit();
                return ['ok'=>true,'txn_ref'=>$txnRef,'amount_sdg'=>$amount,'commission_sdg'=>$commission];
            } catch (Throwable $e) {
                db()->rollBack();
                throw $e;
            }
        } catch (Throwable $e) { return ['ok'=>false,'error'=>$e->getMessage()]; }
    }

    // ── processCashOut(): سحب نقدي ────────────────────────────
    public static function processCashOut(int $agentUserId, string $customerPhone, float $amount, string $pin): array {
        require_once __DIR__ . '/SudannaPayEngine.php';
        try {
            $custAcc = SudannaPayEngine::getAccountByPhone($customerPhone);
            if (!$custAcc) return ['ok'=>false,'error'=>'customer_not_found'];

            if (!SudannaPayEngine::verifyPin($custAcc['user_id'], $pin))
                return ['ok'=>false,'error'=>'invalid_pin'];

            if ((float)$custAcc['balance_sdg'] < $amount)
                return ['ok'=>false,'error'=>'insufficient_balance'];

            $agent = db()->prepare("SELECT * FROM sdpay_agents WHERE user_id=? AND status='active' LIMIT 1");
            $agent->execute([$agentUserId]);
            $ag = $agent->fetch();
            if (!$ag) return ['ok'=>false,'error'=>'agent_not_active'];

            db()->beginTransaction();
            try {
                // سجّل في withdrawal_requests
                try {
                    db()->prepare(
                        "INSERT INTO withdrawal_requests (request_ref,user_id,agent_id,institution_id,amount_sdg,net_sdg,withdrawal_type,status,pin_verified_at)
                         VALUES (?,?,?,?,?,?,'agent_cash','disbursed',NOW())"
                    )->execute(['WDR'.date('YmdHis').substr(md5(uniqid()),0,6),$custAcc['user_id'],$ag['id'],$ag['institution_id']??0,$amount,$amount]);
                } catch (\Throwable $ignored) {}
                db()->prepare("UPDATE sdpay_accounts SET balance_sdg=balance_sdg-? WHERE user_id=?")
                   ->execute([$amount, $custAcc['user_id']]);

                $commission = $amount * self::AGENT_COMMISSION;
                db()->prepare("UPDATE sdpay_accounts SET balance_sdg=balance_sdg+? WHERE user_id=?")
                   ->execute([$commission, $agentUserId]);

                $txnRef = 'COT'.date('YmdHis').substr(md5(uniqid()),0,6);
                db()->prepare(
                    "INSERT INTO sdpay_agent_transactions
                     (agent_id,type,customer_account,amount_sdg,commission_sdg,txn_ref,status)
                     VALUES (?,?,?,?,?,?,'completed')"
                )->execute([$ag['id'],'cashout',$custAcc['account_no'],$amount,$commission,$txnRef]);

                db()->prepare(
                    "INSERT INTO sdpay_transactions
                     (txn_ref,type,from_account,amount_sdg,fee_sdg,net_sdg,status,channel,narration)
                     VALUES (?,'cashout',?,?,0,?,'completed','agent','سحب نقدي عبر وكيل')"
                )->execute([$txnRef,$custAcc['account_no'],$amount,$amount]);

                db()->commit();
                return ['ok'=>true,'txn_ref'=>$txnRef,'amount_sdg'=>$amount];
            } catch (Throwable $e) { db()->rollBack(); throw $e; }
        } catch (Throwable $e) { return ['ok'=>false,'error'=>$e->getMessage()]; }
    }

    // ── getNearbyAgents(): الوكلاء القريبون ──────────────────
    public static function getNearbyAgents(float $lat, float $lng, int $limit=15): array {
        try {
            $st = db()->prepare(
                "SELECT *,
                 (6371*acos(cos(radians(?))*cos(radians(gps_lat))*cos(radians(gps_lng)-radians(?))+sin(radians(?))*sin(radians(gps_lat)))) AS dist_km
                 FROM sdpay_agents WHERE status='active' AND gps_lat IS NOT NULL
                 HAVING dist_km < 20 ORDER BY dist_km LIMIT ?"
            );
            $st->execute([$lat,$lng,$lat,$limit]);
            return $st->fetchAll();
        } catch (Throwable $e) { return []; }
    }
}
