<?php
/**
 * ═══════════════════════════════════════════════════════════
 * sms_receive.php — Transaction ID ভিত্তিক Matching (নতুন, সহজ Version)
 * ═══════════════════════════════════════════════════════════
 */
error_reporting(E_ALL);
ini_set('display_errors', 1);

include __DIR__ . "/../../conn.php";
require_once __DIR__ . '/sms_secret_config.php';

header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, X-Device-Secret');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; }

$logDir = __DIR__ . '/sms_logs';
if (!file_exists($logDir)) { @mkdir($logDir, 0777, true); }
function smsLog($msg) {
    global $logDir;
    @file_put_contents($logDir . '/sms_' . date('Y-m-d') . '.log', '[' . date('H:i:s') . "] $msg" . PHP_EOL, FILE_APPEND);
}

// ✅ Secret Verify
$deviceSecret = $_SERVER['HTTP_X_DEVICE_SECRET'] ?? ($_SERVER['REDIRECT_HTTP_X_DEVICE_SECRET'] ?? '');
if ($deviceSecret !== SMS_DEVICE_SECRET) {
    smsLog("REJECTED: Wrong Secret");
    echo json_encode(['code' => 1, 'msg' => 'Unauthorized Device']);
    exit;
}

$input = json_decode(file_get_contents('php://input'), true);
if (!is_array($input)) { echo json_encode(['code' => 1, 'msg' => 'Invalid JSON']); exit; }

// ✅ Raw SMS থেকে Parse করা (Amount, TrxID, Sender Number)
if (isset($input['raw_sms'])) {
    $rawSmsText = $input['raw_sms'];
    preg_match('/(?:Tk|BDT)\s*([\d,]+\.?\d*)/i', $rawSmsText, $m1);
    $input['amount'] = isset($m1[1]) ? floatval(str_replace(',', '', $m1[1])) : 0;
    preg_match('/(?:Transaction ID|TrxID|TxnID)\s*[:\s]?\s*([A-Za-z0-9]+)/i', $rawSmsText, $m2);
    $input['trxid'] = $m2[1] ?? '';
    preg_match('/(?:from\s+|Uddokta:\s*)(01\d{9})/i', $rawSmsText, $m3);
    $input['sender'] = $m3[1] ?? ($input['sender'] ?? '');
}

$trxid = trim($input['trxid'] ?? '');
$amount = round(floatval($input['amount'] ?? 0), 2);
$sender = trim($input['sender'] ?? '');
$gateway = strtolower(trim($input['gateway'] ?? ''));

smsLog("INCOMING: TrxID=$trxid | Amount=$amount | Sender=$sender | Gateway=$gateway");

if ($trxid === '' || $amount <= 0) {
    smsLog("REJECTED: Missing TrxID or Amount");
    echo json_encode(['code' => 1, 'msg' => 'Invalid Data']);
    exit;
}

// ✅ ধাপ ১ — এই TrxID দিয়ে User-এর জমা দেওয়া Verification খোঁজা
$find = $conn->prepare("
    SELECT * FROM pending_verifications
    WHERE trxid = ? AND status = 'pending' AND expires_at >= NOW()
    LIMIT 1
");
$find->bind_param("s", $trxid);
$find->execute();
$result = $find->get_result();

if ($result->num_rows === 0) {
    smsLog("UNMATCHED: No pending verification for TrxID=$trxid");

    // ✅ নতুন যোগ — এই SMS-টা "Orphan" হিসেবে Save করা হচ্ছে,
    // যাতে User পরে Website-এ Order Submit করলে, সাথে সাথে
    // Match করে দেওয়া যায় (SMS আগে এসে গেলেও যেন কাজ করে)
    $orphanStmt = $conn->prepare("
        INSERT IGNORE INTO orphan_sms_log (trxid, amount, sender, gateway, expires_at)
        VALUES (?, ?, ?, ?, DATE_ADD(NOW(), INTERVAL 24 HOUR))
    ");
    $orphanStmt->bind_param("sdss", $trxid, $amount, $sender, $gateway);
    $orphanStmt->execute();
    $orphanStmt->close();

    // ⚠️ সাময়িক Debug — এই TrxID দিয়ে আসলে কী আছে (Status/Expiry নির্বিশেষে) তা দেখানো
    $debugFind = $conn->prepare("SELECT *, NOW() as server_now FROM pending_verifications WHERE trxid = ?");
    $debugFind->bind_param("s", $trxid);
    $debugFind->execute();
    $debugResult = $debugFind->get_result();
    $debugRecord = $debugResult->num_rows > 0 ? $debugResult->fetch_assoc() : null;

    echo json_encode([
        'code' => 0,
        'msg' => 'SMS Recorded, কোনো Matching Verification পাওয়া যায়নি',
        'debug_searched_trxid' => $trxid,
        'debug_record_found_ignoring_status_expiry' => $debugRecord
    ]);
    exit;
}

$record = $result->fetch_assoc();

// ✅ ধাপ ২ — Mobile Number শুধু Log-এর জন্য মিলিয়ে দেখা হচ্ছে
// (আর কখনো Reject করা হবে না) — কারণ TrxID এমনিতেই Unique,
// তাই শুধু TrxID+Amount মিললেই যথেষ্ট নিরাপদ ধরা হচ্ছে
if ($sender !== '' && strtolower($sender) !== 'unknown') {
    $cleanRecordMobile = preg_replace('/[^0-9]/', '', $record['mobile']);
    $cleanSenderMobile = preg_replace('/[^0-9]/', '', $sender);
    $mobileMatches = (substr($cleanRecordMobile, -10) === substr($cleanSenderMobile, -10));

    if (!$mobileMatches) {
        smsLog("INFO: Mobile mismatch (কিন্তু আটকানো হয়নি, শুধু Log). Record=$cleanRecordMobile | SMS Sender=$cleanSenderMobile");
    }
} else {
    smsLog("INFO: Sender unknown — শুধু TrxID+Amount Match দিয়েই এগোনো হচ্ছে (TrxID=$trxid)");
}

// ✅ ধাপ ৩ — সব ঠিক থাকলে, SMS-এর আসল Amount দিয়ে Balance বাড়ানো
$userId = $record['user_id'];

/* ══════════════════════════════════════════════════════════════
   ✅ নতুন যোগ — Deposit-এর আগে, User কোন Agent-এর Downline নাকি
   সরাসরি Admin-এর User, তা বের করা। তারপর সেই সঠিক Pool-এ
   যথেষ্ট Coin আছে কিনা Check করা — Coin না থাকলে, Deposit
   একদম হবেই না (Coin কখনো "নতুন তৈরি" হবে না)।
   ══════════════════════════════════════════════════════════════ */
$poolIsAgent = false;
$poolId = null; // Agent হলে Agent-এর userid, নাহলে Main Admin-এর unohs

$selfQ = $conn->query("SELECT code FROM shonu_subjects WHERE id = '$userId'");
$selfRow = $selfQ ? $selfQ->fetch_assoc() : null;

if ($selfRow && !empty($selfRow['code'])) {
    $refQ = $conn->query("SELECT id FROM shonu_subjects WHERE owncode = '" . $conn->real_escape_string($selfRow['code']) . "'");
    $refRow = $refQ ? $refQ->fetch_assoc() : null;
    if ($refRow) {
        $agentChk = $conn->query("SELECT userid FROM tb_agent WHERE userid = '{$refRow['id']}' AND status = '1'");
        if ($agentChk && $agentChk->num_rows > 0) {
            $poolIsAgent = true;
            $poolId = $refRow['id'];
        }
    }
}

if (!$poolIsAgent) {
    // সরাসরি Admin-এর User — Main Admin-এর unohs বের করা
    $adminRow = $conn->query("SELECT unohs FROM nirvahaka_shonu ORDER BY unohs ASC LIMIT 1")->fetch_assoc();
    $poolId = $adminRow['unohs'] ?? null;
}

// ✅ সেই Pool-এর বর্তমান Coin Balance Check করা
$poolBalance = 0;
if ($poolIsAgent) {
    $poolBalRow = $conn->query("SELECT motta FROM shonu_kaichila WHERE balakedara = '$poolId'")->fetch_assoc();
    $poolBalance = $poolBalRow ? floatval($poolBalRow['motta']) : 0;
} else {
    $poolBalRow = $conn->query("SELECT motta FROM nirvahaka_shonu WHERE unohs = '$poolId'")->fetch_assoc();
    $poolBalance = $poolBalRow ? floatval($poolBalRow['motta']) : 0;
}

if ($poolBalance < $amount) {
    smsLog("BLOCKED: Insufficient Pool Coin. Pool=" . ($poolIsAgent ? "Agent#$poolId" : "Admin#$poolId") . " | Balance=$poolBalance | Needed=$amount");
    echo json_encode(['code' => 1, 'msg' => 'যথেষ্ট Coin নেই (' . ($poolIsAgent ? 'Agent' : 'Admin') . ' Pool-এ), তাই Deposit হয়নি। Admin/Agent-এর সাথে যোগাযোগ করো।']);
    exit;
}

$conn->begin_transaction();
try {
    $upd = $conn->prepare("UPDATE pending_verifications SET status='verified', verified_amount=?, verified_at=NOW() WHERE id=? AND status='pending'");
    $upd->bind_param("di", $amount, $record['id']);
    $upd->execute();
    if ($upd->affected_rows <= 0) throw new Exception('Already verified or expired');

    // ✅ নতুন যোগ — সঠিক Pool (Agent বা Admin) থেকে Coin কাটা
    if ($poolIsAgent) {
        $poolDeduct = $conn->prepare("UPDATE shonu_kaichila SET motta = motta - ? WHERE balakedara = ?");
        $poolDeduct->bind_param("di", $amount, $poolId);
    } else {
        $poolDeduct = $conn->prepare("UPDATE nirvahaka_shonu SET motta = motta - ? WHERE unohs = ?");
        $poolDeduct->bind_param("di", $amount, $poolId);
    }
    $poolDeduct->execute();
    if ($poolDeduct->affected_rows <= 0) throw new Exception('Pool coin deduction failed');

    $bal = $conn->prepare("UPDATE shonu_kaichila SET motta = motta + ? WHERE balakedara = ?");
    $bal->bind_param("di", $amount, $record['user_id']);
    $bal->execute();

    if ($bal->affected_rows <= 0) {
        // ✅ নতুন যোগ — যদি এই User-এর কোনো Balance Row-ই না থাকে,
        // তাহলে Update ব্যর্থ হওয়ার বদলে, প্রথমে একটা নতুন Row
        // তৈরি করে, তারপর সেই Amount বসানো হচ্ছে
        $checkRow = $conn->prepare("SELECT balakedara FROM shonu_kaichila WHERE balakedara = ?");
        $checkRow->bind_param("i", $record['user_id']);
        $checkRow->execute();
        $rowExists = $checkRow->get_result()->num_rows > 0;
        $checkRow->close();

        if (!$rowExists) {
            $createRow = $conn->prepare("INSERT INTO shonu_kaichila (balakedara, motta) VALUES (?, ?)");
            $createRow->bind_param("id", $record['user_id'], $amount);
            $createRow->execute();
            if ($createRow->affected_rows <= 0) {
                throw new Exception("Balance row create failed for user_id={$record['user_id']}: " . $conn->error);
            }
        } else {
            throw new Exception("Balance row exists but UPDATE affected 0 rows for user_id={$record['user_id']}: " . $conn->error);
        }
    }

    $conn->commit();
    // ✅ নতুন যোগ — পুরনো "thevani" Table-এও Status Update (Double-Approve এড়াতে)
    $conn->query("UPDATE thevani SET sthiti = '1' WHERE ullekha = '" . $conn->real_escape_string($trxid) . "'");

    smsLog("SUCCESS: TrxID=$trxid | User={$record['user_id']} | +$amount");

    // ✅ ঠিক করা হলো — Telegram File Upload করা না থাকলে যেন
    // পুরো System ভেঙে না যায়, তাই আগে Check করে নেওয়া হচ্ছে
    $telegramFile = __DIR__ . "/../../../telegram_notify.php";
    if (file_exists($telegramFile)) {
        require_once $telegramFile;
        if (function_exists('notifyDeposit')) {
            notifyDeposit($record['mobile'], $amount, $gateway, $trxid);
        }
    }

    echo json_encode(['code' => 0, 'msg' => 'Payment Verified & Balance Updated', 'amount' => $amount]);

} catch (Throwable $e) {
    $conn->rollback();
    smsLog("ERROR: " . $e->getMessage());
    echo json_encode(['code' => 1, 'msg' => 'Error: ' . $e->getMessage()]);
}
