<?php

namespace App\ViewModels;

use App\Models\Event;
use App\Models\Game;
use App\Models\PlayerProfile;
use App\Queries\EventQuery;
use App\Queries\GameCatalogQuery;
use App\Services\MockDataService;

class DashboardPresenter
{
    public function __construct(
        private GameCatalogQuery $gameCatalog,
        private EventQuery $eventQuery,
        private EventPresenter $eventPresenter,
    ) {}

    public function present(bool $useMock = false): array
    {
        $games = $this->presentGames($useMock);
        $events = $this->presentEvents($useMock);
        $stats = $this->presentStats($useMock);
        $featured = $this->presentFeaturedTournament($useMock);

        return [
            'stats' => $stats,
            'games' => $games,
            'events' => $events,
            'liveMatches' => $this->presentLiveMatches(),
            'topPlayers' => $this->presentTopPlayers(),
            'featuredTournament' => $featured,
            'community' => config('navigation.community'),
            'isPreviewData' => $useMock,
        ];
    }

    private function presentStats(bool $useMock): array
    {
        if ($useMock) {
            $mock = MockDataService::platformStats();

            return [
                ['key' => 'players', 'label' => 'Players', 'value' => $mock['players'], 'icon' => 'players'],
                ['key' => 'teams', 'label' => 'Teams', 'value' => $mock['teams'], 'icon' => 'teams'],
                ['key' => 'scrims', 'label' => 'Scrims Today', 'value' => $mock['matches_today'], 'icon' => 'scrims'],
                ['key' => 'events', 'label' => 'Live Events', 'value' => $mock['tournaments'], 'icon' => 'events'],
            ];
        }

        $players = PlayerProfile::query()->count();
        $events = Event::query()->whereIn('status', ['published', 'registration_open', 'in_progress'])->count();
        $mock = MockDataService::platformStats();

        return [
            ['key' => 'players', 'label' => 'Players', 'value' => max($players, 0), 'icon' => 'players'],
            ['key' => 'teams', 'label' => 'Teams', 'value' => $mock['teams'], 'icon' => 'teams'],
            ['key' => 'scrims', 'label' => 'Scrims Today', 'value' => $mock['matches_today'], 'icon' => 'scrims'],
            ['key' => 'events', 'label' => 'Live Events', 'value' => max($events, 0), 'icon' => 'events'],
        ];
    }

    private function presentGames(bool $useMock): array
    {
        if ($useMock) {
            return collect(MockDataService::games())->take(6)->map(fn (array $game) => [
                'name' => $game['name'] ?? 'Game',
                'slug' => $game['id'] ?? $game['slug'] ?? '',
                'cover' => $game['cover'] ?? null,
                'players_count' => $game['players_count'] ?? 0,
                'url' => url('preview/games/'.($game['id'] ?? '')),
                'is_mock' => true,
            ])->all();
        }

        return $this->gameCatalog->allActive()->take(6)->map(function (Game $game) {
            return [
                'name' => method_exists($game, 'translationName') ? ($game->translationName() ?? $game->name) : $game->name,
                'slug' => $game->slug,
                'cover' => $game->cover_path,
                'players_count' => (int) ($game->player_game_profiles_count ?? 0),
                'url' => route('games.show', ['game' => $game->slug]),
                'is_mock' => false,
            ];
        })->all();
    }

    private function presentEvents(bool $useMock): array
    {
        if ($useMock) {
            return collect(MockDataService::tournaments())->take(4)->values()->map(function (array $t, int $i) {
                return [
                    'name' => $t['name'] ?? 'Event',
                    'slug' => $t['slug'] ?? '',
                    'game_name' => $t['game_name'] ?? '',
                    'start_date' => $t['start_date'] ?? null,
                    'prize_pool' => $t['prize_pool'] ?? 0,
                    'participants' => ($t['registered_teams'] ?? 0).'/'.($t['max_teams'] ?? 0),
                    'status' => $t['status'] ?? 'upcoming',
                    'url' => url('preview/tournaments/'.($t['slug'] ?? '')),
                    'accent' => ['gold', 'blue', 'green', 'violet'][$i % 4],
                    'cover' => $t['cover'] ?? null,
                ];
            })->all();
        }

        $events = $this->eventQuery->upcomingForDashboard(4);

        return collect($events)->values()->map(function (array $t, int $i) {
            return [
                'name' => $t['name'] ?? 'Event',
                'slug' => $t['slug'] ?? '',
                'game_name' => $t['game_name'] ?? '',
                'start_date' => $t['start_date'] ?? null,
                'prize_pool' => $t['prize_pool'] ?? 0,
                'participants' => ($t['registered_teams'] ?? 0).'/'.($t['max_teams'] ?? 0),
                'status' => $t['status'] ?? 'upcoming',
                'url' => route('events.show', ['event' => $t['slug']]),
                'accent' => ['gold', 'blue', 'green', 'violet'][$i % 4],
                'cover' => $t['cover'] ?? null,
            ];
        })->all();
    }

    private function presentLiveMatches(): array
    {
        $scrims = array_slice(MockDataService::scrims(), 0, 3);

        return collect($scrims)->map(function (array $scrim, int $i) {
            $opponents = [
                ['Alpha Squad', 'Omega Force'],
                ['Team Nexus', 'Iron Legion'],
                ['Sandstorm', 'Nova Rising'],
            ][$i] ?? ['Team A', 'Team B'];

            return [
                'game' => $scrim['game_name'] ?? 'Esports',
                'stage' => $scrim['format'] ?? 'BO3',
                'team_a' => $opponents[0],
                'team_b' => $opponents[1],
                'score_a' => [13, 8, 11][$i] ?? 0,
                'score_b' => [11, 13, 9][$i] ?? 0,
                'is_live' => true,
            ];
        })->all();
    }

    private function presentTopPlayers(): array
    {
        return collect(MockDataService::rankings())->take(5)->values()->map(function (array $player, int $i) {
            $primaryGame = $player['games'][0] ?? [];

            return [
                'position' => $i + 1,
                'username' => $player['username'] ?? 'Player',
                'avatar' => $player['avatar'] ?? asset('assets/images/generated/players/player-1.webp'),
                'rank' => $primaryGame['rank'] ?? 'Unranked',
                'points' => $player['stats']['points'] ?? 0,
                'online' => (bool) ($player['online'] ?? false),
            ];
        })->all();
    }

    private function presentFeaturedTournament(bool $useMock): ?array
    {
        if ($useMock) {
            $t = collect(MockDataService::tournaments())->firstWhere('status', 'registration_open')
                ?? MockDataService::tournaments()[0] ?? null;

            if (! $t) {
                return null;
            }

            return [
                'game_name' => $t['game_name'] ?? 'Esports',
                'name' => $t['name'] ?? 'Tournament',
                'starts_at' => $t['start_date'] ?? now()->addDays(7)->toDateString(),
                'url' => url('preview/tournaments/'.($t['slug'] ?? '')),
            ];
        }

        $featured = $this->eventQuery->featured(1)->first();

        if (! $featured) {
            return null;
        }

        $mapped = $this->eventPresenter->toTournamentArray($featured);

        return [
            'game_name' => $mapped['game_name'],
            'name' => $mapped['name'],
            'starts_at' => $mapped['starts_at']?->toIso8601String() ?? $mapped['start_date'],
            'url' => route('events.show', ['event' => $mapped['slug']]),
        ];
    }
}
