<?php

namespace App\Http\Controllers\Highscore;

use App\Http\Controllers\Controller;
use App\Models\Enums\EmpireEnum;
use App\Models\Game\Highscore\GuildHighscoreCache;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;

class GuildHighscoreController extends Controller
{
    private const RESULTS_PER_PAGE = 10;
    private const CACHE_LIFETIME_MINUTES = 60; // Refresh every hour

    /**
     * Check if cache needs refresh and refresh if needed
     */
    private function refreshCacheIfNeeded(): void
    {
        $lastEntry = GuildHighscoreCache::first();

        if (!$lastEntry || !$lastEntry->date || $lastEntry->date->diffInMinutes(now()) >= self::CACHE_LIFETIME_MINUTES) {
            $this->refreshGuildCache();
        }
    }

    /**
     * Refresh the guild highscore cache directly (instead of using artisan)
     */
    private function refreshGuildCache(): void
    {
        try {
            // Get guilds ordered by ladder_point
            // Join with player table to get master name
            // Join with player_index to get empire (empire is stored per account, not per player)
            $guilds = DB::connection('player')
                ->table('guild')
                ->leftJoin('player', 'guild.master', '=', 'player.id')
                ->leftJoin('player_index', 'player.account_id', '=', 'player_index.id')
                ->select([
                    'guild.name',
                    'player.name as master',
                    'player_index.empire',
                    'guild.level',
                    'guild.ladder_point'
                ])
                ->orderByDesc('guild.ladder_point')
                ->limit(5000)
                ->get();

            if ($guilds->isEmpty()) {
                return;
            }

            // Clear existing cache
            DB::connection('website')->table('guild_highscore_cache')->truncate();

            // Insert new data with rank
            $rank = 0;
            $chunks = $guilds->chunk(500);

            foreach ($chunks as $chunk) {
                $insertData = [];
                foreach ($chunk as $guild) {
                    $rank++;
                    $insertData[] = [
                        'id' => $rank,
                        'name' => $guild->name,
                        'master' => $guild->master ?? 'Unknown',
                        'empire' => $guild->empire,
                        'level' => $guild->level,
                        'ladder_point' => $guild->ladder_point ?? 0,
                        'date' => now(),
                    ];
                }
                DB::connection('website')->table('guild_highscore_cache')->insert($insertData);
            }

            Log::info("Guild highscore cache refreshed with {$rank} guilds.");
        } catch (\Exception $e) {
            Log::error('Guild highscore cache refresh failed: ' . $e->getMessage());
        }
    }

    public function show(Request $request, ?int $empireChoice = null, ?int $page = null): View
    {
        $this->refreshCacheIfNeeded();

        $query = GuildHighscoreCache::query()->orderBy('id');

        // If "empireChoice" is a valid empire, add it to the query; otherwise set empireChoice to -1
        if (in_array($empireChoice, array_column(EmpireEnum::cases(), 'value'), true))
            $query->where('empire', $empireChoice);
        else
            $empireChoice = -1;

        // Check whether "guildChoice" or "guildLeaderChoice" were requested
        $validated = $request->validate([
            'guild-choice' => 'nullable',
            'guild-leader-choice' => 'nullable',
        ]);
        $guildChoice = $validated['guild-choice'] ?? null;
        $guildLeaderChoice = $validated['guild-leader-choice'] ?? null;

        // If "guild-choice" was specified, find the guild with that name
        if (!empty($guildChoice))
            $query->where('name', 'LIKE', '%' . $guildChoice . '%');

        // If "guild-leader-choice" was specified, find the guild master with that name
        if (!empty($guildLeaderChoice))
            $query->where('master', 'LIKE', '%' . $guildLeaderChoice . '%');

        $highscore = $query->paginate(self::RESULTS_PER_PAGE, ['*'], 'page', $page);

        return view('main/guildhighscore', [
            'highscore' => $highscore,
            'empireChoice' => $empireChoice,
            'guildChoice' => $guildChoice,
            'guildLeaderChoice' => $guildLeaderChoice,
        ]);
    }

    public function search(Request $request): View
    {
        $this->refreshCacheIfNeeded();

        $validated = $request->validate([
            'empire-choice' => 'required|int',
            'guild-choice' => 'nullable',
            'guild-leader-choice' => 'nullable',
        ]);

        $empireChoice = (int) $validated['empire-choice'];
        $guildChoice = $validated['guild-choice'];
        $guildLeaderChoice = $validated['guild-leader-choice'];

        $query = GuildHighscoreCache::query()->orderBy('id');

        // If "empire-choice" is a valid empire, add it to the query
        if (in_array($empireChoice, array_column(EmpireEnum::cases(), 'value'), true))
            $query->where('empire', $empireChoice);

        // If "guild-choice" was specified, find the guild with that name
        if (!empty($guildChoice))
            $query->where('name', 'LIKE', '%' . $guildChoice . '%');

        // If "guild-leader-choice" was specified, find the guild master with that name
        if (!empty($guildLeaderChoice))
            $query->where('master', 'LIKE', '%' . $guildLeaderChoice . '%');

        $highscore = $query->paginate(self::RESULTS_PER_PAGE);

        return view('main/guildhighscore', [
            'highscore' => $highscore,
            'empireChoice' => $empireChoice,
            'guildChoice' => $guildChoice,
            'guildLeaderChoice' => $guildLeaderChoice,
        ]);
    }
}
