<?php

header('Content-Type: application/json');
require_once __DIR__ . '/../includes/cors.php';

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit; }

require_once __DIR__ . '/../includes/supabase.php';
require_once __DIR__ . '/../includes/auth.php';

$token = requireAuth();
$userId = getUserId($token);
$input = getInput();
$action = $input['action'] ?? '';

switch ($action) {
    case 'queue': handleQueue($userId, $input); break;
    case 'dequeue': handleBgDequeue($userId); break;
    case 'status': handleStatus($userId); break;
    case 'move': handleMove($userId, $input); break;
    case 'get': handleGet($userId, $input); break;
    case 'complete': handleComplete($userId, $input); break;
    case 'heartbeat': handleBgHeartbeat($userId, $input); break;
    case 'leave': handleBgLeave($userId, $input); break;
    case 'emote': handleEmote($userId, $input); break;
    default: jsonError('Invalid action');
}

function handleBgDequeue(string $userId): void {
    $sdb = supabaseService();
    $sdb->delete('backgammon_queue', ['user_id' => 'eq.' . $userId]);
    jsonResponse(['success' => true]);
}

function handleQueue(string $userId, array $input): void {
    $sdb = supabaseService();
    $variant = $input['variant'] ?? 'sheshbesh';
    $matchLength = intval($input['match_length'] ?? 3);

    // STEP 1: Remove ALL existing entries for this player (prevents ghost/self-match)
    $sdb->delete('backgammon_queue', ['user_id' => 'eq.' . $userId]);

    // STEP 2: Clean stale entries from other players (older than 90 seconds)
    $staleTime = gmdate('c', time() - 90);
    $sdb->delete('backgammon_queue', [
        'match_id' => 'is.null',
        'created_at' => 'lt.' . $staleTime
    ]);

    // STEP 3: Search for available opponent
    $searchUrl = SUPABASE_REST . '/backgammon_queue'
        . '?user_id=neq.' . $userId
        . '&match_id=is.null'
        . '&variant=eq.' . $variant
        . '&select=id,user_id'
        . '&order=created_at.asc'
        . '&limit=1';

    $ch = curl_init($searchUrl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'apikey: ' . SUPABASE_SERVICE_KEY,
        'Authorization: Bearer ' . SUPABASE_SERVICE_KEY,
        'Content-Type: application/json',
        'Prefer: return=representation'
    ]);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    $result = curl_exec($ch);
    $opponents = json_decode($result, true);

    if (!empty($opponents) && isset($opponents[0])) {
        $opponent = $opponents[0];

        // STEP 4: Atomically claim opponent — set match_id to a placeholder to prevent races
        $claimResult = $sdb->update('backgammon_queue', [
            'match_id' => '00000000-0000-0000-0000-000000000000'
        ], [
            'id' => 'eq.' . $opponent['id'],
            'match_id' => 'is.null'
        ]);

        if (empty($claimResult) || isset($claimResult['error'])) {
            // Opponent was grabbed by someone else — add self to queue
            $sdb->insert('backgammon_queue', [
                'user_id' => $userId,
                'variant' => $variant,
                'match_length' => $matchLength
            ]);
            jsonResponse(['queued' => true]);
            return;
        }

        // STEP 5: Create match
        $players = [$opponent['user_id'], $userId];
        $whiteIdx = rand(0, 1);
        $colors = [$whiteIdx === 0 ? 'white' : 'black', $whiteIdx === 1 ? 'white' : 'black'];

        $matchData = [
            'status' => 'in_progress',
            'players' => $players,
            'colors' => $colors,
            'variant' => $variant,
            'match_length' => $matchLength,
            'scores' => [0, 0],
            'current_turn' => $whiteIdx,
            'game_state' => [
                'variant' => $variant,
                'match_length' => $matchLength,
                'game_number' => 1,
                'cube_value' => 1,
                'cube_owner' => null,
                'crawford' => false
            ],
            'host_id' => $opponent['user_id'],
            'created_by' => $userId
        ];

        $match = $sdb->insert('backgammon_matches', $matchData);
        $matchId = $match[0]['id'] ?? $match['id'] ?? null;

        if ($matchId) {
            $sdb->update('backgammon_queue', ['match_id' => $matchId], ['id' => 'eq.' . $opponent['id']]);

            jsonResponse([
                'match_id' => $matchId,
                'player_index' => 1,
                'players' => $players,
                'color' => $colors[1]
            ]);
            return;
        }
    }

    // No opponent found — queue up
    $sdb->insert('backgammon_queue', [
        'user_id' => $userId,
        'variant' => $variant,
        'match_length' => $matchLength
    ]);
    jsonResponse(['queued' => true]);
}

function handleStatus(string $userId): void {
    $sdb = supabaseService();

    $entry = $sdb->get('backgammon_queue', [
        'user_id' => 'eq.' . $userId,
        'select' => 'id,match_id',
        'limit' => 1
    ]);

    if (!empty($entry) && !isset($entry['error']) && !empty($entry[0]['match_id'])) {
        $matchId = $entry[0]['match_id'];
        $sdb->delete('backgammon_queue', ['user_id' => 'eq.' . $userId]);

        $matches = $sdb->get('backgammon_matches', ['id' => 'eq.' . $matchId, 'select' => 'players,colors', 'limit' => 1]);
        $players = [];
        $colors = [];
        if (!empty($matches) && !isset($matches['error'])) {
            $players = json_decode($matches[0]['players'] ?? '[]', true);
            $colors = json_decode($matches[0]['colors'] ?? '[]', true);
        }
        $playerIndex = array_search($userId, $players);

        jsonResponse([
            'match_id' => $matchId,
            'player_index' => $playerIndex !== false ? $playerIndex : 0,
            'players' => $players,
            'color' => $colors[$playerIndex] ?? 'white'
        ]);
        return;
    }

    jsonResponse(['waiting' => true]);
}

function handleMove(string $userId, array $input): void {
    $matchId = $input['match_id'] ?? '';
    if (!$matchId) jsonError('match_id required');

    $sdb = supabaseService();
    $update = [];

    if (isset($input['game_state'])) {
        $gs = is_string($input['game_state']) ? $input['game_state'] : json_encode($input['game_state']);
        $update['game_state'] = $gs;
    }
    if (isset($input['match_state'])) {
        $ms = is_string($input['match_state']) ? json_decode($input['match_state'], true) : $input['match_state'];
        if (isset($ms['scores'])) $update['scores'] = json_encode($ms['scores']);
        if (isset($ms['gameNumber'])) $update['game_number'] = $ms['gameNumber'];
    }
    if (isset($input['cube'])) {
        $update['cube_state'] = is_string($input['cube']) ? $input['cube'] : json_encode($input['cube']);
    }
    if (isset($input['current_turn'])) {
        $update['current_turn'] = intval($input['current_turn']);
    }

    $update['last_activity'] = date('c');
    $update['updated_at'] = date('c');

    if (!empty($update)) {
        $sdb->update('backgammon_matches', $update, ['id' => 'eq.' . $matchId]);
    }
    jsonResponse(['success' => true]);
}

function handleGet(string $userId, array $input): void {
    $matchId = $input['match_id'] ?? ($_GET['match_id'] ?? '');
    if (!$matchId) jsonError('match_id required');

    $sdb = supabaseService();
    $matches = $sdb->get('backgammon_matches', ['id' => 'eq.' . $matchId, 'select' => '*', 'limit' => 1]);

    if (empty($matches) || isset($matches['error'])) jsonError('Not found', 404);
    $match = $matches[0];

    // Server-side turn timeout (30s)
    if ($match['status'] === 'in_progress') {
        $timeout = supabaseRpc('enforce_turn_timeout', [
            'p_game_key' => 'backgammon',
            'p_match_id' => $matchId,
            'p_timeout_seconds' => 30
        ]);
        if (!empty($timeout['timeout'])) {
            $match['_turn_timed_out'] = true;
            $match['_timeout_player'] = $timeout['player_index'] ?? null;
        }
    }

    jsonResponse($match);
}

function handleComplete(string $userId, array $input): void {
    $matchId = $input['match_id'] ?? '';
    if (!$matchId) jsonError('match_id required');
    $winner = $input['winner'] ?? null;
    $reason = $input['reason'] ?? 'normal';

    $sdb = supabaseService();

    $sdb->update('backgammon_matches', [
        'status' => 'completed',
        'completed_at' => date('c'),
        'winner_id' => $winner,
        'result' => $reason,
        'updated_at' => date('c')
    ], ['id' => 'eq.' . $matchId]);

    $result = supabaseRpc('complete_match', [
        'p_game_key' => 'backgammon',
        'p_match_id' => $matchId,
        'p_winners' => json_encode([$winner]),
        'p_reason' => $reason
    ]);

    jsonResponse($result ?: ['success' => true]);
}

function handleBgHeartbeat(string $userId, array $input): void {
    $matchId = $input['match_id'] ?? '';
    if (!$matchId) jsonError('match_id required');

    $result = supabaseRpc('match_heartbeat', [
        'p_game_key' => 'backgammon',
        'p_match_id' => $matchId,
        'p_player_id' => $userId
    ]);

    jsonResponse($result ?: ['status' => 'ok']);
}

function handleBgLeave(string $userId, array $input): void {
    $matchId = $input['match_id'] ?? '';
    if (!$matchId) jsonError('match_id required');

    $sdb = supabaseService();
    $matches = $sdb->get('backgammon_matches', ['id' => 'eq.' . $matchId, 'select' => 'players,game_state', 'limit' => 1]);
    if (empty($matches) || isset($matches['error'])) jsonError('Not found');

    $gameState = json_decode($matches[0]['game_state'] ?? '{}', true);
    $gameState['left_by'] = $userId;
    $gameState['left_at'] = date('c');

    $sdb->update('backgammon_matches', [
        'game_state' => json_encode($gameState),
        'status' => 'abandoned',
        'updated_at' => date('c')
    ], ['id' => 'eq.' . $matchId]);

    jsonResponse(['success' => true]);
}

function handleEmote(string $userId, array $input): void {
    $matchId = $input['match_id'] ?? '';
    if (!$matchId) jsonError('match_id required');

    $sdb = supabaseService();
    $sdb->update('backgammon_matches', [
        'last_emote' => json_encode([
            'user_id' => $userId,
            'emote' => $input['emote'] ?? '',
            'at' => date('c')
        ]),
        'updated_at' => date('c')
    ], ['id' => 'eq.' . $matchId]);

    jsonResponse(['success' => true]);
}
