<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\GameMatch;
use App\Models\Tournament;
use App\Models\TournamentMatch;
use App\Models\User;
use App\Services\MatchResultService;
use App\Services\TournamentBracketService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class BotController extends Controller
{
    public function __construct(
        private readonly MatchResultService      $resultService,
        private readonly TournamentBracketService $bracket,
    ) {}

    // -------------------------------------------------------------------------
    // GET /api/bot/pending-matches
    // Returns all pending/in_progress/submitted ranked matches with player info.
    // -------------------------------------------------------------------------
    public function pendingMatches(): JsonResponse
    {
        $matches = GameMatch::with(['host:id,username,discord_id,elo', 'guest:id,username,discord_id,elo'])
            ->whereIn('status', ['pending', 'in_progress', 'submitted'])
            ->latest()
            ->limit(50)
            ->get()
            ->map(fn ($m) => [
                'id'          => $m->id,
                'status'      => $m->status,
                'host'        => ['id' => $m->host_id,  'username' => $m->host?->username,  'discord_id' => $m->host?->discord_id,  'elo' => $m->host?->elo],
                'guest'       => ['id' => $m->guest_id, 'username' => $m->guest?->username, 'discord_id' => $m->guest?->discord_id, 'elo' => $m->guest?->elo],
                'submitted'   => [
                    'host'  => $m->hasHostSubmitted(),
                    'guest' => $m->hasGuestSubmitted(),
                ],
            ]);

        return response()->json(['matches' => $matches]);
    }

    // -------------------------------------------------------------------------
    // POST /api/bot/match-score
    // Admin bot submits final score directly (bypasses dual-submit flow).
    // Body: { match_id, score_host, score_guest }
    // -------------------------------------------------------------------------
    public function submitMatchScore(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'match_id'    => ['required', 'integer', 'exists:matches,id'],
            'score_host'  => ['required', 'integer', 'min:0', 'max:99'],
            'score_guest' => ['required', 'integer', 'min:0', 'max:99'],
        ]);

        $match = GameMatch::with(['host', 'guest'])->findOrFail($validated['match_id']);

        if ($match->status === 'completed') {
            return response()->json(['error' => 'Match already completed.'], 422);
        }

        $this->resultService->finalize(
            $match,
            $validated['score_host'],
            $validated['score_guest']
        );

        $match->refresh();

        return response()->json([
            'ok'          => true,
            'match_id'    => $match->id,
            'score_host'  => $match->score_host,
            'score_guest' => $match->score_guest,
            'winner'      => $match->winner?->username,
            'elo'         => [
                'host'  => ['change' => $match->elo_change_host,  'new' => $match->host?->elo],
                'guest' => ['change' => $match->elo_change_guest, 'new' => $match->guest?->elo],
            ],
        ]);
    }

    // -------------------------------------------------------------------------
    // GET /api/bot/tournaments
    // Returns tournaments that are in_progress or registration.
    // -------------------------------------------------------------------------
    public function tournaments(): JsonResponse
    {
        $tournaments = Tournament::withCount('participants')
            ->whereIn('status', ['registration', 'in_progress'])
            ->latest()
            ->get()
            ->map(fn ($t) => [
                'id'     => $t->id,
                'title'  => $t->title,
                'status' => $t->status,
                'format' => $t->format,
                'players_count' => $t->participants_count,
                'max_players'   => $t->max_players,
            ]);

        return response()->json(['tournaments' => $tournaments]);
    }

    // -------------------------------------------------------------------------
    // GET /api/bot/tournament/{id}/pending-matches
    // Returns pending tournament matches for a specific tournament.
    // -------------------------------------------------------------------------
    public function tournamentPendingMatches(int $id): JsonResponse
    {
        $tournament = Tournament::findOrFail($id);

        $matches = TournamentMatch::where('tournament_id', $id)
            ->where('status', 'pending')
            ->whereNotNull('player1_id')
            ->whereNotNull('player2_id')
            ->with(['player1:id,username,discord_id', 'player2:id,username,discord_id'])
            ->orderBy('round')
            ->orderBy('match_number')
            ->get()
            ->map(fn ($m) => [
                'id'         => $m->id,
                'round'      => $m->round,
                'phase'      => $m->phase,
                'group'      => $m->group_name,
                'is_golden_goal' => $m->is_golden_goal,
                'player1'    => ['id' => $m->player1_id, 'username' => $m->player1?->username, 'discord_id' => $m->player1?->discord_id],
                'player2'    => ['id' => $m->player2_id, 'username' => $m->player2?->username, 'discord_id' => $m->player2?->discord_id],
            ]);

        return response()->json([
            'tournament' => ['id' => $tournament->id, 'title' => $tournament->title, 'format' => $tournament->format],
            'matches'    => $matches,
        ]);
    }

    // -------------------------------------------------------------------------
    // POST /api/bot/tournament-score
    // Submit score for a tournament match.
    // Body: { tournament_match_id, score1, score2 }
    // -------------------------------------------------------------------------
    public function submitTournamentScore(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'tournament_match_id' => ['required', 'integer', 'exists:tournament_matches,id'],
            'score1'              => ['required', 'integer', 'min:0', 'max:99'],
            'score2'              => ['required', 'integer', 'min:0', 'max:99'],
        ]);

        $match = TournamentMatch::with(['tournament', 'player1', 'player2'])->findOrFail($validated['tournament_match_id']);

        if ($match->status === 'completed') {
            return response()->json(['error' => 'Match already completed.'], 422);
        }

        try {
            $this->bracket->submitScore($match, $validated['score1'], $validated['score2']);
        } catch (\InvalidArgumentException $e) {
            return response()->json(['error' => $e->getMessage()], 422);
        }

        $match->refresh();

        $winner = match ($match->winner_id) {
            $match->player1_id => $match->player1?->username,
            $match->player2_id => $match->player2?->username,
            default            => null,
        };

        return response()->json([
            'ok'         => true,
            'match_id'   => $match->id,
            'tournament' => $match->tournament?->title,
            'round'      => $match->round,
            'phase'      => $match->phase,
            'group'      => $match->group_name,
            'score1'     => $match->score1,
            'score2'     => $match->score2,
            'is_draw'    => $match->is_draw,
            'is_golden_goal' => $match->is_golden_goal,
            'winner'     => $winner,
            'player1'    => $match->player1?->username,
            'player2'    => $match->player2?->username,
        ]);
    }

    // -------------------------------------------------------------------------
    // GET /api/bot/player?discord_id=xxx  OR  ?username=xxx
    // Look up a player by Discord ID or username.
    // -------------------------------------------------------------------------
    public function findPlayer(Request $request): JsonResponse
    {
        $request->validate([
            'discord_id' => ['required_without:username', 'nullable', 'string'],
            'username'   => ['required_without:discord_id', 'nullable', 'string'],
        ]);

        $user = $request->discord_id
            ? User::where('discord_id', $request->discord_id)->first()
            : User::where('username', 'like', $request->username)->first();

        if (! $user) {
            return response()->json(['error' => 'Player not found.'], 404);
        }

        return response()->json([
            'id'         => $user->id,
            'username'   => $user->username,
            'discord_id' => $user->discord_id,
            'elo'        => $user->elo,
            'rank'       => $user->rank,
            'wins'       => $user->wins,
            'losses'     => $user->losses,
            'draws'      => $user->draws,
        ]);
    }
}
