<?php

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, 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);
$method = $_SERVER['REQUEST_METHOD'];
$sdb = supabaseService();

if ($method === 'GET') {
    // Get all achievements with player progress
    $achievements = $sdb->get('achievements', ['select' => 'id,name,name_ar,description,description_ar,category,tier,condition,xp_reward,coins_reward,icon_url,is_hidden', 'order' => 'tier.asc,category.asc']);
    if (!is_array($achievements) || isset($achievements['error'])) {
        jsonResponse(['achievements' => [], 'stats' => ['total' => 0, 'completed' => 0]]);
    }

    $playerAch = $sdb->get('player_achievements', ['player_id' => 'eq.' . $userId, 'select' => 'achievement_id,progress,completed,completed_at']);
    $playerMap = [];
    if (is_array($playerAch) && !isset($playerAch['error'])) {
        foreach ($playerAch as $pa) {
            $playerMap[$pa['achievement_id']] = $pa;
        }
    }

    $result = [];
    $totalCompleted = 0;
    foreach ($achievements as $a) {
        $condition = $a['condition'];
        if (is_string($condition)) $condition = json_decode($condition, true);

        $pa = $playerMap[$a['id']] ?? null;
        $progress = $pa['progress'] ?? 0;
        $completed = $pa['completed'] ?? false;
        $target = $condition['count'] ?? 1;

        if ($a['is_hidden'] && !$completed) {
            // Hidden achievements show only if completed
            continue;
        }

        if ($completed) $totalCompleted++;

        $result[] = [
            'id' => $a['id'],
            'name' => $a['name_ar'] ?? $a['name'],
            'name_en' => $a['name'],
            'description' => $a['description_ar'] ?? $a['description'],
            'category' => $a['category'],
            'tier' => $a['tier'],
            'icon_url' => $a['icon_url'] ?? '',
            'xp_reward' => $a['xp_reward'],
            'coins_reward' => $a['coins_reward'],
            'condition_type' => $condition['type'] ?? '',
            'target' => $target,
            'progress' => min($progress, $target),
            'completed' => $completed,
            'completed_at' => $pa['completed_at'] ?? null
        ];
    }

    jsonResponse([
        'achievements' => $result,
        'stats' => ['total' => count($result), 'completed' => $totalCompleted]
    ]);
}

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

    if ($action === 'check') {
        // Recalculate all achievement progress for this player
        $profile = getPlayerProfile($sdb, $userId);
        if (!$profile) jsonError('Profile not found');

        $achievements = $sdb->get('achievements', ['select' => 'id,condition,coins_reward,xp_reward']);
        if (!is_array($achievements) || isset($achievements['error'])) {
            jsonResponse(['checked' => 0, 'newly_completed' => []]);
        }

        // Gather player stats
        $stats = gatherPlayerStats($sdb, $userId, $profile);
        $newlyCompleted = [];

        foreach ($achievements as $a) {
            $condition = $a['condition'];
            if (is_string($condition)) $condition = json_decode($condition, true);
            if (!$condition) continue;

            $type = $condition['type'] ?? '';
            $target = $condition['count'] ?? 1;
            $currentValue = $stats[$type] ?? 0;

            // Get or create player_achievement row
            $existing = $sdb->get('player_achievements', [
                'player_id' => 'eq.' . $userId,
                'achievement_id' => 'eq.' . $a['id'],
                'limit' => 1
            ]);

            $alreadyCompleted = false;
            if (is_array($existing) && !isset($existing['error']) && !empty($existing)) {
                $alreadyCompleted = $existing[0]['completed'] ?? false;
                if ($alreadyCompleted) continue;

                // Update progress
                $updateData = ['progress' => min($currentValue, $target)];
                if ($currentValue >= $target) {
                    $updateData['completed'] = true;
                    $updateData['completed_at'] = gmdate('c');
                    $newlyCompleted[] = $a['id'];
                    grantAchievementReward($sdb, $userId, $a);
                }
                $sdb->update('player_achievements', $updateData, [
                    'player_id' => 'eq.' . $userId,
                    'achievement_id' => 'eq.' . $a['id']
                ]);
            } else {
                // Create new row
                $insertData = [
                    'player_id' => $userId,
                    'achievement_id' => $a['id'],
                    'progress' => min($currentValue, $target),
                    'completed' => $currentValue >= $target
                ];
                if ($currentValue >= $target) {
                    $insertData['completed_at'] = gmdate('c');
                    $newlyCompleted[] = $a['id'];
                    grantAchievementReward($sdb, $userId, $a);
                }
                $sdb->insert('player_achievements', $insertData);
            }
        }

        jsonResponse(['checked' => count($achievements), 'newly_completed' => $newlyCompleted]);
    }

    if ($action === 'claim') {
        $achievementId = $input['achievement_id'] ?? '';
        if (!$achievementId) jsonError('achievement_id required');

        // Check if completed but reward not granted
        $pa = $sdb->get('player_achievements', [
            'player_id' => 'eq.' . $userId,
            'achievement_id' => 'eq.' . $achievementId,
            'completed' => 'eq.true',
            'limit' => 1
        ]);
        if (!is_array($pa) || isset($pa['error']) || empty($pa)) {
            jsonError('Achievement not completed');
        }

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

    jsonError('Invalid action');
}

jsonError('Method not allowed', 405);

function getPlayerProfile($sdb, string $userId): ?array {
    $profiles = $sdb->get('profiles', ['id' => 'eq.' . $userId, 'select' => '*', 'limit' => 1]);
    if (is_array($profiles) && !empty($profiles) && !isset($profiles['error'])) return $profiles[0];
    return null;
}

function gatherPlayerStats($sdb, string $userId, array $profile): array {
    // Count friends
    $friends = $sdb->get('friendships', [
        'or' => '(user_id.eq.' . $userId . ',friend_id.eq.' . $userId . ')',
        'status' => 'eq.accepted',
        'select' => 'id',
        'limit' => 1000
    ]);
    $friendCount = (is_array($friends) && !isset($friends['error'])) ? count($friends) : 0;

    // Count cosmetics owned
    $cosmetics = $sdb->get('player_cosmetics', [
        'player_id' => 'eq.' . $userId,
        'select' => 'id',
        'limit' => 1000
    ]);
    $cosmeticCount = (is_array($cosmetics) && !isset($cosmetics['error'])) ? count($cosmetics) : 0;

    // Count tournament participations
    $tournaments = $sdb->get('tournament_registrations', [
        'player_id' => 'eq.' . $userId,
        'select' => 'id',
        'limit' => 1000
    ]);
    $tournamentCount = (is_array($tournaments) && !isset($tournaments['error'])) ? count($tournaments) : 0;

    // Get best rating
    $bestRating = max(
        $profile['elo_rapid'] ?? 1200,
        $profile['elo_blitz'] ?? 1200,
        $profile['elo_bullet'] ?? 1200,
        $profile['elo_classical'] ?? 1200
    );

    return [
        'wins' => $profile['total_wins'] ?? 0,
        'games_played' => $profile['games_played'] ?? 0,
        'win_streak' => $profile['win_streak'] ?? 0,
        'level' => $profile['level'] ?? 1,
        'daily_streak' => $profile['daily_streak'] ?? 0,
        'friends' => $friendCount,
        'cosmetics_owned' => $cosmeticCount,
        'tournaments_played' => $tournamentCount,
        'tournaments_won' => 0,
        'elo' => $bestRating,
        'ludo_wins' => 0,
        'beat_all_bots' => 0,
    ];
}

function grantAchievementReward($sdb, string $userId, array $achievement): void {
    $coins = intval($achievement['coins_reward'] ?? 0);
    $xp = intval($achievement['xp_reward'] ?? 0);

    if ($coins <= 0 && $xp <= 0) return;

    $updates = [];
    if ($coins > 0) $updates['coins'] = $coins;
    if ($xp > 0) $updates['xp'] = $xp;

    // Use RPC for atomic coin award if available
    if ($coins > 0) {
        $sdb->rpc('award_coins', ['p_player_id' => $userId, 'p_amount' => $coins, 'p_reason' => 'Achievement: ' . $achievement['id']]);
    }

    if ($xp > 0) {
        // Atomic XP increment
        $profiles = $sdb->get('profiles', ['id' => 'eq.' . $userId, 'select' => 'xp,level', 'limit' => 1]);
        if (is_array($profiles) && !empty($profiles)) {
            $currentXp = ($profiles[0]['xp'] ?? 0) + $xp;
            $newLevel = floor($currentXp / 500) + 1;
            $sdb->update('profiles', ['xp' => $currentXp, 'level' => $newLevel], ['id' => 'eq.' . $userId]);
        }
    }

    $sdb->insert('economy_transactions', [
        'player_id' => $userId,
        'type' => 'achievement_reward',
        'currency' => 'coins',
        'amount' => $coins,
        'balance_after' => 0,
        'reason' => 'Achievement: ' . $achievement['id']
    ]);
}
