<?php
require_once __DIR__ . '/../config/database.php';

header('Content-Type: application/json');

$token = get_auth_token();

if (!$token) {
    http_response_code(401);
    echo json_encode(['error' => 'unauthorized']);
    exit;
}

$userRes = supabase_auth('user', [], $token, 'GET');
$userId = $userRes['data']['id'] ?? null;
$userName = $userRes['data']['user_metadata']['display_name'] ?? 'لاعب';

if (!$userId) {
    http_response_code(401);
    echo json_encode(['error' => 'invalid_token']);
    exit;
}

if ($_SERVER['REQUEST_METHOD'] === 'GET') {
    $action = $_GET['action'] ?? '';
    handleGet($action, $userId, $token);
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $input = json_decode(file_get_contents('php://input'), true);
    $action = $input['action'] ?? '';
    handlePost($action, $input, $userId, $userName, $token);
} else {
    http_response_code(405);
    echo json_encode(['error' => 'method_not_allowed']);
}

function handleGet($action, $userId, $token) {
    switch ($action) {
        case 'status':
            $matchId = $_GET['match_id'] ?? '';
            if (!$matchId) {
                http_response_code(400);
                echo json_encode(['error' => 'match_id_required']);
                return;
            }
            $res = supabase_rest('GET', "ludo_matches?id=eq.{$matchId}&select=*", [], $token);
            if (empty($res['data'])) {
                http_response_code(404);
                echo json_encode(['error' => 'not_found']);
                return;
            }
            echo json_encode(['ok' => true, 'match' => $res['data'][0]]);
            break;

        default:
            http_response_code(400);
            echo json_encode(['error' => 'invalid_action']);
    }
}

function handlePost($action, $input, $userId, $userName, $token) {
    switch ($action) {
        case 'create':
            createRoom($input, $userId, $userName, $token);
            break;
        case 'join':
            joinRoom($input, $userId, $userName, $token);
            break;
        case 'start':
            startGame($input, $userId, $token);
            break;
        case 'roll':
            rollDice($input, $userId, $token);
            break;
        case 'move':
            movePiece($input, $userId, $token);
            break;
        case 'leave':
            leaveGame($input, $userId, $token);
            break;
        case 'chat':
            sendChat($input, $userId, $userName, $token);
            break;
        case 'matchmake':
            matchmake($input, $userId, $userName, $token);
            break;
        default:
            http_response_code(400);
            echo json_encode(['error' => 'invalid_action']);
    }
}

function generateRoomCode() {
    $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
    $code = '';
    for ($i = 0; $i < 6; $i++) {
        $code .= $chars[random_int(0, strlen($chars) - 1)];
    }
    return $code;
}

function createRoom($input, $userId, $userName, $token) {
    $playerCount = intval($input['player_count'] ?? 4);
    if ($playerCount < 2) $playerCount = 2;
    if ($playerCount > 4) $playerCount = 4;

    $bots = $input['bots'] ?? [];
    $roomCode = generateRoomCode();

    $players = [
        ['id' => $userId, 'name' => $userName, 'color' => 'P1', 'type' => 'human', 'connected' => true]
    ];

    foreach ($bots as $bot) {
        $colorIdx = count($players);
        $colors = ['P1', 'P2', 'P3', 'P4'];
        if ($colorIdx >= $playerCount) break;
        $players[] = [
            'id' => 'bot_' . $colorIdx,
            'name' => $bot['name'] ?? ('بوت ' . $colorIdx),
            'color' => $colors[$colorIdx],
            'type' => 'bot',
            'difficulty' => $bot['difficulty'] ?? 'easy',
            'connected' => true
        ];
    }

    $positions = [];
    $basePositions = ['P1' => [500,501,502,503], 'P2' => [600,601,602,603], 'P3' => [700,701,702,703], 'P4' => [800,801,802,803]];
    $colors = ['P1','P2','P3','P4'];
    for ($i = 0; $i < $playerCount; $i++) {
        $positions[$colors[$i]] = $basePositions[$colors[$i]];
    }

    $data = [
        'room_code' => $roomCode,
        'status' => 'waiting',
        'player_count' => $playerCount,
        'players' => json_encode($players),
        'current_turn' => 0,
        'positions' => json_encode($positions),
        'moves' => json_encode([]),
        'winners' => json_encode([]),
        'game_state' => json_encode(['phase' => 'waiting']),
        'chat' => json_encode([]),
        'host_id' => $userId
    ];

    $res = supabase_rest('POST', 'ludo_matches', $data, $token);

    if ($res['status'] >= 400) {
        http_response_code(500);
        echo json_encode(['error' => 'create_failed', 'details' => $res['data']]);
        return;
    }

    echo json_encode(['ok' => true, 'match' => $res['data'][0], 'room_code' => $roomCode]);
}

function joinRoom($input, $userId, $userName, $token) {
    $roomCode = strtoupper(trim($input['room_code'] ?? ''));
    if (!$roomCode) {
        http_response_code(400);
        echo json_encode(['error' => 'room_code_required']);
        return;
    }

    $res = supabase_rest('GET', "ludo_matches?room_code=eq.{$roomCode}&status=eq.waiting&select=*", [], $token);
    if (empty($res['data'])) {
        http_response_code(404);
        echo json_encode(['error' => 'room_not_found']);
        return;
    }

    $match = $res['data'][0];
    $players = json_decode($match['players'], true);

    foreach ($players as $p) {
        if ($p['id'] === $userId) {
            echo json_encode(['ok' => true, 'match' => $match, 'already_joined' => true]);
            return;
        }
    }

    if (count($players) >= $match['player_count']) {
        http_response_code(400);
        echo json_encode(['error' => 'room_full']);
        return;
    }

    $colors = ['P1','P2','P3','P4'];
    $usedColors = array_map(function($p) { return $p['color']; }, $players);
    $nextColor = '';
    foreach ($colors as $c) {
        if (!in_array($c, $usedColors)) { $nextColor = $c; break; }
    }

    $players[] = [
        'id' => $userId,
        'name' => $userName,
        'color' => $nextColor,
        'type' => 'human',
        'connected' => true
    ];

    $update = ['players' => json_encode($players)];
    $patchRes = supabase_rest('PATCH', "ludo_matches?id=eq.{$match['id']}", $update, $token);

    if ($patchRes['status'] >= 400) {
        http_response_code(500);
        echo json_encode(['error' => 'join_failed']);
        return;
    }

    echo json_encode(['ok' => true, 'match' => $patchRes['data'][0]]);
}

function startGame($input, $userId, $token) {
    $matchId = $input['match_id'] ?? '';
    if (!$matchId) {
        http_response_code(400);
        echo json_encode(['error' => 'match_id_required']);
        return;
    }

    $res = supabase_rest('GET', "ludo_matches?id=eq.{$matchId}&select=*", [], $token);
    if (empty($res['data'])) {
        http_response_code(404);
        echo json_encode(['error' => 'not_found']);
        return;
    }

    $match = $res['data'][0];
    if ($match['host_id'] !== $userId) {
        http_response_code(403);
        echo json_encode(['error' => 'not_host']);
        return;
    }

    if ($match['status'] !== 'waiting') {
        http_response_code(400);
        echo json_encode(['error' => 'already_started']);
        return;
    }

    $players = json_decode($match['players'], true);

    // Fill remaining slots with bots
    $colors = ['P1','P2','P3','P4'];
    $usedColors = array_map(function($p) { return $p['color']; }, $players);
    $botIdx = count($players);
    while (count($players) < $match['player_count']) {
        $nextColor = '';
        foreach ($colors as $c) {
            if (!in_array($c, $usedColors)) { $nextColor = $c; break; }
        }
        $usedColors[] = $nextColor;
        $players[] = [
            'id' => 'bot_' . $botIdx,
            'name' => 'بوت ' . $botIdx,
            'color' => $nextColor,
            'type' => 'bot',
            'difficulty' => 'easy',
            'connected' => true
        ];
        $botIdx++;
    }

    $update = [
        'status' => 'in_progress',
        'players' => json_encode($players),
        'game_state' => json_encode(['phase' => 'dice_not_rolled', 'started_at' => date('c')])
    ];

    $patchRes = supabase_rest('PATCH', "ludo_matches?id=eq.{$matchId}", $update, $token);
    echo json_encode(['ok' => true, 'match' => $patchRes['data'][0]]);
}

function rollDice($input, $userId, $token) {
    $matchId = $input['match_id'] ?? '';
    $match = getAndValidateMatch($matchId, $userId, $token);
    if (!$match) return;

    $players = json_decode($match['players'], true);
    $currentTurn = $match['current_turn'];
    $currentPlayer = $players[$currentTurn];

    if ($currentPlayer['id'] !== $userId) {
        http_response_code(400);
        echo json_encode(['error' => 'not_your_turn']);
        return;
    }

    $gameState = json_decode($match['game_state'], true);
    if (($gameState['phase'] ?? '') !== 'dice_not_rolled') {
        http_response_code(400);
        echo json_encode(['error' => 'already_rolled']);
        return;
    }

    $diceValue = random_int(1, 6);
    $gameState['phase'] = 'dice_rolled';
    $gameState['last_dice'] = $diceValue;
    $gameState['last_roll_at'] = date('c');

    $update = [
        'dice_value' => $diceValue,
        'game_state' => json_encode($gameState)
    ];

    $patchRes = supabase_rest('PATCH', "ludo_matches?id=eq.{$matchId}", $update, $token);
    echo json_encode(['ok' => true, 'dice_value' => $diceValue, 'match' => $patchRes['data'][0]]);
}

function movePiece($input, $userId, $token) {
    $matchId = $input['match_id'] ?? '';
    $pieceIdx = intval($input['piece'] ?? -1);

    $match = getAndValidateMatch($matchId, $userId, $token);
    if (!$match) return;

    $players = json_decode($match['players'], true);
    $currentTurn = $match['current_turn'];
    $currentPlayer = $players[$currentTurn];

    if ($currentPlayer['id'] !== $userId) {
        http_response_code(400);
        echo json_encode(['error' => 'not_your_turn']);
        return;
    }

    $gameState = json_decode($match['game_state'], true);
    if (($gameState['phase'] ?? '') !== 'dice_rolled') {
        http_response_code(400);
        echo json_encode(['error' => 'dice_not_rolled']);
        return;
    }

    $positions = json_decode($match['positions'], true);
    $moves = json_decode($match['moves'], true);
    $winners = json_decode($match['winners'], true);
    $diceValue = $match['dice_value'];
    $playerColor = $currentPlayer['color'];

    $basePositions = ['P1' => [500,501,502,503], 'P2' => [600,601,602,603], 'P3' => [700,701,702,703], 'P4' => [800,801,802,803]];
    $startPositions = ['P1' => 0, 'P2' => 13, 'P3' => 26, 'P4' => 39];
    $turningPoints = ['P1' => 50, 'P2' => 11, 'P3' => 24, 'P4' => 37];
    $homeEntrance = ['P1' => [100,101,102,103,104], 'P2' => [200,201,202,203,204], 'P3' => [300,301,302,303,304], 'P4' => [400,401,402,403,404]];
    $homePositions = ['P1' => 105, 'P2' => 205, 'P3' => 305, 'P4' => 405];
    $safePositions = [0, 8, 13, 21, 26, 34, 39, 47];

    if ($pieceIdx < 0 || $pieceIdx > 3) {
        http_response_code(400);
        echo json_encode(['error' => 'invalid_piece']);
        return;
    }

    $currentPos = $positions[$playerColor][$pieceIdx];
    $isInBase = in_array($currentPos, $basePositions[$playerColor]);
    $newPos = null;

    if ($isInBase) {
        if ($diceValue !== 6) {
            http_response_code(400);
            echo json_encode(['error' => 'need_six_to_exit']);
            return;
        }
        $newPos = $startPositions[$playerColor];
    } else {
        $newPos = calculateNewPos($playerColor, $currentPos, $diceValue, $turningPoints, $homeEntrance, $homePositions);
    }

    if ($newPos === null) {
        http_response_code(400);
        echo json_encode(['error' => 'invalid_move']);
        return;
    }

    $positions[$playerColor][$pieceIdx] = $newPos;
    $killed = null;

    // Check kills
    if ($newPos >= 0 && $newPos <= 51 && !in_array($newPos, $safePositions)) {
        $activePlayers = array_map(function($p) { return $p['color']; }, $players);
        foreach ($activePlayers as $oppColor) {
            if ($oppColor === $playerColor) continue;
            if (!isset($positions[$oppColor])) continue;
            for ($j = 0; $j < 4; $j++) {
                if ($positions[$oppColor][$j] === $newPos) {
                    $positions[$oppColor][$j] = $basePositions[$oppColor][$j];
                    $killed = ['player' => $oppColor, 'piece' => $j];
                    break 2;
                }
            }
        }
    }

    $moveRecord = [
        'player' => $playerColor,
        'piece' => $pieceIdx,
        'from' => $currentPos,
        'to' => $newPos,
        'dice' => $diceValue,
        'kill' => $killed,
        'at' => date('c')
    ];
    $moves[] = $moveRecord;

    // Check if player finished
    $reachedHome = ($newPos === $homePositions[$playerColor]);
    $playerFinished = true;
    for ($i = 0; $i < 4; $i++) {
        if ($positions[$playerColor][$i] !== $homePositions[$playerColor]) {
            $playerFinished = false;
            break;
        }
    }

    if ($playerFinished && !in_array($playerColor, $winners)) {
        $winners[] = $playerColor;
    }

    // Determine next turn
    $extraTurn = ($diceValue === 6 || $killed !== null || $reachedHome) && !$playerFinished;
    $consecutiveSixes = intval($gameState['consecutive_sixes'] ?? 0);

    if ($diceValue === 6) {
        $consecutiveSixes++;
        if ($consecutiveSixes >= 3) {
            $extraTurn = false;
            $consecutiveSixes = 0;
        }
    } else {
        $consecutiveSixes = 0;
    }

    $activePlayers = array_map(function($p) { return $p['color']; }, $players);
    $remaining = array_filter($activePlayers, function($c) use ($winners) { return !in_array($c, $winners); });

    $gameOver = count($remaining) <= 1;
    $nextTurn = $currentTurn;

    if (!$extraTurn || $playerFinished) {
        $consecutiveSixes = 0;
        $totalPlayers = count($players);
        $nextTurn = ($currentTurn + 1) % $totalPlayers;
        $attempts = 0;
        while (in_array($players[$nextTurn]['color'], $winners) && $attempts < $totalPlayers) {
            $nextTurn = ($nextTurn + 1) % $totalPlayers;
            $attempts++;
        }
    }

    $gameState['phase'] = 'dice_not_rolled';
    $gameState['consecutive_sixes'] = $consecutiveSixes;
    $gameState['last_move_at'] = date('c');

    $update = [
        'positions' => json_encode($positions),
        'moves' => json_encode($moves),
        'winners' => json_encode($winners),
        'current_turn' => $nextTurn,
        'game_state' => json_encode($gameState)
    ];

    if ($gameOver) {
        foreach ($remaining as $c) {
            if (!in_array($c, $winners)) $winners[] = $c;
        }
        $update['winners'] = json_encode($winners);
        $update['status'] = 'completed';
        $update['completed_at'] = date('c');
        $update['result'] = $winners[0] . '_wins';
        $gameState['phase'] = 'game_over';
        $update['game_state'] = json_encode($gameState);
    }

    $patchRes = supabase_rest('PATCH', "ludo_matches?id=eq.{$matchId}", $update, $token);

    $response = ['ok' => true, 'match' => $patchRes['data'][0], 'move' => $moveRecord];
    if ($killed) $response['killed'] = $killed;
    if ($gameOver) $response['game_over'] = true;

    // Update ludo ratings for all human players when game ends
    if ($gameOver) {
        updateLudoRatings($players, $winners, $userId);
    }

    echo json_encode($response);

    // Execute bot turns if next player is a bot
    if (!$gameOver && $players[$nextTurn]['type'] === 'bot') {
        executeBotTurns($matchId, $patchRes['data'][0], $token);
    }
}

function updateLudoRatings($players, $winners, $currentUserId) {
    foreach ($players as $p) {
        if ($p['type'] !== 'human') continue;
        $pid = $p['id'];
        $color = $p['color'];
        $isWinner = isset($winners[0]) && $winners[0] === $color;
        $result = $isWinner ? 'win' : 'loss';

        $existing = supabase_rest('GET', "player_game_ratings?player_id=eq.{$pid}&game_key=eq.ludo&mode=eq.default&select=id,rating,games_played,wins,losses,draws,win_streak,best_win_streak", [], SUPABASE_SERVICE_KEY);

        if (!empty($existing['data'])) {
            $pgr = $existing['data'][0];
            $currentRating = $pgr['rating'];
            $gp = $pgr['games_played'];
            $kFactor = ($gp < 30) ? 40 : 20;
            $opponentRating = 1200;
            $expected = 1.0 / (1.0 + pow(10, ($opponentRating - $currentRating) / 400.0));
            $actual = $isWinner ? 1.0 : 0.0;
            $change = (int)round($kFactor * ($actual - $expected));
            $newRating = max(0, $currentRating + $change);
            $newWinStreak = $isWinner ? ($pgr['win_streak'] + 1) : 0;
            $bestStreak = max($pgr['best_win_streak'], $newWinStreak);

            supabase_rest('PATCH', "player_game_ratings?id=eq.{$pgr['id']}", [
                'rating' => $newRating,
                'games_played' => $gp + 1,
                'wins' => $pgr['wins'] + ($isWinner ? 1 : 0),
                'losses' => $pgr['losses'] + ($isWinner ? 0 : 1),
                'win_streak' => $newWinStreak,
                'best_win_streak' => $bestStreak,
                'last_played_at' => date('c'),
                'updated_at' => date('c'),
            ], SUPABASE_SERVICE_KEY);
        } else {
            $newRating = $isWinner ? 1220 : 1180;
            supabase_rest('POST', 'player_game_ratings', [
                'player_id' => $pid,
                'game_key' => 'ludo',
                'mode' => 'default',
                'rating' => $newRating,
                'games_played' => 1,
                'wins' => $isWinner ? 1 : 0,
                'losses' => $isWinner ? 0 : 1,
                'draws' => 0,
                'win_streak' => $isWinner ? 1 : 0,
                'best_win_streak' => $isWinner ? 1 : 0,
                'last_played_at' => date('c'),
            ], SUPABASE_SERVICE_KEY);
        }

        // XP + coins for ludo
        $profileRes = supabase_rest('GET', "profiles?id=eq.{$pid}&select=id,xp,level,coins", [], SUPABASE_SERVICE_KEY);
        if (!empty($profileRes['data'])) {
            $profile = $profileRes['data'][0];
            $xpAward = 50 + ($isWinner ? 30 : 0);
            $coinsAward = $isWinner ? 15 : 0;
            $pUpdate = [
                'xp' => ($profile['xp'] ?? 0) + $xpAward,
                'total_games_played' => ($profile['total_games_played'] ?? 0) + 1,
            ];
            if ($isWinner) {
                $pUpdate['total_wins'] = ($profile['total_wins'] ?? 0) + 1;
                $pUpdate['coins'] = ($profile['coins'] ?? 0) + $coinsAward;
            } else {
                $pUpdate['total_losses'] = ($profile['total_losses'] ?? 0) + 1;
            }
            supabase_rest('PATCH', "profiles?id=eq.{$pid}", $pUpdate, SUPABASE_SERVICE_KEY);
        }
    }
}

function executeBotTurns($matchId, $match, $token) {
    $maxIterations = 20;
    $iteration = 0;

    while ($iteration < $maxIterations) {
        $iteration++;
        $players = json_decode($match['players'], true);
        $currentTurn = $match['current_turn'];
        $currentPlayer = $players[$currentTurn];

        if ($currentPlayer['type'] !== 'bot') break;
        if ($match['status'] === 'completed') break;

        $positions = json_decode($match['positions'], true);
        $gameState = json_decode($match['game_state'], true);
        $moves = json_decode($match['moves'], true);
        $winners = json_decode($match['winners'], true);
        $playerColor = $currentPlayer['color'];

        $basePositions = ['P1' => [500,501,502,503], 'P2' => [600,601,602,603], 'P3' => [700,701,702,703], 'P4' => [800,801,802,803]];
        $startPositions = ['P1' => 0, 'P2' => 13, 'P3' => 26, 'P4' => 39];
        $turningPoints = ['P1' => 50, 'P2' => 11, 'P3' => 24, 'P4' => 37];
        $homeEntrance = ['P1' => [100,101,102,103,104], 'P2' => [200,201,202,203,204], 'P3' => [300,301,302,303,304], 'P4' => [400,401,402,403,404]];
        $homePositions = ['P1' => 105, 'P2' => 205, 'P3' => 305, 'P4' => 405];
        $safePositions = [0, 8, 13, 21, 26, 34, 39, 47];

        // Bot rolls dice
        $diceValue = random_int(1, 6);

        // Find eligible pieces
        $eligible = [];
        for ($i = 0; $i < 4; $i++) {
            $pos = $positions[$playerColor][$i];
            if ($pos === $homePositions[$playerColor]) continue;
            $isInBase = in_array($pos, $basePositions[$playerColor]);
            if ($isInBase) {
                if ($diceValue === 6) $eligible[] = $i;
                continue;
            }
            $newPos = calculateNewPos($playerColor, $pos, $diceValue, $turningPoints, $homeEntrance, $homePositions);
            if ($newPos !== null) $eligible[] = $i;
        }

        if (empty($eligible)) {
            // No moves, skip turn
            $consecutiveSixes = 0;
            $nextTurn = findNextTurn($currentTurn, $players, $winners);
            $gameState['phase'] = 'dice_not_rolled';
            $gameState['consecutive_sixes'] = 0;

            $update = [
                'current_turn' => $nextTurn,
                'dice_value' => $diceValue,
                'game_state' => json_encode($gameState)
            ];
            $patchRes = supabase_rest('PATCH', "ludo_matches?id=eq.{$matchId}", $update, $token);
            $match = $patchRes['data'][0];
            continue;
        }

        // Bot picks piece (simple: random for easy, best for hard)
        $difficulty = $currentPlayer['difficulty'] ?? 'easy';
        $chosenPiece = $eligible[0];
        if ($difficulty === 'easy') {
            $chosenPiece = $eligible[array_rand($eligible)];
        } else {
            $bestScore = -999;
            foreach ($eligible as $pi) {
                $score = scoreBotMove($playerColor, $pi, $diceValue, $positions, $players, $basePositions, $startPositions, $homeEntrance, $homePositions, $safePositions);
                if ($score > $bestScore) {
                    $bestScore = $score;
                    $chosenPiece = $pi;
                }
            }
        }

        // Execute move
        $currentPos = $positions[$playerColor][$chosenPiece];
        $isInBase = in_array($currentPos, $basePositions[$playerColor]);
        $newPos = $isInBase ? $startPositions[$playerColor] : calculateNewPos($playerColor, $currentPos, $diceValue, $turningPoints, $homeEntrance, $homePositions);

        $positions[$playerColor][$chosenPiece] = $newPos;
        $killed = null;

        if ($newPos >= 0 && $newPos <= 51 && !in_array($newPos, $safePositions)) {
            foreach ($players as $p) {
                if ($p['color'] === $playerColor) continue;
                $oppColor = $p['color'];
                if (!isset($positions[$oppColor])) continue;
                for ($j = 0; $j < 4; $j++) {
                    if ($positions[$oppColor][$j] === $newPos) {
                        $positions[$oppColor][$j] = $basePositions[$oppColor][$j];
                        $killed = ['player' => $oppColor, 'piece' => $j];
                        break 2;
                    }
                }
            }
        }

        $moves[] = [
            'player' => $playerColor,
            'piece' => $chosenPiece,
            'from' => $currentPos,
            'to' => $newPos,
            'dice' => $diceValue,
            'kill' => $killed,
            'at' => date('c'),
            'bot' => true
        ];

        $reachedHome = ($newPos === $homePositions[$playerColor]);
        $playerFinished = true;
        for ($i = 0; $i < 4; $i++) {
            if ($positions[$playerColor][$i] !== $homePositions[$playerColor]) {
                $playerFinished = false;
                break;
            }
        }
        if ($playerFinished && !in_array($playerColor, $winners)) {
            $winners[] = $playerColor;
        }

        $extraTurn = ($diceValue === 6 || $killed !== null || $reachedHome) && !$playerFinished;
        $consecutiveSixes = intval($gameState['consecutive_sixes'] ?? 0);
        if ($diceValue === 6) {
            $consecutiveSixes++;
            if ($consecutiveSixes >= 3) { $extraTurn = false; $consecutiveSixes = 0; }
        } else {
            $consecutiveSixes = 0;
        }

        $activePlayers = array_map(function($p) { return $p['color']; }, $players);
        $remaining = array_filter($activePlayers, function($c) use ($winners) { return !in_array($c, $winners); });
        $gameOver = count($remaining) <= 1;

        $nextTurn = $currentTurn;
        if (!$extraTurn || $playerFinished) {
            $consecutiveSixes = 0;
            $nextTurn = findNextTurn($currentTurn, $players, $winners);
        }

        $gameState['phase'] = 'dice_not_rolled';
        $gameState['consecutive_sixes'] = $consecutiveSixes;
        $gameState['last_move_at'] = date('c');

        $update = [
            'positions' => json_encode($positions),
            'moves' => json_encode($moves),
            'winners' => json_encode($winners),
            'current_turn' => $nextTurn,
            'dice_value' => $diceValue,
            'game_state' => json_encode($gameState)
        ];

        if ($gameOver) {
            foreach ($remaining as $c) {
                if (!in_array($c, $winners)) $winners[] = $c;
            }
            $update['winners'] = json_encode($winners);
            $update['status'] = 'completed';
            $update['completed_at'] = date('c');
            $update['result'] = $winners[0] . '_wins';
            $gameState['phase'] = 'game_over';
            $update['game_state'] = json_encode($gameState);
        }

        $patchRes = supabase_rest('PATCH', "ludo_matches?id=eq.{$matchId}", $update, $token);
        $match = $patchRes['data'][0];

        if ($gameOver) break;
    }
}

function findNextTurn($currentTurn, $players, $winners) {
    $total = count($players);
    $next = ($currentTurn + 1) % $total;
    $attempts = 0;
    while (in_array($players[$next]['color'], $winners) && $attempts < $total) {
        $next = ($next + 1) % $total;
        $attempts++;
    }
    return $next;
}

function scoreBotMove($playerColor, $pieceIdx, $diceValue, $positions, $players, $basePositions, $startPositions, $homeEntrance, $homePositions, $safePositions) {
    $score = 0;
    $currentPos = $positions[$playerColor][$pieceIdx];
    $isInBase = in_array($currentPos, $basePositions[$playerColor]);

    if ($isInBase) {
        $score += 30;
        $startPos = $startPositions[$playerColor];
        foreach ($players as $p) {
            if ($p['color'] === $playerColor) continue;
            if (!isset($positions[$p['color']])) continue;
            for ($j = 0; $j < 4; $j++) {
                if ($positions[$p['color']][$j] === $startPos) { $score += 50; break 2; }
            }
        }
        return $score;
    }

    $turningPoints = ['P1' => 50, 'P2' => 11, 'P3' => 24, 'P4' => 37];
    $newPos = calculateNewPos($playerColor, $currentPos, $diceValue, $turningPoints, $homeEntrance, $homePositions);
    if ($newPos === null) return -999;

    if ($newPos === $homePositions[$playerColor]) return 100;
    if (in_array($newPos, $homeEntrance[$playerColor])) $score += 25;

    if ($newPos >= 0 && $newPos <= 51) {
        foreach ($players as $p) {
            if ($p['color'] === $playerColor) continue;
            if (!isset($positions[$p['color']])) continue;
            for ($j = 0; $j < 4; $j++) {
                if ($positions[$p['color']][$j] === $newPos && !in_array($newPos, $safePositions)) {
                    $score += 50;
                    break 2;
                }
            }
        }
        if (in_array($newPos, $safePositions)) $score += 20;
    }

    return $score;
}

function calculateNewPos($playerColor, $currentPos, $diceValue, $turningPoints, $homeEntrance, $homePositions) {
    $isInHome = in_array($currentPos, $homeEntrance[$playerColor]);
    if ($isInHome) {
        $homeIdx = array_search($currentPos, $homeEntrance[$playerColor]);
        $stepsLeft = 5 - $homeIdx;
        if ($diceValue > $stepsLeft) return null;
        if ($diceValue === $stepsLeft) return $homePositions[$playerColor];
        return $homeEntrance[$playerColor][$homeIdx + $diceValue];
    }

    $turningPoint = $turningPoints[$playerColor];
    $distanceToTurn = ($turningPoint - $currentPos + 52) % 52;

    if ($distanceToTurn === 0) {
        if ($diceValue <= 5) return $homeEntrance[$playerColor][$diceValue - 1];
        return null;
    }

    if ($diceValue > $distanceToTurn && $distanceToTurn > 0 && $distanceToTurn < 7) {
        $overflow = $diceValue - $distanceToTurn;
        if ($overflow <= 5) return $homeEntrance[$playerColor][$overflow - 1];
        return null;
    }

    return ($currentPos + $diceValue) % 52;
}

function leaveGame($input, $userId, $token) {
    $matchId = $input['match_id'] ?? '';
    $match = getAndValidateMatch($matchId, $userId, $token);
    if (!$match) return;

    $players = json_decode($match['players'], true);
    $playerIdx = -1;
    foreach ($players as $idx => $p) {
        if ($p['id'] === $userId) { $playerIdx = $idx; break; }
    }

    if ($playerIdx === -1) {
        http_response_code(400);
        echo json_encode(['error' => 'not_in_match']);
        return;
    }

    // Replace player with bot
    $players[$playerIdx]['type'] = 'bot';
    $players[$playerIdx]['difficulty'] = 'easy';
    $players[$playerIdx]['connected'] = false;
    $players[$playerIdx]['name'] = 'بوت (غادر)';

    $update = ['players' => json_encode($players)];
    $patchRes = supabase_rest('PATCH', "ludo_matches?id=eq.{$matchId}", $update, $token);
    echo json_encode(['ok' => true]);
}

function sendChat($input, $userId, $userName, $token) {
    $matchId = $input['match_id'] ?? '';
    $text = trim($input['text'] ?? '');

    if (!$text || strlen($text) > 100) {
        http_response_code(400);
        echo json_encode(['error' => 'invalid_message']);
        return;
    }

    $match = getAndValidateMatch($matchId, $userId, $token);
    if (!$match) return;

    $chat = json_decode($match['chat'], true);
    $chat[] = [
        'sender_id' => $userId,
        'sender_name' => $userName,
        'text' => htmlspecialchars($text, ENT_QUOTES, 'UTF-8'),
        'at' => date('c')
    ];

    $update = ['chat' => json_encode($chat)];
    $patchRes = supabase_rest('PATCH', "ludo_matches?id=eq.{$matchId}", $update, $token);
    echo json_encode(['ok' => true]);
}

function matchmake($input, $userId, $userName, $token) {
    $subAction = $input['sub_action'] ?? 'join';

    if ($subAction === 'leave') {
        supabase_rest('DELETE', "ludo_queue?user_id=eq.{$userId}", [], $token);
        echo json_encode(['ok' => true, 'status' => 'left']);
        return;
    }

    // Check if already in queue
    $existing = supabase_rest('GET', "ludo_queue?user_id=eq.{$userId}&select=*", [], $token);
    if (!empty($existing['data'])) {
        // Poll for match
        $queueEntry = $existing['data'][0];
        if (!empty($queueEntry['match_id'])) {
            echo json_encode(['ok' => true, 'status' => 'matched', 'match_id' => $queueEntry['match_id']]);
            supabase_rest('DELETE', "ludo_queue?user_id=eq.{$userId}", [], $token);
            return;
        }

        // Try to find opponent
        $opponents = supabase_rest('GET', "ludo_queue?user_id=neq.{$userId}&match_id=is.null&select=*&limit=1", [], $token);
        if (!empty($opponents['data'])) {
            $opponent = $opponents['data'][0];
            // Create match
            $roomCode = generateRoomCode();
            $matchData = [
                'room_code' => $roomCode,
                'status' => 'in_progress',
                'player_count' => 2,
                'players' => json_encode([
                    ['id' => $userId, 'name' => $userName, 'color' => 'P1', 'type' => 'human', 'connected' => true],
                    ['id' => $opponent['user_id'], 'name' => $opponent['user_name'] ?? 'لاعب', 'color' => 'P2', 'type' => 'human', 'connected' => true]
                ]),
                'current_turn' => 0,
                'positions' => json_encode(['P1' => [500,501,502,503], 'P2' => [600,601,602,603]]),
                'moves' => json_encode([]),
                'winners' => json_encode([]),
                'game_state' => json_encode(['phase' => 'dice_not_rolled', 'started_at' => date('c')]),
                'chat' => json_encode([]),
                'host_id' => $userId
            ];

            $matchRes = supabase_rest('POST', 'ludo_matches', $matchData, $token);
            if (!empty($matchRes['data'])) {
                $newMatchId = $matchRes['data'][0]['id'];
                supabase_rest('PATCH', "ludo_queue?user_id=eq.{$opponent['user_id']}", ['match_id' => $newMatchId], $token);
                supabase_rest('DELETE', "ludo_queue?user_id=eq.{$userId}", [], $token);
                echo json_encode(['ok' => true, 'status' => 'matched', 'match_id' => $newMatchId]);
                return;
            }
        }

        echo json_encode(['ok' => true, 'status' => 'waiting']);
        return;
    }

    // Join queue
    $queueData = [
        'user_id' => $userId,
        'user_name' => $userName
    ];
    supabase_rest('POST', 'ludo_queue', $queueData, $token);
    echo json_encode(['ok' => true, 'status' => 'queued']);
}

function getAndValidateMatch($matchId, $userId, $token) {
    if (!$matchId) {
        http_response_code(400);
        echo json_encode(['error' => 'match_id_required']);
        return null;
    }

    $res = supabase_rest('GET', "ludo_matches?id=eq.{$matchId}&select=*", [], $token);
    if (empty($res['data'])) {
        http_response_code(404);
        echo json_encode(['error' => 'not_found']);
        return null;
    }

    $match = $res['data'][0];
    if ($match['status'] === 'completed' || $match['status'] === 'aborted') {
        http_response_code(400);
        echo json_encode(['error' => 'game_ended']);
        return null;
    }

    $players = json_decode($match['players'], true);
    $found = false;
    foreach ($players as $p) {
        if ($p['id'] === $userId) { $found = true; break; }
    }
    if (!$found) {
        http_response_code(403);
        echo json_encode(['error' => 'not_in_match']);
        return null;
    }

    return $match;
}
