<?php

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');

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__ . '/../config/constants.php';

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

$db = supabaseService();

switch ($action) {
    case 'create-or-join':
        handleCreateOrJoin($db, $userId, $input);
        break;
    case 'report-result':
        handleReportResult($db, $userId, $input);
        break;
    case 'my-pending':
        handleMyPending($db, $userId);
        break;
    default:
        jsonError('Invalid action');
}

function handleCreateOrJoin($db, string $userId, array $input): void {
    $tournamentId = $input['tournament_id'] ?? '';
    $roundId = $input['round_id'] ?? '';
    $pairingIndex = intval($input['pairing_index'] ?? -1);

    if (!$tournamentId || !$roundId || $pairingIndex < 0) {
        jsonError('tournament_id, round_id, and pairing_index are required');
    }

    // Fetch the round and its pairings
    $rounds = $db->get('el3ab_tournament_rounds', [
        'id' => 'eq.' . $roundId,
        'tournament_id' => 'eq.' . $tournamentId,
        'select' => 'id,round_number,pairings,status',
        'limit' => 1
    ]);

    $round = is_array($rounds) && !empty($rounds) && !isset($rounds['error']) ? $rounds[0] : null;
    if (!$round) jsonError('Round not found', 404);
    if ($round['status'] !== 'in_progress') jsonError('Round is not in progress');

    $rawPairings = $round['pairings'] ?? '[]';
    $pairings = is_array($rawPairings) ? $rawPairings : json_decode($rawPairings, true);
    if (!isset($pairings[$pairingIndex])) jsonError('Pairing not found');

    $pairing = $pairings[$pairingIndex];
    $playerA = $pairing['player_a'] ?? $pairing['white_id'] ?? null;
    $playerB = $pairing['player_b'] ?? $pairing['black_id'] ?? null;

    if ($userId !== $playerA && $userId !== $playerB) {
        jsonError('You are not part of this pairing');
    }

    // BYE check
    if (!$playerA || !$playerB || $playerA === 'BYE' || $playerB === 'BYE') {
        jsonResponse(['bye' => true, 'message' => 'BYE round — auto win']);
    }

    $roundNumber = $round['round_number'] ?? 1;

    // Check if match already exists for this pairing
    $existing = $db->get('matches', [
        'tournament_id' => 'eq.' . $tournamentId,
        'tournament_round' => 'eq.' . $roundNumber,
        'select' => 'id,white_player_id,black_player_id,status,time_control',
        'or' => "(and(white_player_id.eq.{$playerA},black_player_id.eq.{$playerB}),and(white_player_id.eq.{$playerB},black_player_id.eq.{$playerA}))",
        'limit' => 1
    ]);

    if (is_array($existing) && !empty($existing) && !isset($existing['error'])) {
        $match = $existing[0];
        $color = ($match['white_player_id'] === $userId) ? 'w' : 'b';
        $opponentId = ($match['white_player_id'] === $userId) ? $match['black_player_id'] : $match['white_player_id'];
        jsonResponse([
            'match_id' => $match['id'],
            'color' => $color,
            'opponent_id' => $opponentId,
            'time_control' => $match['time_control'],
            'status' => $match['status'],
            'already_exists' => true
        ]);
    }

    // Determine colors from pairing data
    $whiteId = $playerA;
    $blackId = $playerB;

    // Get tournament time control
    $tournaments = $db->get('el3ab_tournaments', [
        'id' => 'eq.' . $tournamentId,
        'select' => 'time_control,game_key',
        'limit' => 1
    ]);
    $tournament = is_array($tournaments) && !empty($tournaments) ? $tournaments[0] : null;
    $timeControl = $tournament['time_control'] ?? 'rapid_10_0';
    $gameKey = $tournament['game_key'] ?? 'chess';

    // Parse time control for initial_time_ms and increment
    $tcParts = explode('_', $timeControl);
    $minutes = intval($tcParts[1] ?? 10);
    $increment = intval($tcParts[2] ?? 0);
    $initialTimeMs = $minutes * 60 * 1000;
    $incrementMs = $increment * 1000;

    // Create the match
    $matchData = [
        'game_key' => $gameKey,
        'match_type' => 'tournament',
        'white_player_id' => $whiteId,
        'black_player_id' => $blackId,
        'status' => 'in_progress',
        'time_control' => $timeControl,
        'initial_time_ms' => $initialTimeMs,
        'increment_ms' => $incrementMs,
        'white_time_remaining_ms' => $initialTimeMs,
        'black_time_remaining_ms' => $initialTimeMs,
        'tournament_id' => $tournamentId,
        'tournament_round' => $roundNumber,
        'starting_fen' => 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
        'current_fen' => 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',
        'moves' => '[]',
        'started_at' => date('c'),
        'metadata' => json_encode([
            'mode' => 'tournament',
            'round_id' => $roundId,
            'pairing_index' => $pairingIndex
        ])
    ];

    $result = $db->insert('matches', $matchData);
    if (isset($result['error'])) jsonError('Failed to create match: ' . ($result['error'] ?? ''));

    $match = is_array($result) && !empty($result) ? (isset($result[0]) ? $result[0] : $result) : null;
    $matchId = $match['id'] ?? null;

    if (!$matchId) jsonError('Match creation failed');

    $color = ($whiteId === $userId) ? 'w' : 'b';
    $opponentId = ($whiteId === $userId) ? $blackId : $whiteId;

    jsonResponse([
        'match_id' => $matchId,
        'color' => $color,
        'opponent_id' => $opponentId,
        'time_control' => $timeControl,
        'status' => 'in_progress',
        'already_exists' => false
    ]);
}

function handleReportResult($db, string $userId, array $input): void {
    $matchId = $input['match_id'] ?? '';
    $tournamentId = $input['tournament_id'] ?? '';
    $result = $input['result'] ?? '';

    if (!$matchId || !$tournamentId || !$result) {
        jsonError('match_id, tournament_id, and result are required');
    }

    // Get match to verify and extract tournament info
    $matches = $db->get('matches', ['id' => 'eq.' . $matchId, 'select' => '*', 'limit' => 1]);
    $match = is_array($matches) && !empty($matches) && !isset($matches['error']) ? $matches[0] : null;
    if (!$match) jsonError('Match not found', 404);

    if ($match['tournament_id'] !== $tournamentId) jsonError('Match does not belong to this tournament');

    // Check if already reported (idempotent)
    $rawMeta = $match['metadata'] ?? '{}';
    $metadata = is_array($rawMeta) ? $rawMeta : json_decode($rawMeta, true);
    if (!empty($metadata['tournament_reported'])) {
        jsonResponse(['ok' => true, 'already_reported' => true]);
    }

    // Map result to Swiss format
    $swissResult = mapToSwissResult($result, $match['white_player_id'], $match['black_player_id'], $userId);

    // Get tournament to check format and swiss_api_tournament_id
    $tournaments = $db->get('el3ab_tournaments', [
        'id' => 'eq.' . $tournamentId,
        'select' => 'swiss_api_tournament_id,format',
        'limit' => 1
    ]);
    $tournament = is_array($tournaments) && !empty($tournaments) ? $tournaments[0] : null;

    // Report to Swiss API if linked
    if ($tournament && !empty($tournament['swiss_api_tournament_id'])) {
        $roundNumber = $match['tournament_round'] ?? 1;
        $roundId = $metadata['round_id'] ?? null;
        $pairingIndex = $metadata['pairing_index'] ?? null;

        if ($roundId && $pairingIndex !== null) {
            reportToSwissApi($tournament['swiss_api_tournament_id'], $roundId, $pairingIndex, $swissResult);
        }
    }

    // Update el3ab_tournament_rounds results JSONB
    $roundNumber = $match['tournament_round'] ?? 1;
    $roundsData = $db->get('el3ab_tournament_rounds', [
        'tournament_id' => 'eq.' . $tournamentId,
        'round_number' => 'eq.' . $roundNumber,
        'select' => 'id,results',
        'limit' => 1
    ]);

    if (is_array($roundsData) && !empty($roundsData) && !isset($roundsData['error'])) {
        $roundRow = $roundsData[0];
        $rawResults = $roundRow['results'] ?? '[]';
        $results = is_array($rawResults) ? $rawResults : json_decode($rawResults, true);
        $results[] = [
            'match_id' => $matchId,
            'result' => $swissResult,
            'white_player_id' => $match['white_player_id'],
            'black_player_id' => $match['black_player_id'],
            'reported_at' => date('c')
        ];
        $db->update('el3ab_tournament_rounds', ['results' => json_encode($results)], ['id' => 'eq.' . $roundRow['id']]);
    }

    // Mark match metadata as reported
    $metadata['tournament_reported'] = true;
    $metadata['reported_at'] = date('c');
    $db->update('matches', ['metadata' => json_encode($metadata)], ['id' => 'eq.' . $matchId]);

    // Handle bracket tournaments
    if ($tournament && ($tournament['format'] === 'single_elimination' || $tournament['format'] === 'double_elimination')) {
        $winnerId = determineWinner($result, $match);
        if ($winnerId) {
            $bracketMatches = $db->get('bracket_matches', [
                'tournament_id' => 'eq.' . $tournamentId,
                'match_id' => 'eq.' . $matchId,
                'limit' => 1
            ]);
            if (is_array($bracketMatches) && !empty($bracketMatches) && !isset($bracketMatches['error'])) {
                $db->update('bracket_matches', [
                    'result' => $swissResult,
                    'winner_id' => $winnerId,
                    'status' => 'completed'
                ], ['id' => 'eq.' . $bracketMatches[0]['id']]);
            }
        }
    }

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

function handleMyPending($db, string $userId): void {
    // Get all tournaments the player is registered for that are in_progress
    $regs = $db->get('tournament_registrations', [
        'player_id' => 'eq.' . $userId,
        'status' => 'eq.registered',
        'select' => 'tournament_id'
    ]);

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

    $pending = [];

    foreach ($regs as $reg) {
        $tid = $reg['tournament_id'];

        // Get tournament info
        $tournaments = $db->get('el3ab_tournaments', [
            'id' => 'eq.' . $tid,
            'status' => 'eq.in_progress',
            'select' => 'id,name,time_control,game_key',
            'limit' => 1
        ]);
        if (!is_array($tournaments) || empty($tournaments) || isset($tournaments['error'])) continue;
        $tournament = $tournaments[0];

        // Get in_progress rounds
        $rounds = $db->get('el3ab_tournament_rounds', [
            'tournament_id' => 'eq.' . $tid,
            'status' => 'eq.in_progress',
            'select' => 'id,round_number,pairings',
            'order' => 'round_number.desc',
            'limit' => 1
        ]);
        if (!is_array($rounds) || empty($rounds) || isset($rounds['error'])) continue;

        $round = $rounds[0];
        $rawPairings = $round['pairings'] ?? '[]';
        $pairings = is_array($rawPairings) ? $rawPairings : json_decode($rawPairings, true);

        foreach ($pairings as $idx => $pairing) {
            $playerA = $pairing['player_a'] ?? $pairing['white_id'] ?? null;
            $playerB = $pairing['player_b'] ?? $pairing['black_id'] ?? null;

            if ($userId !== $playerA && $userId !== $playerB) continue;

            // Check if already has a match for this round
            $existingMatch = $db->get('matches', [
                'tournament_id' => 'eq.' . $tid,
                'tournament_round' => 'eq.' . $round['round_number'],
                'status' => 'eq.completed',
                'or' => "(white_player_id.eq.{$userId},black_player_id.eq.{$userId})",
                'select' => 'id',
                'limit' => 1
            ]);

            if (is_array($existingMatch) && !empty($existingMatch) && !isset($existingMatch['error'])) continue;

            $opponentId = ($userId === $playerA) ? $playerB : $playerA;

            // BYE check
            if (!$opponentId || $opponentId === 'BYE') {
                $pending[] = [
                    'tournament_id' => $tid,
                    'tournament_name' => $tournament['name'],
                    'round_id' => $round['id'],
                    'round_number' => $round['round_number'],
                    'pairing_index' => $idx,
                    'opponent_id' => null,
                    'is_bye' => true,
                    'time_control' => $tournament['time_control'],
                    'game_key' => $tournament['game_key']
                ];
                continue;
            }

            // Get opponent name
            $opponents = $db->get('profiles', ['id' => 'eq.' . $opponentId, 'select' => 'display_name,avatar_url', 'limit' => 1]);
            $opponent = is_array($opponents) && !empty($opponents) ? $opponents[0] : null;

            $pending[] = [
                'tournament_id' => $tid,
                'tournament_name' => $tournament['name'],
                'round_id' => $round['id'],
                'round_number' => $round['round_number'],
                'pairing_index' => $idx,
                'opponent_id' => $opponentId,
                'opponent_name' => $opponent['display_name'] ?? 'Unknown',
                'opponent_avatar' => $opponent['avatar_url'] ?? null,
                'is_bye' => false,
                'time_control' => $tournament['time_control'],
                'game_key' => $tournament['game_key']
            ];
        }
    }

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

function mapToSwissResult(string $result, string $whiteId, string $blackId, string $reporterId): string {
    switch ($result) {
        case 'white_wins':
        case 'win':
            return '1-0';
        case 'black_wins':
        case 'loss':
            return '0-1';
        case 'draw':
            return '1/2-1/2';
        default:
            return $result;
    }
}

function determineWinner(string $result, array $match): ?string {
    switch ($result) {
        case 'white_wins':
            return $match['white_player_id'];
        case 'black_wins':
            return $match['black_player_id'];
        default:
            return null;
    }
}

function reportToSwissApi(string $swissId, string $roundId, int $pairingIndex, string $result): void {
    $url = SWISS_API . '/tournaments/' . $swissId . '/rounds/' . $roundId . '/results';
    $body = json_encode(['pairing_index' => $pairingIndex, 'result' => $result]);

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_exec($ch);
    curl_close($ch);
}
