<?php

namespace App\Http\Controllers\Api;

use App\Contracts\Repositories\MatchRepositoryInterface;
use App\Http\Controllers\Controller;
use App\Models\FootballMatch;
use App\Services\MatchService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class MatchController extends Controller
{
    public function __construct(
        private readonly MatchService             $matchService,
        private readonly MatchRepositoryInterface $matches,
    ) {}

    public function index(): JsonResponse
    {
        $matches = $this->matches->all()->map(fn (FootballMatch $m) => $this->formatMatch($m));

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

    public function active(): JsonResponse
    {
        $match = $this->matches->findActive();

        if (! $match) {
            return response()->json(['data' => null]);
        }

        return response()->json(['data' => $match->toBroadcastState()]);
    }

    public function show(FootballMatch $match): JsonResponse
    {
        $match->load(['homeTeam', 'awayTeam', 'events']);

        return response()->json(['data' => $match->toBroadcastState()]);
    }

    public function store(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'homeTeamId'  => 'required|exists:teams,id',
            'awayTeamId'  => 'required|exists:teams,id|different:homeTeamId',
            'date'        => 'required|date',
            'venue'       => 'nullable|string|max:255',
            'competition' => 'nullable|string|max:255',
            'notes'       => 'nullable|string|max:500',
        ]);

        $match = $this->matches->create([
            'home_team_id'      => $validated['homeTeamId'],
            'away_team_id'      => $validated['awayTeamId'],
            'date'              => $validated['date'],
            'venue'             => $validated['venue'] ?? null,
            'competition'       => $validated['competition'] ?? 'Приятелски',
            'notes'             => $validated['notes'] ?? null,
            'status'            => 'scheduled',
            'score_home'        => 0,
            'score_away'        => 0,
            'period'            => 'pre',
            'timer_accumulated' => 0,
            'running'           => false,
            'show_overlay'      => true,
            'extra_time'        => 0,
        ]);

        $match->load(['homeTeam', 'awayTeam']);

        return response()->json(['data' => $this->formatMatch($match)], 201);
    }

    public function update(Request $request, FootballMatch $match): JsonResponse
    {
        $validated = $request->validate([
            'homeTeamId'  => 'sometimes|exists:teams,id',
            'awayTeamId'  => 'sometimes|exists:teams,id',
            'date'        => 'sometimes|date',
            'venue'       => 'nullable|string|max:255',
            'competition' => 'nullable|string|max:255',
            'status'      => ['sometimes', Rule::in(['scheduled', 'live', 'finished'])],
            'notes'       => 'nullable|string|max:500',
        ]);

        $updated = $this->matches->update($match, array_filter([
            'home_team_id' => $validated['homeTeamId'] ?? null,
            'away_team_id' => $validated['awayTeamId'] ?? null,
            'date'         => $validated['date'] ?? null,
            'venue'        => $validated['venue'] ?? null,
            'competition'  => $validated['competition'] ?? null,
            'status'       => $validated['status'] ?? null,
            'notes'        => $validated['notes'] ?? null,
        ], fn ($v) => $v !== null));

        return response()->json(['data' => $this->formatMatch($updated)]);
    }

    public function destroy(FootballMatch $match): JsonResponse
    {
        $this->matches->delete($match);

        return response()->json(['message' => 'Match deleted.']);
    }

    // ─── Live control actions ─────────────────────────────────────────────────

    public function timerStart(FootballMatch $match): JsonResponse
    {
        $this->matchService->startTimer($match);

        return response()->json(['ok' => true]);
    }

    public function timerPause(FootballMatch $match): JsonResponse
    {
        $this->matchService->pauseTimer($match);

        return response()->json(['ok' => true]);
    }

    public function timerStop(FootballMatch $match): JsonResponse
    {
        $this->matchService->stopTimer($match);

        return response()->json(['ok' => true]);
    }

    public function timerSet(Request $request, FootballMatch $match): JsonResponse
    {
        $request->validate(['seconds' => 'required|integer|min:0|max:7200']);
        $this->matchService->setTimer($match, (int) $request->seconds);

        return response()->json(['ok' => true]);
    }

    public function scoreAdjust(Request $request, FootballMatch $match): JsonResponse
    {
        $request->validate([
            'side'  => ['required', Rule::in(['home', 'away'])],
            'delta' => 'required|integer',
        ]);
        $this->matchService->adjustScore($match, $request->side, (int) $request->delta);

        return response()->json(['ok' => true]);
    }

    public function setPeriod(Request $request, FootballMatch $match): JsonResponse
    {
        $request->validate([
            'period' => ['required', Rule::in(['pre', 'first', 'halftime', 'second', 'extra1', 'extra2', 'full'])],
        ]);
        $this->matchService->setPeriod($match, $request->period);

        return response()->json(['ok' => true]);
    }

    public function setExtraTime(Request $request, FootballMatch $match): JsonResponse
    {
        $request->validate(['minutes' => 'required|integer|min:0|max:30']);
        $this->matchService->setExtraTime($match, (int) $request->minutes);

        return response()->json(['ok' => true]);
    }

    public function clearPopup(FootballMatch $match): JsonResponse
    {
        $this->matchService->clearPopup($match);

        return response()->json(['ok' => true]);
    }

    public function toggleSponsors(FootballMatch $match): JsonResponse
    {
        $this->matchService->toggleSponsors($match);

        return response()->json(['ok' => true]);
    }

    public function setLineup(Request $request, FootballMatch $match): JsonResponse
    {
        $request->validate(['side' => 'nullable|in:home,away']);

        $this->matchService->setLineup($match, $request->input('side'));

        return response()->json(['ok' => true]);
    }

    public function toggleOverlay(FootballMatch $match): JsonResponse
    {
        $this->matchService->toggleOverlay($match);

        return response()->json(['ok' => true]);
    }

    public function reset(FootballMatch $match): JsonResponse
    {
        $this->matchService->resetMatch($match);

        return response()->json(['ok' => true]);
    }

    /**
     * Stop any running match, reset this match to a fresh state, and
     * broadcast it as the current active match.
     * Returns the full broadcast state so the control panel can sync.
     */
    public function activate(FootballMatch $match): JsonResponse
    {
        $fresh = $this->matchService->activateMatch($match);

        return response()->json(['data' => $fresh->toBroadcastState()]);
    }

    // ─── Private helper ───────────────────────────────────────────────────────

    private function formatMatch(FootballMatch $m): array
    {
        return [
            'id'          => $m->id,
            'homeTeamId'  => $m->home_team_id,
            'awayTeamId'  => $m->away_team_id,
            'homeTeam'    => $m->homeTeam
                ? ['id' => $m->homeTeam->id, 'name' => $m->homeTeam->name]
                : null,
            'awayTeam'    => $m->awayTeam
                ? ['id' => $m->awayTeam->id, 'name' => $m->awayTeam->name]
                : null,
            'date'        => $m->date?->toISOString(),
            'venue'       => $m->venue,
            'competition' => $m->competition,
            'status'      => $m->status,
            'scoreHome'   => $m->score_home,
            'scoreAway'   => $m->score_away,
            'notes'       => $m->notes,
        ];
    }
}
