<?php
declare(strict_types=1);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
require_once __DIR__ . '/../config.php';

// Car Race API (Red vs Blue) - 30s rounds
// Native Pakclub PKR integration with Wingo Profit Pool Logic

const CR_DURATION = 30; // seconds

// Auto-create tables if they don't exist
function ensure_cr_tables(PDO $pdo) {
    $pdo->exec("
    CREATE TABLE IF NOT EXISTS `car_race_bets` (
        `id` bigint(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        `user_id` bigint(20) NOT NULL,
        `round_id` bigint(20) UNSIGNED NOT NULL,
        `color` enum('red','blue') NOT NULL,
        `amount` decimal(18,2) NOT NULL,
        `payout` decimal(18,2) DEFAULT 0.00,
        `is_win` tinyint(1) DEFAULT NULL,
        `placed_at` datetime DEFAULT current_timestamp(),
        `settled_at` datetime DEFAULT NULL,
        INDEX idx_round (round_id),
        INDEX idx_user (user_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    
    CREATE TABLE IF NOT EXISTS `car_race_pool` (
        `id` tinyint(1) UNSIGNED NOT NULL PRIMARY KEY DEFAULT 1,
        `balance` decimal(18,2) DEFAULT 0.00
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    
    INSERT IGNORE INTO `car_race_pool` (`id`, `balance`) VALUES (1, 0.00);
    
    CREATE TABLE IF NOT EXISTS `car_race_rounds` (
        `id` bigint(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        `period_number` varchar(30) NOT NULL,
        `started_at` datetime NOT NULL,
        `ended_at` datetime NOT NULL,
        `result_color` enum('red','blue') DEFAULT NULL,
        `is_settled` tinyint(1) DEFAULT 0,
        `total_bet_red` decimal(18,2) DEFAULT 0.00,
        `total_bet_blue` decimal(18,2) DEFAULT 0.00,
        UNIQUE INDEX idx_period (period_number)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    ");
}

function current_user(): ?array {
    if (session_status() === PHP_SESSION_NONE) session_start();
    if (empty($_SESSION['user_id'])) return null;
    $pdo = db();
    $s = $pdo->prepare('SELECT * FROM users WHERE id=? LIMIT 1');
    $s->execute([$_SESSION['user_id']]);
    return $s->fetch() ?: null;
}

function json_response(array $data, int $status=200): void {
    http_response_code($status);
    header('Content-Type: application/json');
    echo json_encode($data, JSON_UNESCAPED_UNICODE);
    exit;
}

function db(): PDO {
    global $pdo;
    return $pdo;
}

function cr_current_period(): array {
    $now = microtime(true);
    $dur = CR_DURATION;
    $dayStart = (int)(floor($now / 86400) * 86400);
    $idx = (int)floor(($now - $dayStart) / $dur);
    $start = $dayStart + $idx * $dur;
    $end   = $start + $dur;
    $periodNumber = gmdate('Ymd', $start) . 'R' . str_pad((string)($idx + 1), 5, '0', STR_PAD_LEFT);
    return [
        'pn' => $periodNumber,
        'start' => $start,
        'end'   => $end,
        'rem'   => max(0, $end - $now),
    ];
}

function cr_ensure_round(): array {
    $pdo = db();
    ensure_cr_tables($pdo);
    
    $p = cr_current_period();
    $stmt = $pdo->prepare('SELECT * FROM car_race_rounds WHERE period_number = ? LIMIT 1');
    $stmt->execute([$p['pn']]);
    $row = $stmt->fetch();
    if ($row) return $row;

    try {
        $ins = $pdo->prepare('INSERT IGNORE INTO car_race_rounds (period_number, started_at, ended_at) VALUES (?, FROM_UNIXTIME(?), FROM_UNIXTIME(?))');
        $ins->execute([$p['pn'], $p['start'], $p['end']]);
    } catch (Throwable $e) {}

    $stmt->execute([$p['pn']]);
    return $stmt->fetch();
}

function cr_settle_round(int $roundId): void {
    $pdo = db();
    $pdo->beginTransaction();
    try {
        $s = $pdo->prepare('SELECT * FROM car_race_rounds WHERE id=? AND is_settled=0 FOR UPDATE');
        $s->execute([$roundId]);
        $round = $s->fetch();
        if (!$round) { $pdo->commit(); return; }

        $betsStmt = $pdo->prepare('SELECT * FROM car_race_bets WHERE round_id = ? AND settled_at IS NULL');
        $betsStmt->execute([$roundId]);
        $bets = $betsStmt->fetchAll();

        if (!$bets) {
            $rand = random_int(1, 100);
            $winColor = ($rand <= 50) ? 'red' : 'blue';
            $pdo->prepare('UPDATE car_race_rounds SET result_color=?, is_settled=1 WHERE id=?')
                ->execute([$winColor, $roundId]);
            $pdo->commit();
            return;
        }

        $totRed = 0.0; $totBlue = 0.0;
        foreach ($bets as $b) {
            if ($b['color'] === 'red')   $totRed   += (float)$b['amount'];
            if ($b['color'] === 'blue')  $totBlue  += (float)$b['amount'];
        }

        // --- WINGO WIN/LOSS DYNAMIC POOL LOGIC ---
        $pool_st = $pdo->query("SELECT balance FROM car_race_pool ORDER BY id ASC LIMIT 1 FOR UPDATE");
        $pool_balance = $pool_st ? (float)$pool_st->fetchColumn() : 0;
        
        $max_allowed_payout = $pool_balance * 0.70;
        
        $payout_red = $totRed * 2.0;
        $payout_blue = $totBlue * 2.0;
        
        $affordable = [];
        if ($payout_red <= $max_allowed_payout) {
            $affordable[] = ['color' => 'red', 'payout' => $payout_red];
        }
        if ($payout_blue <= $max_allowed_payout) {
            $affordable[] = ['color' => 'blue', 'payout' => $payout_blue];
        }
        
        // 15% random chance to force losing outcome even if pool balance allows payout
        $force_random_loss = (random_int(1, 100) <= 15);
        
        if (!empty($affordable) && !$force_random_loss) {
            usort($affordable, function($a, $b) { return $b['payout'] <=> $a['payout']; });
            $winColor = $affordable[0]['color'];
            
            if (count($affordable) > 1 && $affordable[0]['payout'] == $affordable[1]['payout']) {
                $winColor = (random_int(1, 100) <= 50) ? 'red' : 'blue';
            }
        } else {
            // Fallback: Pick whichever color has the lower payout requirement to save pool balance
            if ($payout_red < $payout_blue) {
                $winColor = 'red';
            } elseif ($payout_blue < $payout_red) {
                $winColor = 'blue';
            } else {
                $winColor = (random_int(1, 100) <= 50) ? 'red' : 'blue';
            }
        }

        $pdo->prepare('UPDATE car_race_rounds SET result_color=?, is_settled=1 WHERE id=?')
            ->execute([$winColor, $roundId]);

        $total_payout = 0;
        foreach ($bets as $b) {
            $isWin = ($b['color'] === $winColor);
            $won = $isWin ? (float)$b['amount'] * 2.0 : 0.0;
            
            $pdo->prepare("UPDATE car_race_bets SET is_win=?, payout=?, settled_at=NOW() WHERE id=?")
                ->execute([$isWin ? 1 : 0, $won, $b['id']]);

            if ($won > 0) {
                $total_payout += $won;
                $pdo->prepare('UPDATE users SET balance = balance + ? WHERE id = ?')
                    ->execute([$won, $b['user_id']]);
            }
        }

        if ($total_payout > 0) {
            $pdo->prepare("UPDATE car_race_pool SET balance = GREATEST(0, balance - ?) WHERE id=1")->execute([$total_payout]);
        }

        $pdo->commit();
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        throw $e;
    }
}

function cr_get_state(): void {
  try {
    $user = current_user();
    $round = cr_ensure_round();
    $pdo = db();
    $p = cr_current_period();

    // 1. Settle any open historical rounds matching past timelines
    $over = $pdo->prepare(
        'SELECT id FROM car_race_rounds WHERE is_settled=0 AND ended_at <= FROM_UNIXTIME(?) ORDER BY id LIMIT 10'
    );
    $over->execute([time()]);
    foreach ($over->fetchAll(PDO::FETCH_COLUMN) as $rid) {
        try {
            cr_settle_round((int)$rid);
        } catch (Throwable $e) {}
    }

    // 2. Fallback period-number validation to counter server timezone variations
    $over_periods = $pdo->prepare(
        'SELECT id FROM car_race_rounds WHERE is_settled=0 AND period_number < ? ORDER BY id LIMIT 10'
    );
    $over_periods->execute([$p['pn']]);
    foreach ($over_periods->fetchAll(PDO::FETCH_COLUMN) as $rid) {
        try {
            cr_settle_round((int)$rid);
        } catch (Throwable $e) {}
    }

    if (!empty($round['id'])) {
        $chk = $pdo->prepare('SELECT * FROM car_race_rounds WHERE id=? LIMIT 1');
        $chk->execute([$round['id']]);
        $round = $chk->fetch() ?: $round;
    }

    $histStmt = $pdo->query(
        "SELECT period_number,result_color,ended_at,total_bet_red,total_bet_blue
         FROM car_race_rounds
         WHERE is_settled=1 AND result_color IS NOT NULL
         ORDER BY id DESC LIMIT 10"
    );
    $history = $histStmt->fetchAll();

    $myBets = [];
    if ($user) {
        $b = $pdo->prepare(
            'SELECT b.id, b.user_id, b.round_id, b.color, b.amount AS amount_usd, b.payout AS payout_usd, b.is_win, b.placed_at, b.settled_at, r.period_number
             FROM car_race_bets b
             JOIN car_race_rounds r ON b.round_id = r.id
             WHERE b.user_id=? ORDER BY b.id DESC LIMIT 20'
         );
        $b->execute([$user['id']]);
        $myBets = $b->fetchAll();
    }

    json_response([
        'ok' => true,
        'server_time' => microtime(true),
        'period' => [
            'number' => $p['pn'],
            'start'  => $p['start'],
            'end'    => $p['end'],
            'remain' => $p['rem'],
        ],
        'history' => $history,
        'my_bets' => $myBets,
        'balance_usd' => $user ? (float)$user['balance'] : 0,
        'currency'    => 'Rs',
        'fx_rate'     => 1,
    ]);
  } catch (Throwable $ex) {
    json_response(['ok' => false, 'error' => 'State Error: ' . $ex->getMessage()], 500);
  }
}

function cr_place_bet(): void {
    $user = current_user();
    if (!$user) json_response(['ok' => false, 'error' => 'Login required'], 401);

    $in = json_decode(file_get_contents('php://input'), true) ?: [];
    $color = $_POST['color'] ?? $in['color'] ?? '';
    $amount = round((float)($_POST['amount'] ?? $in['amount'] ?? 0), 2);

    if (!in_array($color, ['red','blue'], true)) {
        json_response(['ok' => false, 'error' => 'Invalid color']);
    }
    if ($amount < 10) {
        json_response(['ok' => false, 'error' => 'Minimum bet is 10 PKR']);
    }

    $round = cr_ensure_round();
    $p = cr_current_period();
    $now = microtime(true);
    if ($p['end'] - $now <= 5) { 
        json_response(['ok' => false, 'error' => 'Betting closed for this round']);
    }

    $pdo = db();
    $pdo->beginTransaction();
    try {
        $balStmt = $pdo->prepare('SELECT balance FROM users WHERE id=? FOR UPDATE');
        $balStmt->execute([$user['id']]);
        $bal = (float)$balStmt->fetchColumn();
        if ($amount > $bal) {
            $pdo->rollBack();
            json_response(['ok' => false, 'error' => 'Insufficient balance']);
        }

        // --- REJECT BOTH SIDE BETTING ---
        $checkBet = $pdo->prepare('SELECT color FROM car_race_bets WHERE user_id = ? AND round_id = ? LIMIT 1');
        $checkBet->execute([$user['id'], $round['id']]);
        $existingColor = $checkBet->fetchColumn();

        if ($existingColor && $existingColor !== $color) {
            $pdo->rollBack();
            json_response(['ok' => false, 'error' => 'Illegal betting not allowed']);
        }

        // Deduct balance and wager requirements
        $pdo->prepare('UPDATE users SET balance = balance - ?, wager = GREATEST(0, wager - ?) WHERE id=?')
            ->execute([$amount, $amount, $user['id']]);

        $pdo->prepare('UPDATE car_race_pool SET balance = balance + ? WHERE id = 1')
            ->execute([$amount]);

        $pdo->prepare(
            "INSERT INTO car_race_bets (user_id, round_id, color, amount) VALUES (?, ?, ?, ?)"
        )->execute([$user['id'], $round['id'], $color, $amount]);

        $col = ($color === 'red') ? 'total_bet_red' : 'total_bet_blue';
        $pdo->prepare("UPDATE car_race_rounds SET $col = $col + ? WHERE id=?")
            ->execute([$amount, $round['id']]);

        $pdo->commit();
        json_response(['ok' => true, 'balance_usd' => $bal - $amount]);
    } catch (Throwable $ex) {
        $pdo->rollBack();
        json_response(['ok' => false, 'error' => 'DB error: ' . $ex->getMessage()], 500);
    }
}

$action = $_GET['action'] ?? '';
if (session_status() === PHP_SESSION_NONE) session_start();
$is_demo = isset($_SESSION['is_demo']) && $_SESSION['is_demo'] == 1;
if (!$is_demo && isset($_SESSION['user_id'])) {
    $uid_chk = (int)$_SESSION['user_id'];
    $is_demo = (int)db()->query("SELECT is_demo FROM users WHERE id = $uid_chk")->fetchColumn();
    if ($is_demo) $_SESSION['is_demo'] = 1;
}
if ($is_demo) {
    json_response(['ok' => false, 'error' => 'This account can only play WinGo.']);
}

if ($action === 'get_state') cr_get_state();
elseif ($action === 'place_bet') cr_place_bet();
elseif ($action === 'settle') json_response(['ok' => true]); 
else json_response(['ok' => false, 'error' => 'Invalid action'], 400);
