<?php

/**
 * Tournament read API (standings, rounds, pairings, arena).
 *
 * This used to proxy every request to an external Swiss service. That service
 * requires an Authorization header and this file never sent one, so every call
 * returned 401 and each getter quietly fell through to an empty array — which
 * is why standings, pairings, rounds and brackets have always rendered blank.
 *
 * It now reads EL3AB's own tournament tables through includes/tournament-engine.php.
 * The external service is still consulted, but only as an optional extra when a
 * tournament is explicitly linked to one AND a key is configured.
 */

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/auth.php';
require_once __DIR__ . '/../includes/supabase.php';
require_once __DIR__ . '/../includes/chess.php';
require_once __DIR__ . '/../includes/tournament-engine.php';
require_once __DIR__ . '/../config/constants.php';

$action = $_GET['action'] ?? (getInput()['action'] ?? '');

switch ($action) {
    case 'tournament':      getTournament(); break;
    case 'standings':       getStandings(); break;
    case 'rounds':          getRounds(); break;
    case 'pairings':        getPairings(); break;
    case 'my-games':        getMyGames(); break;
    case 'bracket':         getBracket(); break;
    case 'arena-join':      arenaJoin(); break;
    case 'arena-status':    arenaStatus(); break;
    case 'arena-standings': arenaStandings(); break;
    default:                jsonError('Invalid action');
}

/**
 * Optional call out to the external Swiss service.
 *
 * Returns an error array unless SWISS_API_KEY is configured — the point being
 * that a missing key is now an explicit, visible condition rather than a silent
 * 401 that every caller mistook for "no data".
 */
function swissApi(string $method, string $path, ?array $body = null): array {
    $key = defined('SWISS_API_KEY') ? SWISS_API_KEY : '';
    if ($key === '') {
        return ['error' => 'swiss_api_not_configured', 'code' => 0];
    }

    $ch = curl_init(SWISS_API . $path);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 8);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'Authorization: Bearer ' . $key,
    ]);
    if ($method === 'POST') {
        curl_setopt($ch, CURLOPT_POST, true);
        if ($body) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    }
    $response = curl_exec($ch);
    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    $data = json_decode($response, true);
    if ($code >= 400 || $data === null) {
        return ['error' => $data['message'] ?? 'Swiss API error', 'code' => $code];
    }
    return $data;
}

function requireTournament($db, string $id): array {
    $t = tournamentLoad($db, $id);
    if (!$t) jsonError('Tournament not found', 404);
    return $t;
}

function getTournament(): void {
    $id = $_GET['id'] ?? '';
    if (!$id) jsonError('id required');

    $db = supabaseService();
    $t = requireTournament($db, $id);

    $players = tournamentPlayers($db, $id, $t['time_control'] ?? 'rapid_10_0');
    $t['player_count'] = count($players);
    $t['rounds_total'] = (int)($t['swiss_rounds'] ?? $t['rounds_total'] ?? 0);

    $rounds = tournamentRounds($db, $id);
    $t['rounds'] = array_map(fn($r) => [
        'id' => $r['id'],
        'round_number' => (int)$r['round_number'],
        'status' => $r['status'],
        'games' => count($r['pairings']),
        'completed' => count(array_filter($r['pairings'], fn($p) => ($p['result'] ?? null) !== null)),
    ], $rounds);

    jsonResponse($t);
}

function getStandings(): void {
    $tournamentId = $_GET['tournament_id'] ?? '';
    if (!$tournamentId) jsonError('tournament_id required');

    $db = supabaseService();
    $t = requireTournament($db, $tournamentId);

    jsonResponse(['standings' => tournamentStandings($db, $t)]);
}

function getRounds(): void {
    $tournamentId = $_GET['tournament_id'] ?? '';
    if (!$tournamentId) jsonError('tournament_id required');

    $db = supabaseService();
    requireTournament($db, $tournamentId);

    $rounds = tournamentRounds($db, $tournamentId);
    jsonResponse(['rounds' => array_map(fn($r) => [
        'id' => $r['id'],
        'round_number' => (int)$r['round_number'],
        'status' => $r['status'],
        'started_at' => $r['started_at'],
        'completed_at' => $r['completed_at'],
        'games' => count($r['pairings']),
        'completed' => count(array_filter($r['pairings'], fn($p) => ($p['result'] ?? null) !== null)),
    ], $rounds)]);
}

function getPairings(): void {
    $tournamentId = $_GET['tournament_id'] ?? '';
    if (!$tournamentId) jsonError('tournament_id required');
    $roundNumber = isset($_GET['round']) ? (int)$_GET['round'] : null;

    $db = supabaseService();
    $t = requireTournament($db, $tournamentId);

    if ($roundNumber === null) $roundNumber = max(1, (int)($t['current_round'] ?? 1));
    $round = tournamentRound($db, $tournamentId, $roundNumber);
    if (!$round) jsonResponse(['pairings' => [], 'round_number' => $roundNumber]);

    jsonResponse([
        'round_id' => $round['id'],
        'round_number' => (int)$round['round_number'],
        'status' => $round['status'],
        'pairings' => decoratePairings($db, $round['pairings']),
    ]);
}

/** Attach display names so the UI does not have to resolve every uuid itself. */
function decoratePairings($db, array $pairings): array {
    $ids = [];
    foreach ($pairings as $p) {
        foreach (['white_id', 'black_id'] as $k) {
            if (!empty($p[$k])) $ids[$p[$k]] = true;
        }
    }
    $names = [];
    if ($ids) {
        $profiles = $db->get('profiles', [
            'id' => 'in.(' . implode(',', array_keys($ids)) . ')',
            'select' => 'id,display_name,username,avatar_url',
        ]);
        if (is_array($profiles) && !isset($profiles['error'])) {
            foreach ($profiles as $pr) $names[$pr['id']] = $pr;
        }
    }

    return array_map(function ($p) use ($names) {
        $w = $names[$p['white_id'] ?? ''] ?? null;
        $b = $names[$p['black_id'] ?? ''] ?? null;
        return array_merge($p, [
            'white_name'   => $w['display_name'] ?? $w['username'] ?? null,
            'white_avatar' => $w['avatar_url'] ?? null,
            'black_name'   => $b['display_name'] ?? $b['username'] ?? null,
            'black_avatar' => $b['avatar_url'] ?? null,
        ]);
    }, $pairings);
}

function getMyGames(): void {
    $token = requireAuth();
    $userId = getUserId($token);
    $tournamentId = $_GET['tournament_id'] ?? '';
    if (!$tournamentId) jsonError('tournament_id required');

    $db = supabaseService();
    requireTournament($db, $tournamentId);

    $games = [];
    foreach (tournamentRounds($db, $tournamentId) as $round) {
        foreach ($round['pairings'] as $p) {
            $isMine = ($p['white_id'] ?? null) === $userId || ($p['black_id'] ?? null) === $userId;
            if (!$isMine) continue;
            $games[] = [
                'round_number' => (int)$round['round_number'],
                'board'        => $p['board'] ?? null,
                'is_bye'       => !empty($p['is_bye']),
                'color'        => (($p['white_id'] ?? null) === $userId) ? 'w' : 'b',
                'opponent_id'  => (($p['white_id'] ?? null) === $userId) ? ($p['black_id'] ?? null) : ($p['white_id'] ?? null),
                'result'       => $p['result'] ?? null,
                'match_id'     => $p['match_id'] ?? null,
                'pairing_id'   => $p['pairing_id'] ?? null,
            ];
        }
    }

    jsonResponse(['games' => $games]);
}

function getBracket(): void {
    $tournamentId = $_GET['tournament_id'] ?? '';
    if (!$tournamentId) jsonError('tournament_id required');

    $db = supabaseService();
    $t = requireTournament($db, $tournamentId);

    // Knockout brackets are not implemented natively yet. Say so plainly rather
    // than returning an empty array that the UI renders as "no games".
    if (!in_array($t['format'] ?? '', ['single_elimination', 'double_elimination', 'swiss_to_bracket'], true)) {
        jsonResponse(['bracket' => [], 'format' => $t['format'] ?? null, 'supported' => false]);
    }

    $rows = $db->get('bracket_matches', ['tournament_id' => 'eq.' . $tournamentId, 'select' => '*', 'order' => 'round.asc']);
    jsonResponse([
        'bracket' => (is_array($rows) && !isset($rows['error'])) ? $rows : [],
        'format' => $t['format'],
        'supported' => true,
    ]);
}

// ---------------------------------------------------------------------------
// Arena — continuous pairing rather than fixed rounds
// ---------------------------------------------------------------------------

function arenaJoin(): void {
    $token = requireAuth();
    $userId = getUserId($token);
    $input = getInput();
    $tournamentId = $input['tournament_id'] ?? ($_GET['tournament_id'] ?? '');
    if (!$tournamentId) jsonError('tournament_id required');

    $db = supabaseService();
    $t = requireTournament($db, $tournamentId);

    // Arena is round-based under the hood: a player asks for their current game.
    $pending = tournamentPendingPairingFor($db, $t, $userId);
    if (!$pending) {
        jsonResponse(['status' => 'waiting']);
    }
    if (!empty($pending['pairing']['is_bye'])) {
        jsonResponse(['status' => 'bye', 'round_number' => (int)$pending['round']['round_number']]);
    }

    $p = $pending['pairing'];
    $isWhite = ($p['white_id'] === $userId);
    jsonResponse([
        'status'       => 'paired',
        'color'        => $isWhite ? 'w' : 'b',
        'opponent_id'  => $isWhite ? $p['black_id'] : $p['white_id'],
        'time_control' => chessNormaliseTimeControl($t['time_control'] ?? null),
        'round_number' => (int)$pending['round']['round_number'],
        'board'        => $p['board'] ?? null,
        // The client calls tournament-match.php create-or-join to open the game,
        // so the match id is minted in exactly one place.
        'needs_match'  => true,
    ]);
}

function arenaStatus(): void {
    $token = requireAuth();
    $userId = getUserId($token);
    $tournamentId = $_GET['tournament_id'] ?? '';
    if (!$tournamentId) jsonError('tournament_id required');

    $db = supabaseService();
    $t = requireTournament($db, $tournamentId);

    if ($t['status'] !== TOURNAMENT_STATUS_IN_PROGRESS) {
        jsonResponse(['status' => $t['status']]);
    }

    $pending = tournamentPendingPairingFor($db, $t, $userId);
    if (!$pending) jsonResponse(['status' => 'waiting']);
    if (!empty($pending['pairing']['is_bye'])) {
        jsonResponse(['status' => 'bye', 'round_number' => (int)$pending['round']['round_number']]);
    }

    $p = $pending['pairing'];
    $isWhite = ($p['white_id'] === $userId);
    $matchId = tournamentMatchIdFor($tournamentId, (int)$pending['round']['round_number'], (int)($p['board'] ?? 1));
    $rows = $db->get('matches', ['id' => 'eq.' . $matchId, 'select' => 'id,status', 'limit' => 1]);
    $exists = is_array($rows) && !empty($rows) && !isset($rows['error']);

    jsonResponse([
        'status'       => $exists ? 'in_game' : 'paired',
        'match_id'     => $exists ? $matchId : null,
        'color'        => $isWhite ? 'w' : 'b',
        'opponent_id'  => $isWhite ? $p['black_id'] : $p['white_id'],
        'time_control' => chessNormaliseTimeControl($t['time_control'] ?? null),
        'round_number' => (int)$pending['round']['round_number'],
    ]);
}

function arenaStandings(): void {
    $tournamentId = $_GET['tournament_id'] ?? '';
    if (!$tournamentId) jsonError('tournament_id required');

    $db = supabaseService();
    $t = requireTournament($db, $tournamentId);
    jsonResponse(['standings' => tournamentStandings($db, $t)]);
}
