<?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';
require_once __DIR__ . '/../includes/chess.php';
require_once __DIR__ . '/../includes/tournament-engine.php';

$method = $_SERVER['REQUEST_METHOD'];

if ($method === 'GET') {
    $action = $_GET['action'] ?? 'list';
    $db = supabaseService();

    if ($action === 'list') {
        // Start anything that is due. Doing this off ordinary traffic means a
        // tournament begins on time even if no external scheduler is running —
        // it is throttled, idempotent, and the same pattern the matchmaking
        // queue already uses for its stale sweep.
        tournamentStartDueTournaments($db);

        $tournaments = $db->get('el3ab_tournaments', [
            'select' => 'id,name,game_key,format,time_control,status,max_players,swiss_rounds,rounds_total,starts_at,prize_pool_coins,entry_fee_coins,updated_at',
            'status' => 'neq.cancelled',
            'order' => 'created_at.desc',
            'limit' => 50
        ]);

        if (!is_array($tournaments) || isset($tournaments['error'])) {
            jsonResponse(['tournaments' => []]);
        }

        $cutoff = date('c', strtotime('-3 days'));
        $tournaments = array_values(array_filter($tournaments, function ($t) use ($cutoff) {
            if ($t['status'] === 'completed') {
                $endDate = $t['updated_at'] ?? $t['starts_at'] ?? '';
                return $endDate > $cutoff;
            }
            return true;
        }));

        foreach ($tournaments as &$t) {
            $regs = $db->get('tournament_registrations', [
                'tournament_id' => 'eq.' . $t['id'],
                'select' => 'id',
                'status' => 'eq.registered'
            ]);
            $t['player_count'] = is_array($regs) && !isset($regs['error']) ? count($regs) : 0;
            unset($t['updated_at']);
        }

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

    if ($action === 'detail') {
        $id = $_GET['id'] ?? '';
        if (!$id) jsonError('id required');

        $tournament = $db->getOne('el3ab_tournaments', ['id' => 'eq.' . $id]);
        if (!$tournament || isset($tournament['error'])) jsonError('Not found', 404);

        jsonResponse($tournament);
    }

    if ($action === 'my-registrations') {
        $token = requireAuth();
        $userId = getUserId($token);
        $regs = $db->get('tournament_registrations', [
            'player_id' => 'eq.' . $userId,
            'status' => 'eq.registered',
            'select' => 'tournament_id'
        ]);
        jsonResponse(['registrations' => is_array($regs) && !isset($regs['error']) ? $regs : []]);
    }
}

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

    // Service role throughout: $userId comes from the verified token, so nothing
    // here is caller-supplied. Registration used to go through the user's own
    // JWT, where an RLS policy could drop the insert and still report success.
    $db = supabaseService();

    if ($action === 'register') {
        $tournamentId = $input['tournament_id'] ?? '';
        if (!$tournamentId) jsonError('tournament_id required');

        $t = tournamentLoad($db, $tournamentId);
        if (!$t) jsonError('Tournament not found', 404);

        if (!in_array($t['status'], [TOURNAMENT_STATUS_REGISTRATION, TOURNAMENT_STATUS_DRAFT], true)) {
            jsonError('Registration is closed for this tournament', 409);
        }
        if (!empty($t['registration_closes_at']) && strtotime($t['registration_closes_at']) < time()) {
            jsonError('Registration has closed', 409);
        }

        $existing = $db->get('tournament_registrations', [
            'tournament_id' => 'eq.' . $tournamentId,
            'player_id' => 'eq.' . $userId,
            'select' => 'id,status',
            'limit' => 1,
        ]);
        $existing = (is_array($existing) && !empty($existing) && !isset($existing['error'])) ? $existing[0] : null;

        if ($existing && ($existing['status'] ?? '') === 'registered') {
            jsonResponse(['success' => true, 'already_registered' => true]);
        }

        // Count against the cap only among players who are actually in.
        $regs = $db->get('tournament_registrations', [
            'tournament_id' => 'eq.' . $tournamentId,
            'status' => 'eq.registered',
            'select' => 'id',
        ]);
        $count = (is_array($regs) && !isset($regs['error'])) ? count($regs) : 0;
        if (!empty($t['max_players']) && $count >= (int)$t['max_players']) {
            jsonError('Tournament is full', 409);
        }

        if ($existing) {
            // Re-joining after withdrawing: revive the row rather than inserting
            // a second one, which the old code would have done.
            $res = $db->update('tournament_registrations', [
                'status' => 'registered',
                'withdrawn_at' => null,
            ], ['id' => 'eq.' . $existing['id']]);
        } else {
            $res = $db->insert('tournament_registrations', [
                'tournament_id' => $tournamentId,
                'player_id' => $userId,
                'status' => 'registered',
            ]);
        }
        if (isset($res['error'])) jsonError($res['error']);

        jsonResponse(['success' => true, 'player_count' => $count + 1]);
    }

    if ($action === 'cancel') {
        $tournamentId = $input['tournament_id'] ?? '';
        if (!$tournamentId) jsonError('tournament_id required');

        $t = tournamentLoad($db, $tournamentId);
        if (!$t) jsonError('Tournament not found', 404);

        // Once play has begun a player withdraws; the row is kept so their
        // completed games keep counting towards opponents' tiebreaks.
        $status = ($t['status'] === TOURNAMENT_STATUS_IN_PROGRESS) ? 'withdrawn' : 'cancelled';
        $db->update('tournament_registrations', [
            'status' => $status,
            'withdrawn_at' => gmdate('c'),
        ], [
            'tournament_id' => 'eq.' . $tournamentId,
            'player_id' => 'eq.' . $userId,
        ]);

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

    if ($action === 'check-start') {
        // Lets a client nudge a due tournament into starting without waiting for
        // the scheduler tick. Idempotent, and it only ever starts a tournament
        // whose own start time has already passed.
        $tournamentId = $input['tournament_id'] ?? '';
        if (!$tournamentId) jsonError('tournament_id required');

        $t = tournamentLoad($db, $tournamentId);
        if (!$t) jsonError('Tournament not found', 404);

        if ($t['status'] === TOURNAMENT_STATUS_IN_PROGRESS) {
            jsonResponse(['started' => true, 'current_round' => (int)$t['current_round']]);
        }
        if (empty($t['auto_start']) || empty($t['starts_at']) || strtotime($t['starts_at']) > time()) {
            jsonResponse(['started' => false, 'reason' => 'not_due']);
        }

        $res = tournamentStart($db, $tournamentId);
        jsonResponse(['started' => (bool)$res['ok'], 'reason' => $res['error']]);
    }
}

jsonError('Invalid request');
