<?php

namespace App\Services;

use App\Models\Torneo;
use App\Models\Equipo;
use Carbon\Carbon;

class FixtureService
{
    /**
     * Genera un fixture Round-Robin para los equipos de un torneo.
     *
     * @param Torneo $torneo
     * @param string $fechaInicio  'Y-m-d'
     * @param int    $diasEntreJornadas
     * @param string $sedeDefault
     * @param bool   $dobleRueda  Si true, genera ida y vuelta
     * @return array  Array de arrays con los datos de cada evento a crear
     */
    public function generarRoundRobin(
        Torneo $torneo,
        string $fechaInicio,
        int    $diasEntreJornadas = 7,
        ?string $sedeDefault = '',
        bool   $dobleRueda = false
    ): array {
        $equipos = $torneo->equipos()->get()->values()->toArray();
        $n       = count($equipos);

        if ($n < 2) {
            throw new \InvalidArgumentException('Se necesitan al menos 2 equipos para generar un fixture.');
        }

        // Si número impar, agregar BYE
        $hayBye = false;
        if ($n % 2 !== 0) {
            $equipos[] = null; // BYE
            $n++;
            $hayBye = true;
        }

        $mitad    = $n / 2;
        $jornadas = $n - 1;
        $partidos = [];
        $fechaActual = Carbon::parse($fechaInicio);

        // Algoritmo Round-Robin: fijar el primer equipo, rotar el resto
        $lista = range(0, $n - 1);

        for ($jornada = 0; $jornada < $jornadas; $jornada++) {
            $jornadaPartidos = [];

            for ($i = 0; $i < $mitad; $i++) {
                $localIdx    = $lista[$i];
                $visitanteIdx= $lista[$n - 1 - $i];

                // Si alguno es BYE (null), saltar
                if ($equipos[$localIdx] === null || $equipos[$visitanteIdx] === null) continue;

                $local     = $equipos[$localIdx];
                $visitante = $equipos[$visitanteIdx];

                // Alternar localía: en jornadas pares, invertir
                if ($jornada % 2 === 1) {
                    [$local, $visitante] = [$visitante, $local];
                }

                $jornadaPartidos[] = [
                    'id_equipo_local'      => $local['id_equipo'],
                    'id_equipo_visitante'  => $visitante['id_equipo'],
                    'fecha_evento'         => $fechaActual->format('Y-m-d'),
                    'hora_inicio'          => '20:00:00',
                    'hora_fin'             => '22:00:00',
                    'sede'                 => $sedeDefault,
                    'id_torneo'            => $torneo->id,
                    'nombre_evento'        => null, // se genera automáticamente
                    'precio'               => 0,
                    'jornada'              => $jornada + 1,
                ];
            }

            $partidos = array_merge($partidos, $jornadaPartidos);
            $fechaActual->addDays($diasEntreJornadas);

            // Rotar la lista (el primer elemento fijo)
            $rotatable = array_slice($lista, 1);
            array_push($rotatable, array_shift($rotatable));
            $lista = array_merge([$lista[0]], $rotatable);
        }

        // Doble rueda: agregar vuelta con localías invertidas
        if ($dobleRueda && !empty($partidos)) {
            $vuelta = [];
            foreach ($partidos as $p) {
                $vuelta[] = array_merge($p, [
                    'id_equipo_local'     => $p['id_equipo_visitante'],
                    'id_equipo_visitante' => $p['id_equipo_local'],
                    'fecha_evento'        => Carbon::parse($p['fecha_evento'])->addDays($jornadas * $diasEntreJornadas)->format('Y-m-d'),
                    'jornada'             => $p['jornada'] + $jornadas,
                ]);
            }
            $partidos = array_merge($partidos, $vuelta);
        }

        return $partidos;
    }

    /**
     * Persiste el fixture generado como Evento records en la DB.
     */
    public function persistirFixture(array $partidos, Torneo $torneo): int
    {
        $contador = 0;
        foreach ($partidos as $p) {
            $local     = Equipo::with('club')->find($p['id_equipo_local']);
            $visitante = Equipo::with('club')->find($p['id_equipo_visitante']);

            $nombreEvento = ($local->club->nombre ?? '?') . ' vs ' . ($visitante->club->nombre ?? '?');

            \App\Models\Evento::create([
                'id_evento'           => uniqid('ev_'),
                'nombre_evento'       => $nombreEvento,
                'id_equipo_local'     => $p['id_equipo_local'],
                'id_equipo_visitante' => $p['id_equipo_visitante'],
                'fecha_evento'        => $p['fecha_evento'],
                'hora_inicio'         => $p['hora_inicio'],
                'hora_fin'            => $p['hora_fin'],
                'sede'                => $p['sede'] ?: null,
                'id_torneo'           => $torneo->id,
                'precio'              => $p['precio'] ?? 0,
            ]);

            $contador++;
        }
        return $contador;
    }
}
