<?php

/**
 * Tournament administration: create, open registration, start, force-advance,
 * and manual result entry.
 *
 * Before this existed there was no code path anywhere in the platform that could
 * start a tournament or generate a pairing, which is why `auto_start` was set on
 * live tournaments that then sat in `registration` forever.
 */

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';

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

switch ($action) {
    case 'create':        adminCreate($db, $userId, $input); break;
    case 'open':          adminSetStatus($db, $userId, $input, TOURNAMENT_STATUS_REGISTRATION); break;
    case 'cancel':        adminSetStatus($db, $userId, $input, TOURNAMENT_STATUS_CANCELLED); break;
    case 'start':         adminStart($db, $userId, $input); break;
    case 'advance':       adminAdvance($db, $userId, $input); break;
    case 'forfeit':       adminForfeit($db, $userId, $input); break;
    case 'add-player':    adminAddPlayer($db, $userId, $input); break;
    case 'remove-player': adminRemovePlayer($db, $userId, $input); break;
    default:              jsonError('Invalid action');
}

/**
 * Who may administer a tournament: its creator, or a platform admin.
 * Without this any authenticated player could start or cancel an event.
 */
function requireTournamentAdmin($db, string $userId, string $tournamentId): array {
    $t = tournamentLoad($db, $tournamentId);
    if (!$t) jsonError('Tournament not found', 404);
    if (($t['created_by'] ?? null) === $userId) return $t;
    if (isPlatformAdmin($db, $userId)) return $t;
    jsonError('You do not have permission to administer this tournament', 403);
}

function isPlatformAdmin($db, string $userId): bool {
    $rows = $db->get('admin_users', ['id' => 'eq.' . $userId, 'select' => 'id', 'limit' => 1]);
    if (is_array($rows) && !isset($rows['error']) && !empty($rows)) return true;
    // Fall back to a role flag on the profile, if the deployment uses one.
    $p = $db->get('profiles', ['id' => 'eq.' . $userId, 'select' => 'is_admin', 'limit' => 1]);
    return is_array($p) && !empty($p) && !isset($p['error']) && !empty($p[0]['is_admin']);
}

function adminCreate($db, string $userId, array $input): void {
    $name = trim((string)($input['name'] ?? ''));
    if ($name === '') jsonError('name is required');

    $format = $input['format'] ?? 'swiss';
    if (!in_array($format, ['swiss', 'round_robin', 'single_elimination', 'double_elimination', 'swiss_to_bracket', 'arena', 'team_battle'], true)) {
        jsonError('Invalid format');
    }

    $timeControl = chessNormaliseTimeControl($input['time_control'] ?? null);
    $rounds = isset($input['rounds']) ? max(1, min(15, (int)$input['rounds'])) : null;

    $row = [
        'name'          => $name,
        'name_ar'       => $input['name_ar'] ?? null,
        'description'   => $input['description'] ?? '',
        'game_key'      => $input['game_key'] ?? 'chess',
        'format'        => $format,
        'time_control'  => $timeControl,
        'swiss_rounds'  => $rounds,
        'rounds_total'  => $rounds,
        'min_players'   => max(2, (int)($input['min_players'] ?? 4)),
        'max_players'   => max(2, (int)($input['max_players'] ?? 64)),
        // starts_at is NOT NULL in production. Defaulting it to now keeps the
        // create call usable without one, and auto_start then has a time to act on.
        'starts_at'     => $input['starts_at'] ?: gmdate('c'),
        'status'        => TOURNAMENT_STATUS_REGISTRATION,
        'current_round' => 0,
        'auto_start'    => (bool)($input['auto_start'] ?? true),
        'is_rated'      => (bool)($input['is_rated'] ?? true),
        'created_by'    => $userId,
        'tiebreak_rules'=> ['buchholz_cut_1', 'buchholz', 'sonneborn_berger'],
    ];

    $created = $db->insert('el3ab_tournaments', $row);
    if (isset($created['error'])) jsonError('Could not create tournament: ' . $created['error']);

    jsonResponse(['tournament' => $created[0] ?? $created]);
}

function adminSetStatus($db, string $userId, array $input, string $status): void {
    $id = $input['tournament_id'] ?? '';
    if (!$id) jsonError('tournament_id is required');
    requireTournamentAdmin($db, $userId, $id);

    $updated = $db->update('el3ab_tournaments', ['status' => $status, 'updated_at' => gmdate('c')], ['id' => 'eq.' . $id]);
    if (isset($updated['error'])) jsonError($updated['error']);
    jsonResponse(['ok' => true, 'status' => $status]);
}

function adminStart($db, string $userId, array $input): void {
    $id = $input['tournament_id'] ?? '';
    if (!$id) jsonError('tournament_id is required');
    requireTournamentAdmin($db, $userId, $id);

    $res = tournamentStart($db, $id);
    if (!$res['ok']) jsonError($res['error'] ?? 'Could not start tournament', 409);

    jsonResponse([
        'ok' => true,
        'round' => $res['round'] ? [
            'id' => $res['round']['id'],
            'round_number' => (int)$res['round']['round_number'],
            'pairings' => $res['round']['pairings'],
        ] : null,
    ]);
}

function adminAdvance($db, string $userId, array $input): void {
    $id = $input['tournament_id'] ?? '';
    if (!$id) jsonError('tournament_id is required');
    requireTournamentAdmin($db, $userId, $id);

    jsonResponse(tournamentMaybeAdvance($db, $id));
}

function adminForfeit($db, string $userId, array $input): void {
    $id = $input['tournament_id'] ?? '';
    $pairingId = $input['pairing_id'] ?? '';
    $absent = $input['absent_player_id'] ?? '';
    if (!$id || !$pairingId || !$absent) jsonError('tournament_id, pairing_id and absent_player_id are required');

    $t = requireTournamentAdmin($db, $userId, $id);
    $round = (int)($input['round'] ?? $t['current_round'] ?? 0);
    if ($round < 1) jsonError('Tournament has no active round');

    $ok = tournamentForfeitPairing($db, $id, $round, $pairingId, $absent);
    if (!$ok) jsonError('Pairing not found, or it already has a result', 409);
    jsonResponse(['ok' => true]);
}

function adminAddPlayer($db, string $userId, array $input): void {
    $id = $input['tournament_id'] ?? '';
    $playerId = $input['player_id'] ?? '';
    if (!$id || !$playerId) jsonError('tournament_id and player_id are required');
    $t = requireTournamentAdmin($db, $userId, $id);
    if ($t['status'] === TOURNAMENT_STATUS_IN_PROGRESS) {
        jsonError('Cannot add players once the tournament has started', 409);
    }

    $existing = $db->get('tournament_registrations', [
        'tournament_id' => 'eq.' . $id, 'player_id' => 'eq.' . $playerId, 'select' => 'id', 'limit' => 1,
    ]);
    if (is_array($existing) && !empty($existing) && !isset($existing['error'])) {
        $db->update('tournament_registrations', ['status' => 'registered'], ['id' => 'eq.' . $existing[0]['id']]);
        jsonResponse(['ok' => true, 'already_registered' => true]);
    }

    $ins = $db->insert('tournament_registrations', [
        'tournament_id' => $id, 'player_id' => $playerId, 'status' => 'registered',
        'is_bot' => (bool)($input['is_bot'] ?? false),
    ]);
    if (isset($ins['error'])) jsonError($ins['error']);
    jsonResponse(['ok' => true]);
}

function adminRemovePlayer($db, string $userId, array $input): void {
    $id = $input['tournament_id'] ?? '';
    $playerId = $input['player_id'] ?? '';
    if (!$id || !$playerId) jsonError('tournament_id and player_id are required');
    $t = requireTournamentAdmin($db, $userId, $id);

    // Mid-event a player is withdrawn, never deleted, so their played games keep
    // counting towards their opponents' tiebreaks.
    $status = ($t['status'] === TOURNAMENT_STATUS_IN_PROGRESS) ? 'withdrawn' : 'cancelled';
    $db->update('tournament_registrations', [
        'status' => $status, 'withdrawn_at' => gmdate('c'),
    ], ['tournament_id' => 'eq.' . $id, 'player_id' => 'eq.' . $playerId]);

    jsonResponse(['ok' => true, 'status' => $status]);
}
