<?php
// api/callback.php - FINAL FIXED VERSION v6
ob_start();
ini_set('display_errors', 0);
error_reporting(E_ALL);

header('Content-Type: application/json; charset=utf-8');
date_default_timezone_set('Asia/Dhaka');

require '../includes/db.php';
ob_clean();

define('LOG_FILE', __DIR__ . '/callback_log.txt');

function write_log(string $text): void {
    file_put_contents(LOG_FILE, $text, FILE_APPEND | LOCK_EX);
}

// STRING arithmetic — float kabhi nahi banega
function safe_add(string $a, string $b): string {
    return bcadd($a, $b, 2);
}
function safe_sub(string $a, string $b): string {
    return bcsub($a, $b, 2);
}

// STRING return — "54246.44" exact, no garbage
function clean_balance(string $val): string {
    return bcadd($val, '0', 2);
}

// JSON mein string "54246.44" → number 54246.44 (clean)
function build_json(array $data): string {
    return json_encode($data, JSON_NUMERIC_CHECK | JSON_UNESCAPED_UNICODE);
}

// ==========================================
// LOGGING
// ==========================================
$current_time = date('Y-m-d h:i:s A');
$log_text = "\n[$current_time] =========================================\n";

$raw_input = file_get_contents('php://input');
$data = json_decode($raw_input, true);
$log_text .= "RAW INPUT: " . $raw_input . "\n";

if (!$data || !is_array($data)) {
    write_log($log_text . "ERROR: Invalid JSON\n");
    echo build_json(['credit_amount' => 0, 'error' => 'Invalid JSON']);
    exit;
}

// ==========================================
// DATA EXTRACTION
// ==========================================
$game_round     = trim($data['game_round'] ?? '');
$member_account = trim($data['member_account'] ?? '');
$game_uid       = trim($data['game_uid'] ?? '');
$timestamp      = trim($data['timestamp'] ?? '');
$bet_amount     = clean_balance((string)floatval($data['bet_amount'] ?? 0));
$win_amount     = clean_balance((string)floatval($data['win_amount'] ?? 0));

if (empty($member_account) || empty($game_round) || empty($game_uid)) {
    write_log($log_text . "ERROR: Missing required fields\n");
    echo build_json(['credit_amount' => 0, 'error' => 'Missing required fields']);
    exit;
}

$log_text .= "DATA -> User: $member_account | Game: $game_uid | Round: $game_round | Bet: $bet_amount | Win: $win_amount\n";

$unique_tx_key = md5($game_round . $game_uid . $bet_amount . $win_amount . $timestamp);
$log_text .= "TX_KEY: $unique_tx_key\n";

// ==========================================
// DATABASE TRANSACTION
// ==========================================
$conn->begin_transaction();
$old_balance = '0.00';

try {
    // USER FETCH — integer bind
    $user = null;

    if (is_numeric($member_account)) {
        $stmt = $conn->prepare("SELECT id, balance FROM users WHERE id = ? FOR UPDATE");
        $user_id_int = (int)$member_account;
        $stmt->bind_param("i", $user_id_int);
        $stmt->execute();
        $result = $stmt->get_result();
        if ($result->num_rows > 0) {
            $user = $result->fetch_assoc();
        }
        $stmt->close();
    }

    // Fallback: username ya phone se
    if (!$user) {
        $stmt2 = $conn->prepare("SELECT id, balance FROM users WHERE username = ? OR phone = ? FOR UPDATE");
        $stmt2->bind_param("ss", $member_account, $member_account);
        $stmt2->execute();
        $result2 = $stmt2->get_result();
        if ($result2->num_rows > 0) {
            $user = $result2->fetch_assoc();
        }
        $stmt2->close();
    }

    if (!$user) {
        throw new Exception("User ($member_account) not found in DB");
    }

    $db_user_id  = (int)$user['id'];
    $old_balance = clean_balance((string)$user['balance']); // "54236.44" exact string
    $new_balance = $old_balance;

    $log_text .= "USER -> DB ID: $db_user_id | Balance: $old_balance\n";

    // DUPLICATE CHECK
    $check_stmt = $conn->prepare("SELECT id FROM game_bet_history WHERE tx_key = ? LIMIT 1");
    $check_stmt->bind_param("s", $unique_tx_key);
    $check_stmt->execute();
    $is_duplicate = ($check_stmt->get_result()->num_rows > 0);
    $check_stmt->close();

    if ($is_duplicate) {
        $log_text .= "ACTION -> DUPLICATE DETECTED. Returning current balance: $old_balance\n";
    } else {

        // PROCESS BET
        if (bccomp($bet_amount, '0', 2) > 0) {
            if (bccomp($new_balance, $bet_amount, 2) >= 0) {
                $new_balance = safe_sub($new_balance, $bet_amount);
                $log_text .= "ACTION -> BET: $bet_amount deducted. Balance: $new_balance\n";
            } else {
                throw new Exception("Insufficient balance. Have: $new_balance, Need: $bet_amount");
            }
        }

        // PROCESS WIN
        if (bccomp($win_amount, '0', 2) > 0) {
            $new_balance = safe_add($new_balance, $win_amount);
            $log_text .= "ACTION -> WIN: $win_amount added. Balance: $new_balance\n";
        }

        // UPDATE BALANCE — DB ke liye float zaroor chahiye
        $new_bal_db = (float)$new_balance;
        $update_stmt = $conn->prepare("UPDATE users SET balance = ? WHERE id = ?");
        $update_stmt->bind_param("di", $new_bal_db, $db_user_id);
        $update_stmt->execute();

        if ($update_stmt->affected_rows === 0) {
            throw new Exception("Balance update failed for user ID: $db_user_id");
        }
        $update_stmt->close();

        // INSERT HISTORY
        $old_b = (float)$old_balance;
        $new_b = (float)$new_balance;
        $bet_f = (float)$bet_amount;
        $win_f = (float)$win_amount;

        $hist_stmt = $conn->prepare(
            "INSERT INTO game_bet_history 
             (user_id, game_uid, round_id, bet_amount, win_amount, balance_before, balance_after, tx_key, status, created_at) 
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'processed', NOW())"
        );
        $hist_stmt->bind_param(
            "issdddds",
            $db_user_id,
            $game_uid,
            $game_round,
            $bet_f,
            $win_f,
            $old_b,
            $new_b,
            $unique_tx_key
        );

        if (!$hist_stmt->execute()) {
            if ($conn->errno === 1062) {
                $log_text .= "ACTION -> Race condition blocked by DB UNIQUE KEY.\n";
                $conn->rollback();

                $bal_stmt = $conn->prepare("SELECT balance FROM users WHERE id = ?");
                $bal_stmt->bind_param("i", $db_user_id);
                $bal_stmt->execute();
                $bal_row      = $bal_stmt->get_result()->fetch_assoc();
                $race_balance = clean_balance((string)($bal_row['balance'] ?? $old_balance));

                $log_text .= "FINAL RESPONSE (race): " . build_json(['credit_amount' => $race_balance, 'balance' => $race_balance, 'status' => 'duplicate']) . "\n=========================================\n";
                write_log($log_text);
                echo build_json(['credit_amount' => $race_balance, 'balance' => $race_balance, 'status' => 'duplicate', 'timestamp' => round(microtime(true) * 1000)]);
                exit;
            }
            throw new Exception("History insert failed: " . $conn->error);
        }
        $hist_stmt->close();

        $log_text .= "DB -> Updated. Old: $old_balance → New: $new_balance\n";
    }

    $conn->commit();
    $final_balance = $is_duplicate ? $old_balance : $new_balance;

} catch (Exception $e) {
    $conn->rollback();
    $log_text .= "ERROR: " . $e->getMessage() . "\n=========================================\n";
    write_log($log_text);
    echo build_json(['credit_amount' => clean_balance($old_balance), 'error' => $e->getMessage()]);
    exit;
}

// FINAL RESPONSE
// clean_balance() = "54246.44" string
// JSON_NUMERIC_CHECK = 54246.44 clean number — kabhi garbage nahi
$final_clean = clean_balance($final_balance);

$response_data = [
    'credit_amount' => $final_clean,
    'balance'       => $final_clean,
    'status'        => 'success',
    'timestamp'     => round(microtime(true) * 1000)
];

$json_response = build_json($response_data);
$log_text .= "FINAL RESPONSE: $json_response\n=========================================\n";
write_log($log_text);

echo $json_response;
exit;