<?php

namespace App\Http\Controllers\Admin\Web;

use App\Http\Controllers\Controller;
use App\Models\FootballMatch;
use App\Models\Team;
use App\Services\PredictionService;
use App\Interfaces\FootballMatchRepositoryInterface;
use App\Interfaces\PredictionRepositoryInterface;
use Carbon\Carbon;
use Illuminate\Http\Request;

class AdminWebMatchController extends Controller
{
    public function __construct(
        private readonly FootballMatchRepositoryInterface $matchRepo,
        private readonly PredictionService $predictionService
    ) {}

    /**
     * Convert a "datetime-local" form value (entered by the admin in
     * config('app.admin_timezone'), e.g. Asia/Dhaka GMT+6) into a UTC
     * Carbon instance for storage.
     *
     * The Flutter app then converts UTC -> each user's own device
     * timezone automatically, so every fan sees the correct local
     * kickoff time.
     */
    private function adminTimeToUtc(string $value): Carbon
    {
        return Carbon::createFromFormat('Y-m-d\TH:i', $value, config('app.admin_timezone'))
            ->setTimezone('UTC');
    }

    public function index()
    {
        $matches = FootballMatch::with(['homeTeam', 'awayTeam'])
            ->orderBy('match_datetime')
            ->paginate(20);

        return view('admin.matches.index', compact('matches'));
    }

    public function create()
    {
        $teams = Team::orderBy('group_name')->orderBy('name')->get();
        return view('admin.matches.create', compact('teams'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'home_team_id'   => ['required', 'integer', 'exists:teams,id', 'different:away_team_id'],
            'away_team_id'   => ['required', 'integer', 'exists:teams,id'],
            'match_datetime' => ['required', 'date'],
            'venue'          => ['nullable', 'string', 'max:150'],
            'stage'          => ['required', 'in:group,round_of_16,quarterfinal,semifinal,final'],
            'group_name'     => ['nullable', 'string', 'size:1', 'regex:/^[A-La-l]$/i'],
        ]);

        $validated['group_name'] = isset($validated['group_name'])
            ? strtoupper($validated['group_name'])
            : null;

        // Admin enters kickoff time in config('app.admin_timezone') —
        // convert to UTC for storage.
        $validated['match_datetime'] = $this->adminTimeToUtc($validated['match_datetime']);

        $this->matchRepo->create($validated);

        return redirect()->route('admin.matches.index')
                         ->with('success', 'Match created successfully!');
    }

    public function edit(int $id)
    {
        $match = FootballMatch::with(['homeTeam', 'awayTeam'])->findOrFail($id);
        $teams = Team::orderBy('group_name')->orderBy('name')->get();

        // Convert the stored UTC kickoff time to the admin's timezone for
        // display in the datetime-local input.
        $matchDatetimeLocal = $match->match_datetime
            ->copy()
            ->setTimezone(config('app.admin_timezone'))
            ->format('Y-m-d\TH:i');

        return view('admin.matches.edit', compact('match', 'teams', 'matchDatetimeLocal'));
    }

    public function update(Request $request, int $id)
    {
        $validated = $request->validate([
            'status'               => ['required', 'in:upcoming,live,finished'],
            'home_score'           => ['nullable', 'integer', 'min:0'],
            'away_score'           => ['nullable', 'integer', 'min:0'],
            'match_datetime'       => ['required', 'date'],
            'venue'                => ['nullable', 'string', 'max:150'],
            'home_community_votes' => ['nullable', 'integer', 'min:0'],
            'away_community_votes' => ['nullable', 'integer', 'min:0'],
            'draw_community_votes' => ['nullable', 'integer', 'min:0'],
        ]);

        $match = FootballMatch::findOrFail($id);
        $wasNotFinished = $match->status !== 'finished';

        // Admin's hidden/edited kickoff time is in config('app.admin_timezone') —
        // convert to UTC for storage.
        $validated['match_datetime'] = $this->adminTimeToUtc($validated['match_datetime']);

        $this->matchRepo->update($id, $validated);
        $match->refresh();

        // Auto-resolve predictions when match is marked finished
        if ($wasNotFinished && $match->status === 'finished'
            && $match->home_score !== null && $match->away_score !== null) {
            $result = match (true) {
                $match->home_score > $match->away_score => 'home',
                $match->away_score > $match->home_score => 'away',
                default                                 => 'draw',
            };
            $this->predictionService->resolveMatch($match, $result);
        }

        return redirect()->route('admin.matches.index')
                         ->with('success', 'Match updated! Predictions resolved automatically.');
    }

    /**
     * Update the AI prediction block for a match: win probabilities,
     * confidence level, analysis text, key insights, and predicted score.
     * Kept as a separate action so the score/status form above can be
     * submitted independently without re-validating AI fields.
     */
    public function updateAiPrediction(Request $request, int $id)
    {
        $validated = $request->validate([
            'home_win_probability' => ['required', 'numeric', 'min:0', 'max:100'],
            'draw_probability'     => ['required', 'numeric', 'min:0', 'max:100'],
            'away_win_probability' => ['required', 'numeric', 'min:0', 'max:100'],
            'confidence_level'     => ['required', 'in:low,medium,high'],
            'ai_analysis'          => ['nullable', 'string', 'max:2000'],
            'key_insights'         => ['nullable', 'array'],
            'key_insights.*'       => ['nullable', 'string', 'max:255'],
            'predicted_score_home' => ['nullable', 'integer', 'min:0', 'max:20'],
            'predicted_score_away' => ['nullable', 'integer', 'min:0', 'max:20'],
        ]);

        // Probabilities should sum to ~100. Allow small rounding tolerance.
        $sum = $validated['home_win_probability']
             + $validated['draw_probability']
             + $validated['away_win_probability'];

        if (abs($sum - 100) > 0.5) {
            return back()->withInput()->with('error',
                "Win probabilities must add up to 100%. They currently total {$sum}%.");
        }

        // Drop empty insight lines
        $validated['key_insights'] = array_values(array_filter(
            $validated['key_insights'] ?? [],
            fn ($line) => trim((string) $line) !== ''
        ));

        $this->matchRepo->update($id, $validated);

        return redirect()->route('admin.matches.edit', $id)
                         ->with('success', 'AI prediction updated! This now appears in the app.');
    }

    /**
     * Delete a match. Only upcoming matches can be deleted to prevent
     * accidental removal of completed data.
     */
    public function destroy(int $id): \Illuminate\Http\RedirectResponse
    {
        $match = FootballMatch::findOrFail($id);

        if ($match->status !== 'upcoming') {
            return redirect()->route('admin.matches.index')
                ->with('error', 'Only upcoming matches can be deleted.');
        }

        $match->delete();

        return redirect()->route('admin.matches.index')
            ->with('success', 'Match deleted.');
    }
}
