<?php

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

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 'start': handleStart($userId, $input); break;
    case 'queue': handleQueue($userId, $input); break;
    case 'status': handleStatus($userId); break;
    case 'move': handleMove($userId, $input); break;
    case 'get': handleGet($userId, $input); break;
    case 'resign': handleResign($userId, $input); break;
    case 'complete': handleComplete($userId, $input); break;
    default: jsonError('Invalid action');
}

function handleStart(string $userId, array $input): void {
    $sdb = supabaseService();
    $mode = $input['mode'] ?? 'bot';
    $botLevel = $input['bot_level'] ?? 'intermediate';

    $players = [$userId, 'bot_' . $botLevel];

    $matchData = [
        'status' => 'in_progress',
        'players' => json_encode($players),
        'current_turn' => 0,
        'board' => '[]',
        'hands' => '{}',
        'boneyard' => '[]',
        'moves' => '[]',
        'scores' => json_encode(['0' => 0, '1' => 0]),
        'game_state' => json_encode(['move_count' => 0, 'round' => 1, 'mode' => $mode, 'bot_level' => $botLevel]),
        'host_id' => $userId,
        'created_by' => $userId
    ];

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

    if ($id) {
        jsonResponse(['id' => $id, 'status' => 'in_progress']);
    } else {
        jsonError('Failed to create match');
    }
}

function handleQueue(string $userId, array $input): void {
    $sdb = supabaseService();

    $sdb->delete('domino_queue', ['user_id' => 'eq.' . $userId]);

    $searchUrl = SUPABASE_REST . '/domino_queue'
        . '?user_id=neq.' . $userId
        . '&match_id=is.null'
        . '&select=id,user_id'
        . '&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'
    ]);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    $result = curl_exec($ch);
    curl_close($ch);
    $opponents = json_decode($result, true);

    if (!empty($opponents) && isset($opponents[0])) {
        $opponent = $opponents[0];
        $players = [$opponent['user_id'], $userId];

        $matchData = [
            'status' => 'in_progress',
            'players' => json_encode($players),
            'current_turn' => 0,
            'board' => '[]',
            'hands' => '{}',
            'boneyard' => '[]',
            'moves' => '[]',
            'scores' => json_encode(['0' => 0, '1' => 0]),
            'game_state' => json_encode(['move_count' => 0, 'round' => 1, 'mode' => 'live']),
            'host_id' => $opponent['user_id']
        ];

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

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

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

    $sdb->insert('domino_queue', ['user_id' => $userId]);
    jsonResponse(['queued' => true]);
}

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

    $entry = $sdb->get('domino_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('domino_queue', ['user_id' => 'eq.' . $userId]);

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

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

    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['board'])) {
        $board = $input['board'];
        $update['board'] = is_string($board) ? $board : json_encode($board);
    }
    if (isset($input['hands'])) {
        $newHands = is_string($input['hands']) ? json_decode($input['hands'], true) : $input['hands'];
        // Merge with existing hands to preserve other player's data
        $existingMatch = $sdb->get('domino_matches', ['id' => 'eq.' . $matchId, 'select' => 'hands', 'limit' => 1]);
        $existingHands = [];
        if (!empty($existingMatch) && !isset($existingMatch['error']) && !empty($existingMatch[0]['hands'])) {
            $existingHands = is_string($existingMatch[0]['hands']) ? json_decode($existingMatch[0]['hands'], true) : $existingMatch[0]['hands'];
        }
        $mergedHands = array_merge($existingHands ?: [], $newHands ?: []);
        $update['hands'] = json_encode($mergedHands);
    }
    if (isset($input['boneyard'])) {
        $boneyard = $input['boneyard'];
        $update['boneyard'] = is_string($boneyard) ? $boneyard : json_encode($boneyard);
    }
    if (isset($input['current_turn'])) {
        $update['current_turn'] = intval($input['current_turn']);
    }
    if (isset($input['scores'])) {
        $update['scores'] = is_string($input['scores']) ? $input['scores'] : json_encode($input['scores']);
    }
    if (isset($input['game_state'])) {
        $existing = $sdb->get('domino_matches', ['id' => 'eq.' . $matchId, 'select' => 'game_state', 'limit' => 1]);
        $existingGs = [];
        if (!empty($existing) && !isset($existing['error']) && !empty($existing[0]['game_state'])) {
            $existingGs = json_decode($existing[0]['game_state'], true) ?: [];
        }
        $newGs = is_string($input['game_state']) ? json_decode($input['game_state'], true) : $input['game_state'];
        $merged = array_merge($existingGs, $newGs ?: []);
        $update['game_state'] = json_encode($merged);
    }
    if (isset($input['status'])) {
        $update['status'] = $input['status'];
    }
    if (isset($input['winner_id'])) {
        $update['winner_id'] = $input['winner_id'];
    }
    if (isset($input['result'])) {
        $update['result'] = $input['result'];
    }

    if (!empty($update)) {
        $update['updated_at'] = date('c');
        $sdb->update('domino_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('domino_matches', ['id' => 'eq.' . $matchId, 'select' => '*', 'limit' => 1]);

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

    $match = $matches[0];

    $players = json_decode($match['players'] ?? '[]', true);
    $playerIndex = array_search($userId, $players);
    $hands = json_decode($match['hands'] ?? '{}', true);

    $response = $match;
    $response['my_hand'] = $hands[strval($playerIndex)] ?? [];
    $response['opponent_count'] = 0;
    foreach ($hands as $idx => $h) {
        if (intval($idx) !== $playerIndex) {
            $response['opponent_count'] = count($h);
        }
    }
    unset($response['hands']);

    jsonResponse($response);
}

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

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

    if (empty($matches) || isset($matches['error'])) jsonError('Match not found', 404);
    $match = $matches[0];
    if ($match['status'] === 'completed') jsonError('Match already ended');

    $players = json_decode($match['players'] ?? '[]', true);
    $playerIndex = array_search($userId, $players);
    $winnerIndex = $playerIndex === 0 ? 1 : 0;
    $winnerId = $players[$winnerIndex] ?? null;

    $sdb->update('domino_matches', [
        'status' => 'completed',
        'result' => 'player' . ($winnerIndex + 1) . '_wins',
        'winner_id' => $winnerId,
        'game_state' => json_encode(['resigned_by' => $userId, 'move_count' => 999]),
        'updated_at' => date('c')
    ], ['id' => 'eq.' . $matchId]);

    jsonResponse(['result' => 'resigned']);
}

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

    $sdb = supabaseService();
    $playerResult = $input['result'] ?? '';
    $winnerId = $input['winner_id'] ?? null;
    $scores = $input['scores'] ?? null;
    $opponentRating = intval($input['opponent_rating'] ?? 1200);

    $update = [
        'status' => 'completed',
        'result' => $playerResult,
        'updated_at' => date('c')
    ];
    if ($winnerId) $update['winner_id'] = $winnerId;
    if ($scores) $update['scores'] = is_string($scores) ? $scores : json_encode($scores);

    $sdb->update('domino_matches', $update, ['id' => 'eq.' . $matchId]);

    $outcome = 'loss';
    if ($winnerId === $userId) $outcome = 'win';
    elseif ($playerResult === 'draw') $outcome = 'draw';
    elseif (strpos($playerResult, 'player') !== false) {
        $match = $sdb->get('domino_matches', ['id' => 'eq.' . $matchId, 'select' => 'players', 'limit' => 1]);
        if (!empty($match) && !isset($match['error'])) {
            $players = json_decode($match[0]['players'] ?? '[]', true);
            $playerIdx = array_search($userId, $players);
            $winnerIdx = intval(str_replace(['player', '_wins'], '', $playerResult)) - 1;
            if ($playerIdx === $winnerIdx) $outcome = 'win';
        }
    }

    $profiles = $sdb->get('profiles', ['id' => 'eq.' . $userId, 'select' => 'elo_domino,games_played,total_wins,total_draws,total_losses,win_streak,coins,xp,level', 'limit' => 1]);
    $profile = is_array($profiles) && !empty($profiles) && !isset($profiles['error']) ? $profiles[0] : null;

    $ratingChange = 0;
    $coins = 10;
    $xp = 15;
    $newRating = 1200;

    if ($profile) {
        $playerRating = $profile['elo_domino'] ?? 1200;
        $score = ($outcome === 'win') ? 1.0 : (($outcome === 'draw') ? 0.5 : 0.0);
        $newRating = calculateElo($playerRating, $opponentRating, $score);
        $ratingChange = $newRating - $playerRating;

        $updates = ['elo_domino' => $newRating, 'games_played' => ($profile['games_played'] ?? 0) + 1];
        if ($outcome === 'win') {
            $updates['total_wins'] = ($profile['total_wins'] ?? 0) + 1;
            $updates['win_streak'] = ($profile['win_streak'] ?? 0) + 1;
        } elseif ($outcome === 'draw') {
            $updates['total_draws'] = ($profile['total_draws'] ?? 0) + 1;
            $updates['win_streak'] = 0;
        } else {
            $updates['total_losses'] = ($profile['total_losses'] ?? 0) + 1;
            $updates['win_streak'] = 0;
        }

        $sdb->update('profiles', $updates, ['id' => 'eq.' . $userId]);

        $sdb->insert('rating_history', [
            'player_id' => $userId,
            'game_key' => 'domino',
            'time_control_type' => 'standard',
            'rating_before' => $playerRating,
            'rating_after' => $newRating,
            'rating_change' => $ratingChange,
            'match_id' => $matchId,
            'result' => $outcome
        ]);

        $rewardConfig = $sdb->get('reward_config', ['select' => 'key,value']);
        $rewards = [];
        if (is_array($rewardConfig) && !isset($rewardConfig['error'])) {
            foreach ($rewardConfig as $r) $rewards[$r['key']] = intval($r['value']);
        }
        $coins = ($outcome === 'win') ? ($rewards['domino_win_coins'] ?? 50) : (($outcome === 'draw') ? ($rewards['domino_draw_coins'] ?? 20) : ($rewards['domino_loss_coins'] ?? 10));
        $xp = ($outcome === 'win') ? ($rewards['domino_win_xp'] ?? 30) : (($outcome === 'draw') ? ($rewards['domino_draw_xp'] ?? 15) : ($rewards['domino_loss_xp'] ?? 10));

        $sdb->rpc('award_coins', ['p_player_id' => $userId, 'p_amount' => $coins, 'p_reason' => 'Domino ' . $outcome]);

        $currentCoins = ($profile['coins'] ?? 0) + $coins;
        $sdb->insert('economy_transactions', [
            'player_id' => $userId,
            'type' => 'game_reward',
            'currency' => 'coins',
            'amount' => $coins,
            'balance_after' => $currentCoins,
            'reason' => 'Domino ' . $outcome
        ]);
    }

    jsonResponse([
        'success' => true,
        'result' => $outcome,
        'rating_before' => $profile ? ($profile['elo_domino'] ?? 1200) : 1200,
        'rating_after' => $newRating,
        'rating_change' => $ratingChange,
        'coins_earned' => $coins,
        'xp_earned' => $xp
    ]);
}

function calculateElo(int $playerRating, int $opponentRating, float $score): int {
    $k = 32;
    if ($playerRating > 2400) $k = 16;
    elseif ($playerRating > 2000) $k = 24;

    $expected = 1.0 / (1.0 + pow(10, ($opponentRating - $playerRating) / 400.0));
    $newRating = round($playerRating + $k * ($score - $expected));
    return max(100, $newRating);
}
