<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Torneo;
use App\Services\FixtureService;

class FixtureController extends Controller
{
    private FixtureService $fixtureService;

    public function __construct(FixtureService $fixtureService)
    {
        $this->fixtureService = $fixtureService;
    }

    private function checkSuperAdmin()
    {
        if (!session('admin_logged_in') || session('admin_role') != 1) {
            abort(403, 'Solo Súper Administradores pueden generar fixtures.');
        }
    }

    /**
     * POST /admin/torneos/{id}/generar-fixture — Preview del fixture
     */
    public function preview(Request $request, int $id)
    {
        $this->checkSuperAdmin();

        $torneo = Torneo::with('equipos.club')->findOrFail($id);

        $request->validate([
            'fecha_inicio'        => 'required|date|after_or_equal:today',
            'dias_entre_jornadas' => 'required|integer|min:1|max:60',
            'sede_default'        => 'nullable|string|max:200',
            'doble_rueda'         => 'nullable|boolean',
        ]);

        try {
            $partidos = $this->fixtureService->generarRoundRobin(
                torneo:              $torneo,
                fechaInicio:         $request->input('fecha_inicio'),
                diasEntreJornadas:   (int) $request->input('dias_entre_jornadas', 7),
                sedeDefault:         $request->input('sede_default', ''),
                dobleRueda:          (bool) $request->input('doble_rueda', false),
            );

            // Enriquecer con nombres para la vista
            $partidosEnriquecidos = collect($partidos)->map(function ($p) {
                $local     = \App\Models\Equipo::with('club')->find($p['id_equipo_local']);
                $visitante = \App\Models\Equipo::with('club')->find($p['id_equipo_visitante']);
                return array_merge($p, [
                    'nombre_local'     => ($local->club->nombre ?? '?') . ' (' . ($local->categoria ?? '') . ')',
                    'nombre_visitante' => ($visitante->club->nombre ?? '?') . ' (' . ($visitante->categoria ?? '') . ')',
                ]);
            })->toArray();

        } catch (\InvalidArgumentException $e) {
            return back()->with('admin_error', $e->getMessage());
        }

        $fixtureParams = [
            'fecha_inicio'        => $request->input('fecha_inicio'),
            'dias_entre_jornadas' => $request->input('dias_entre_jornadas', 7),
            'sede_default'        => $request->input('sede_default', ''),
            'doble_rueda'         => (bool) $request->input('doble_rueda', false),
        ];

        return view('admin.torneos.fixture_preview', compact('torneo', 'partidosEnriquecidos', 'fixtureParams'));

    }

    /**
     * POST /admin/torneos/{id}/confirmar-fixture — Persiste el fixture
     */
    public function confirmar(Request $request, int $id)
    {
        $this->checkSuperAdmin();

        $torneo = Torneo::with('equipos.club')->findOrFail($id);

        $request->validate([
            'fecha_inicio'        => 'required|date',
            'dias_entre_jornadas' => 'required|integer|min:1',
            'sede_default'        => 'nullable|string|max:200',
            'doble_rueda'         => 'nullable|boolean',
        ]);

        try {
            $partidos = $this->fixtureService->generarRoundRobin(
                torneo:            $torneo,
                fechaInicio:       $request->input('fecha_inicio'),
                diasEntreJornadas: (int) $request->input('dias_entre_jornadas', 7),
                sedeDefault:       $request->input('sede_default', ''),
                dobleRueda:        (bool) $request->input('doble_rueda', false),
            );

            $creados = $this->fixtureService->persistirFixture($partidos, $torneo);

        } catch (\InvalidArgumentException $e) {
            return back()->with('admin_error', $e->getMessage());
        }

        return redirect()->route('admin.torneos.edit', $id)
            ->with('admin_msg', "✅ Fixture generado correctamente: {$creados} partidos creados.");
    }

    public function importForm(int $id)
    {
        $this->checkSuperAdmin();
        $torneo = Torneo::findOrFail($id);
        return view('admin.torneos.importar', compact('torneo'));
    }

    public function importStore(Request $request, int $id)
    {
        $this->checkSuperAdmin();
        $torneo = Torneo::with(['equipos.club'])->findOrFail($id);

        $request->validate([
            'texto_importar' => 'required|string',
        ]);

        $lineas = explode("\n", $request->input('texto_importar'));
        $creados = 0;
        $errores = [];

        foreach ($lineas as $index => $linea) {
            $linea = trim($linea);
            if (empty($linea)) continue;

            try {
                // Formato esperado: Fecha, ClubL, CatL, ClubV, CatV, MarcadorL, MarcadorV, Sede, Grupo
                $partes = str_getcsv($linea);
                
                if (count($partes) < 7) {
                    throw new \Exception("Formato insuficiente. Se esperan al menos 7 columnas.");
                }

                $fechaRaw        = trim($partes[0]);
                $fecha = \Carbon\Carbon::parse(str_replace('/', '-', $fechaRaw))->format('Y-m-d');

                $nombreClubL     = trim($partes[1]);
                $catL            = trim($partes[2]);
                $nombreClubV     = trim($partes[3]);
                $catV            = trim($partes[4]);
                $marcadorL       = trim($partes[5]);
                $marcadorV       = trim($partes[6]);
                $sede            = $partes[7] ?? null;
                $grupo           = $partes[8] ?? null;

                // Buscar equipos con validación de grupo (prioridad) y categoría
                $equipoL = $this->buscarEquipo($nombreClubL, $catL, $torneo, $grupo);
                $equipoV = $this->buscarEquipo($nombreClubV, $catV, $torneo, $grupo);

                if (!$equipoL || !$equipoV) {
                    $missing = !$equipoL ? "'{$nombreClubL} ({$catL})'" : "'{$nombreClubV} ({$catV})'";
                    throw new \Exception("No se encontró el equipo {$missing} en el grupo '" . ($grupo ?? 'N/A') . "' ni por categoría.");
                }

                \App\Models\Evento::create([
                    'id_evento'           => uniqid('ev_imp_'),
                    'id_torneo'           => $id,
                    'fase'                => \App\Models\Evento::FASE_REGULAR,
                    'fecha_evento'        => $fecha,
                    'id_equipo_local'     => $equipoL->id_equipo,
                    'id_equipo_visitante' => $equipoV->id_equipo,
                    'marcador_local'      => $marcadorL !== '' ? (int)$marcadorL : null,
                    'marcador_visitante'  => $marcadorV !== '' ? (int)$marcadorV : null,
                    'nombre_evento'       => $equipoL->club->nombre . ' vs ' . $equipoV->club->nombre,
                    'hora_inicio'         => '19:00:00',
                    'hora_fin'            => '21:00:00',
                    'sede'                => $sede,
                    'precio'              => 0,
                ]);

                $creados++;
            } catch (\Exception $e) {
                $errores[] = "Línea " . ($index + 1) . ": " . $e->getMessage();
                continue;
            }
        }

        $msg = "Se importaron {$creados} partidos exitosamente.";
        if (count($errores) > 0) {
            return back()->with('admin_msg', $msg)->with('admin_error', "Se detectaron errores en " . count($errores) . " líneas:<br>" . implode("<br>", $errores));
        }

        return redirect()->route('admin.torneos.edit', $id)->with('admin_msg', $msg);
    }

    private function buscarEquipo(string $clubName, string $category, Torneo $torneo, ?string $grupo = null)
    {
        $clubNameNorm = $this->normalizeString($clubName);
        $categoryNorm = $this->normalizeString($category);
        $grupoNorm    = $grupo ? $this->normalizeString($grupo) : null;

        // PASO 1: Prioridad absoluta al GRUPO (vía pivot)
        if ($grupoNorm) {
            $match = $torneo->equipos->first(function($e) use ($clubNameNorm, $grupoNorm) {
                $eClubName = $this->normalizeString($e->club->nombre ?? '');
                $eGrupo    = $this->normalizeString($e->pivot->grupo ?? '');
                
                return ($eGrupo === $grupoNorm) && 
                       (strpos($eClubName, $clubNameNorm) !== false || strpos($clubNameNorm, $eClubName) !== false);
            });
            if ($match) return $match;
        }

        // PASO 2: Fallback a búsqueda por CATEGORÍA si el grupo no coincide o no se especificó
        return $torneo->equipos->first(function($e) use ($clubNameNorm, $categoryNorm) {
            $eClubName = $this->normalizeString($e->club->nombre ?? '');
            $eCategory = $this->normalizeString($e->categoria ?? '');
            
            $matchClub = (strpos($eClubName, $clubNameNorm) !== false || strpos($clubNameNorm, $eClubName) !== false);
            $matchCat  = (strpos($eCategory, $categoryNorm) !== false || strpos($categoryNorm, $eCategory) !== false);
            
            return $matchClub && $matchCat;
        });
    }

    private function normalizeString(?string $str): string
    {
        if (!$str) return '';
        $str = mb_strtolower(trim($str), 'UTF-8');
        $str = str_replace(
            ['á', 'é', 'í', 'ó', 'ú', 'ü', 'ñ'],
            ['a', 'e', 'i', 'o', 'u', 'u', 'n'],
            $str
        );
        // Eliminar caracteres no alfanuméricos para un matching más flexible
        return preg_replace('/[^a-z0-9]/', '', $str);
    }

    public function generarPlayoffs(Request $request, int $id)
    {
        $this->checkSuperAdmin();
        $torneo = Torneo::findOrFail($id);
        $grupo = $request->input('grupo');
        $formato = (int) $request->input('formato', 1); // 1, 3, 5

        if (!$grupo) {
            return back()->with('admin_error', 'Debes seleccionar un grupo para generar los playoffs.');
        }

        $ts = new \App\Services\TournamentService();
        $standings = $ts->getStandings($id, true);

        if (!isset($standings[$grupo])) {
            return back()->with('admin_error', "No hay equipos en el grupo {$grupo}.");
        }

        $top8 = array_slice($standings[$grupo], 0, 8);

        if (count($top8) < 2) {
            return back()->with('admin_error', "Se necesitan al menos 2 equipos para generar playoffs.");
        }

        // Determinar emparejamientos (1 vs 8, 4 vs 5, 2 vs 7, 3 vs 6)
        // Usamos el seeding oficial: 1v8, 4v5, 2v7, 3v6
        $parejas = [
            ['local' => $top8[0]['id'], 'visit' => $top8[7]['id'] ?? null, 'nro' => 1],
            ['local' => $top8[3]['id'] ?? null, 'visit' => $top8[4]['id'] ?? null, 'nro' => 2],
            ['local' => $top8[1]['id'] ?? null, 'visit' => $top8[6]['id'] ?? null, 'nro' => 3],
            ['local' => $top8[2]['id'] ?? null, 'visit' => $top8[5]['id'] ?? null, 'nro' => 4],
        ];

        $count = 0;
        foreach ($parejas as $p) {
            if (!$p['local'] || !$p['visit']) continue;

            $local = \App\Models\Equipo::with('club')->find($p['local']);
            $visit = \App\Models\Equipo::with('club')->find($p['visit']);

            // Crear N partidos según el formato
            for ($i = 0; $i < $formato; $i++) {
                \App\Models\Evento::create([
                    'id_evento'           => uniqid('ply_'),
                    'id_torneo'           => $id,
                    'fase'                => \App\Models\Evento::FASE_CUARTOS,
                    'numero_partido_bracket' => $p['nro'],
                    'id_equipo_local'     => $p['local'],
                    'id_equipo_visitante' => $p['visit'],
                    'nombre_evento'       => "4tos (J".($i+1)."): " . $local->club->nombre . " vs " . $visit->club->nombre . " ({$grupo})",
                    'fecha_evento'        => now()->addDays(7 + ($i * 3))->format('Y-m-d'),
                    'hora_inicio'         => '20:00:00',
                    'hora_fin'            => '22:00:00',
                    'precio'              => 0,
                ]);
                $count++;
            }
        }

        return redirect()->route('admin.torneos.playoffs.manage', $id)
            ->with('admin_msg', "Playoffs generados: {$count} partidos creados para el grupo {$grupo}.");
    }

    public function managePlayoffs(int $id)
    {
        $this->checkSuperAdmin();
        $torneo = Torneo::findOrFail($id);
        
        $ts = new \App\Services\TournamentService();
        $bracket = $ts->getPlayoffBrackets($id);
        
        $grupos = \DB::table('torneo_equipo')->where('id_torneo', $id)->distinct()->pluck('grupo')->filter();

        return view('admin.torneos.playoff_manage', compact('torneo', 'bracket', 'grupos'));
    }

    public function avanzarGanador(Request $request, int $id)
    {
        $this->checkSuperAdmin();
        $faseActual = (int) $request->input('fase');
        $nroBracket = (int) $request->input('nro_bracket');
        $idGanador  = (int) $request->input('id_ganador');

        $torneo = Torneo::findOrFail($id);
        $ganador = \App\Models\Equipo::with('club')->findOrFail($idGanador);

        // Mapeo de avance
        // Cuartos 1 & 2 -> Semis 1
        // Cuartos 3 & 4 -> Semis 2
        // Semis 1 & 2 -> Final 1
        $mapping = [
            \App\Models\Evento::FASE_CUARTOS => [
                1 => ['next_fase' => \App\Models\Evento::FASE_SEMIS, 'next_nro' => 1, 'side' => 'local'],
                2 => ['next_fase' => \App\Models\Evento::FASE_SEMIS, 'next_nro' => 1, 'side' => 'visitante'],
                3 => ['next_fase' => \App\Models\Evento::FASE_SEMIS, 'next_nro' => 2, 'side' => 'local'],
                4 => ['next_fase' => \App\Models\Evento::FASE_SEMIS, 'next_nro' => 2, 'side' => 'visitante'],
            ],
            \App\Models\Evento::FASE_SEMIS => [
                1 => ['next_fase' => \App\Models\Evento::FASE_FINAL, 'next_nro' => 1, 'side' => 'local'],
                2 => ['next_fase' => \App\Models\Evento::FASE_FINAL, 'next_nro' => 1, 'side' => 'visitante'],
            ]
        ];

        if (!isset($mapping[$faseActual][$nroBracket])) {
            return back()->with('admin_error', 'No se puede avanzar desde esta fase.');
        }

        $next = $mapping[$faseActual][$nroBracket];
        
        // Buscar si ya existe el partido en la siguiente fase
        $eventoNext = \App\Models\Evento::where('id_torneo', $id)
            ->where('fase', $next['next_fase'])
            ->where('numero_partido_bracket', $next['next_nro'])
            ->first();

        if ($eventoNext) {
            if ($next['side'] == 'local') {
                $eventoNext->id_equipo_local = $idGanador;
            } else {
                $eventoNext->id_equipo_visitante = $idGanador;
            }
            $eventoNext->nombre_evento = ($eventoNext->equipoLocal->club->nombre ?? 'TBD') . ' vs ' . ($eventoNext->equipoVisitante->club->nombre ?? 'TBD');
            $eventoNext->save();
        } else {
            // Crear el primer partido de la serie (por defecto 1 partido, el admin puede agregar más)
            \App\Models\Evento::create([
                'id_evento'           => uniqid('ply_adv_'),
                'id_torneo'           => $id,
                'fase'                => $next['next_fase'],
                'numero_partido_bracket' => $next['next_nro'],
                'id_equipo_local'     => $next['side'] == 'local' ? $idGanador : null,
                'id_equipo_visitante' => $next['side'] == 'visitante' ? $idGanador : null,
                'nombre_evento'       => $next['side'] == 'local' ? ($ganador->club->nombre . " vs TBD") : ("TBD vs " . $ganador->club->nombre),
                'fecha_evento'        => now()->addDays(14)->format('Y-m-d'),
                'hora_inicio'         => '20:00:00',
                'hora_fin'            => '22:00:00',
                'precio'              => 0,
            ]);
        }

        return back()->with('admin_msg', "✅ Equipo {$ganador->club->nombre} avanzado a la siguiente ronda.");
    }
}
