<?php
// Cron: * * * * * curl -s "https://p1.enotice.top/telecom/cron_recharge_status.php?secret=priyotelecom2024"

define('CRON_SECRET', 'priyotelecom2024');
$isWeb = php_sapi_name() !== 'cli';
if ($isWeb && ($_GET['secret']??'') !== CRON_SECRET) { http_response_code(403); die('Forbidden'); }

require_once __DIR__.'/includes/config.php';
require_once __DIR__.'/includes/ecare.php';
require_once __DIR__.'/includes/successtopup.php';
require_once __DIR__.'/includes/custom_api.php';
require_once __DIR__.'/includes/commission.php';
require_once __DIR__.'/includes/telegram.php';

set_time_limit(110);
ignore_user_abort(true);

$db = getDB();

// ─── Detect which API to use for a transaction ─────────────────────────────
function detectApi($t) {
    $note    = $t['note'] ?? '';
    $apiResp = $t['api_response'] ?? '';
    $apiData = $apiResp ? (json_decode($apiResp, true) ?: []) : [];

    // ECARE
    if (strpos($note,'ECARE') !== false
     || !empty($apiData['ecare_ref'])
     || strpos($apiResp,'ecare_ref') !== false
     || strpos($apiResp,'RECEIVED') !== false
     || strpos($note,'TrxID') !== false && strpos($apiResp,'ecare') !== false) {
        return ['type'=>'ecare','ref'=>$apiData['ecare_ref'] ?? $t['reference']];
    }
    // SuccessTopUp
    if (strpos($note,'ST_PENDING') !== false
     || strpos($note,'ST ') !== false
     || strpos($apiResp,'successtopup') !== false) {
        return ['type'=>'st','ref'=>$t['reference']];
    }
    // Custom API — note format: CUSTOM_PENDING_{api_id}
    if (strpos($note,'CUSTOM_PENDING') !== false) {
        preg_match('/CUSTOM_PENDING_?(\d+)?/', $note, $m);
        $apiId = !empty($m[1]) ? intval($m[1]) : (!empty($apiData['custom_api_id']) ? intval($apiData['custom_api_id']) : 0);
        return ['type'=>'custom','api_id'=>$apiId,'ref'=>$t['reference']];
    }
    // Generic pending with TrxID note — try ST first
    if (strpos($note,'TrxID') !== false) {
        return ['type'=>'st','ref'=>$t['reference']];
    }
    return ['type'=>'unknown'];
}

// ─── Resolve success ────────────────────────────────────────────────────────
function markSuccess($db, $t, $trxId, $res) {
    $db->beginTransaction();
    try {
        $db->prepare("UPDATE transactions SET status='success', note=?, api_response=?, updated_at=NOW() WHERE id=?")
           ->execute(["TrxID: {$trxId}", json_encode($res), $t['id']]);
        applyCommission($db, $t['user_id'], 'topup', $t['amount'], $t['reference']);
        $db->prepare("INSERT INTO notifications (user_id,title,message,type) VALUES (?,?,?,'success')")
           ->execute([$t['user_id'], '✅ রিচার্জ সফল!', $t['phone_number'].' — '.CURRENCY.number_format($t['amount'],2).' সম্পন্ন।']);
        $db->commit();
        notifyUserRechargeSuccess($t['user_id'], $t['phone_number'], number_format($t['amount'],2), $t['reference'], $t['op_name']??'');
        echo "  → ✅ SUCCESS (TrxID: $trxId)\n";
    } catch(Exception $e) { $db->rollBack(); echo "  → Error: ".$e->getMessage()."\n"; }
}

// ─── Resolve failed + refund ────────────────────────────────────────────────
function markFailed($db, $t, $reason = '❌ Failed') {
    $db->beginTransaction();
    try {
        $newBal = $t['balance'] + $t['amount'];
        $db->prepare("UPDATE users SET balance=balance+? WHERE id=?")->execute([$t['amount'], $t['user_id']]);
        $db->prepare("UPDATE transactions SET status='failed', note=?, balance_after=?, updated_at=NOW() WHERE id=?")->execute([$reason, $newBal, $t['id']]);
        $db->prepare("INSERT INTO transactions (user_id,type,amount,charge,net_amount,balance_before,balance_after,reference,status,note) VALUES (?,?,?,0,?,?,?,?,?,?)")
           ->execute([$t['user_id'],'refund',$t['amount'],$t['amount'],$t['balance'],$newBal,'RF-'.$t['reference'],'success','Auto refund']);
        $db->prepare("INSERT INTO notifications (user_id,title,message,type) VALUES (?,?,?,'warning')")
           ->execute([$t['user_id'], '❌ রিচার্জ Failed', CURRENCY.number_format($t['amount'],2).' refunded.']);
        $db->commit();
        notifyUserRechargeFailed($t['user_id'], number_format($t['amount'],2), $t['reference']);
        echo "  → ❌ FAILED + Refunded\n";
    } catch(Exception $e) { $db->rollBack(); echo "  → Error: ".$e->getMessage()."\n"; }
}

// ─── Load all custom APIs ────────────────────────────────────────────────────
$customApis = [];
try {
    $rows = $db->query("SELECT * FROM custom_apis WHERE is_active=1 AND endpoint_status IS NOT NULL AND endpoint_status != ''")->fetchAll();
    foreach ($rows as $r) $customApis[$r['id']] = $r;
} catch(Exception $e) {}

// ════════════════════════════════════════════════════════════
// TOPUP pending check
// ════════════════════════════════════════════════════════════
$pendings = $db->query("
    SELECT t.*, u.name as uname, u.balance, o.code as op_code, o.name as op_name
    FROM transactions t
    JOIN users u ON t.user_id = u.id
    LEFT JOIN operators o ON t.operator_id = o.id
    WHERE t.type = 'topup'
    AND t.status = 'pending'
    AND t.created_at >= NOW() - INTERVAL 2 HOUR
    ORDER BY t.created_at ASC
    LIMIT 50
")->fetchAll();

echo "=== TOPUP: ".count($pendings)." pending ===\n";

foreach ($pendings as $t) {
    $ref   = $t['reference'];
    $det   = detectApi($t);
    $atype = $det['type'];

    if ($atype === 'unknown') {
        echo "  $ref | SKIP (unknown API)\n";
        continue;
    }

    $rcStatus = 'pending'; $trxId = ''; $res = [];

    if ($atype === 'ecare') {
        $checkRef = $det['ref'];
        $res   = ecareStatus($checkRef);
        $raw   = $res['rc_status'] ?? '';
        $trxId = $res['trxid'] ?? '';
        if ($raw === 'SUCCESS') $rcStatus = 'success';
        elseif (in_array($raw, ['FAILED','REJECT','REJECTED'])) $rcStatus = 'failed';
        echo "  $ref | ECARE | rc=$raw\n";

    } elseif ($atype === 'st') {
        $res    = successTopupStatus($ref);
        $stStat = strtoupper($res['status'] ?? '');
        $trxId  = $res['trxid'] ?? $res['TRXID'] ?? '';
        $msg    = strtolower($res['message'] ?? '');
        if (in_array($stStat,['SUCCESS','COMPLETED']) || strpos($msg,'success')!==false) $rcStatus = 'success';
        elseif (in_array($stStat,['FAILED','REJECTED','CANCELLED','INVALID']) || strpos($msg,'failed')!==false || strpos($msg,'reject')!==false) $rcStatus = 'failed';
        echo "  $ref | ST | status=$stStat\n";

    } elseif ($atype === 'custom') {
        $apiId = $det['api_id'];
        if (!$apiId || !isset($customApis[$apiId])) {
            // Try all custom APIs
            foreach ($customApis as $caId => $ca) {
                $res = customApiCall($caId, 'status', ['trxid' => $ref, 'ref' => $ref]);
                if ($res['ok']) { $apiId = $caId; break; }
            }
        }
        if ($apiId && isset($customApis[$apiId])) {
            $res    = customApiCall($apiId, 'status', ['trxid' => $ref, 'ref' => $ref]);
            $trxId  = $res['trxid'] ?? '';
            $stStat = strtoupper($res['status'] ?? '');
            $msg    = strtolower($res['message'] ?? '');
            // Use response_map success_value
            $rm     = json_decode($customApis[$apiId]['response_map']??'{}',true)?:[];
            $sv     = $rm['success_value'] ?? '1';
            if ($res['ok'] || (string)$res['result'] === (string)$sv || in_array($stStat,['SUCCESS','COMPLETED'])) $rcStatus = 'success';
            elseif (in_array($stStat,['FAILED','REJECTED','CANCELLED','INVALID'])) $rcStatus = 'failed';
            echo "  $ref | CUSTOM[$apiId] | status=$stStat\n";
        }
    }

    if ($rcStatus === 'success') markSuccess($db, $t, $trxId, $res);
    elseif ($rcStatus === 'failed') markFailed($db, $t, '❌ '.$atype.' Failed');
}

// ════════════════════════════════════════════════════════════
// DRIVE pending check
// ════════════════════════════════════════════════════════════
try {
    $drives = $db->query("
        SELECT dr.*, u.balance as ubal, u.name as uname, dp.name as pkg_name, dp.cashback_amount, dp.commission_percent
        FROM drive_requests dr
        JOIN users u ON dr.user_id = u.id
        LEFT JOIN drive_packages dp ON dr.package_id = dp.id
        WHERE dr.status = 'pending'
        AND dr.created_at >= NOW() - INTERVAL 2 HOUR
        ORDER BY dr.created_at ASC LIMIT 30
    ")->fetchAll();

    echo "\n=== DRIVE: ".count($drives)." pending ===\n";

    foreach ($drives as $dr) {
        $apiData = $dr['note'] ? json_decode($dr['note'], true) : [];
        $isEcare = !empty($apiData['ecare_ref']);
        $checkRef = $isEcare ? $apiData['ecare_ref'] : $dr['reference'];

        $rcStatus='pending'; $trxId=''; $cashback=floatval($dr['cashback_amount']??0);

        if ($isEcare) {
            $res   = ecareStatus($checkRef);
            $raw   = $res['rc_status'] ?? '';
            $trxId = $res['trxid'] ?? '';
            if ($raw==='SUCCESS') $rcStatus='success';
            elseif (in_array($raw,['FAILED','REJECT','REJECTED'])) $rcStatus='failed';
            echo "  {$dr['reference']} | DRIVE ECARE | rc=$raw\n";
        } else {
            $res    = successTopupStatus($dr['reference']);
            $stStat = strtoupper($res['status']??'');
            $trxId  = $res['trxid']??$res['TRXID']??'';
            $msg    = strtolower($res['message']??'');
            $cbRaw  = floatval($res['cashback_amount']??$res['commission']??0);
            if($cbRaw>0) $cashback=$cbRaw;
            if(in_array($stStat,['SUCCESS','COMPLETED'])||strpos($msg,'success')!==false) $rcStatus='success';
            elseif(in_array($stStat,['FAILED','REJECTED','CANCELLED','INVALID'])||strpos($msg,'failed')!==false) $rcStatus='failed';
            echo "  {$dr['reference']} | DRIVE ST | status=$stStat\n";
        }

        if ($rcStatus==='success') {
            $db->beginTransaction();
            try {
                $db->prepare("UPDATE drive_requests SET status='success', note=? WHERE id=?")->execute(["TrxID: $trxId", $dr['id']]);
                if($cashback>0) {
                    $db->prepare("UPDATE users SET balance=balance+? WHERE id=?")->execute([$cashback,$dr['user_id']]);
                    $nb=floatval($db->query("SELECT balance FROM users WHERE id={$dr['user_id']}")->fetchColumn());
                    $db->prepare("INSERT INTO transactions (user_id,type,amount,charge,net_amount,balance_before,balance_after,reference,status,note) VALUES (?,?,?,0,?,?,?,?,?,?)")
                       ->execute([$dr['user_id'],'commission',$cashback,$cashback,$nb-$cashback,$nb,'DRC-'.$dr['reference'],'success','Drive cashback']);
                }
                $db->prepare("INSERT INTO notifications (user_id,title,message,type) VALUES (?,?,?,'success')")
                   ->execute([$dr['user_id'],'✅ Drive সফল!',$dr['phone_number'].' পাঠানো হয়েছে।']);
                $db->commit();
                echo "  → ✅ DRIVE SUCCESS\n";
            } catch(Exception $e) { $db->rollBack(); }
        } elseif ($rcStatus==='failed') {
            $db->beginTransaction();
            try {
                $newBal=$dr['ubal']+$dr['amount'];
                $db->prepare("UPDATE users SET balance=balance+? WHERE id=?")->execute([$dr['amount'],$dr['user_id']]);
                $db->prepare("UPDATE drive_requests SET status='failed' WHERE id=?")->execute([$dr['id']]);
                $db->prepare("INSERT INTO notifications (user_id,title,message,type) VALUES (?,?,?,'warning')")
                   ->execute([$dr['user_id'],'❌ Drive Failed',CURRENCY.number_format($dr['amount'],2).' refunded.']);
                $db->commit();
                echo "  → ❌ DRIVE FAILED + Refunded\n";
            } catch(Exception $e) { $db->rollBack(); }
        }
    }
} catch(Exception $e) { echo "Drive error: ".$e->getMessage()."\n"; }

echo "\n=== Done ===\n";
