<?php

namespace App\Http\Controllers;

use App\Models\Calendario;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class CalendarioController extends Controller
{
    public function index(Request $request)
    {
        $anio = (int)($request->anio ?? date('Y'));

        // Auto-importar si no hay datos del año
        $existe = Calendario::whereYear('fecha', $anio)->exists();
        if (!$existe) {
            $this->generarCalendarioAnio($anio);
        }

        // Cargar todos los días del año agrupados por mes
        $dias = Calendario::whereYear('fecha', $anio)
            ->orderBy('fecha')
            ->get()
            ->groupBy(fn($d) => Carbon::parse($d->fecha)->month);

        $festivos = Calendario::whereYear('fecha', $anio)
            ->where('es_festivo', true)
            ->orderBy('fecha')
            ->get();

        $anios = range(date('Y') - 2, date('Y') + 2);

        return view('calendario.index', compact('dias', 'festivos', 'anio', 'anios'));
    }

    public function toggleFestivo(Request $request, Calendario $calendario)
    {
        $calendario->update([
            'es_festivo'          => !$calendario->es_festivo,
            'descripcion_festivo' => $calendario->es_festivo ? null : ($request->descripcion ?? 'Festivo'),
        ]);

        return response()->json([
            'es_festivo'          => $calendario->es_festivo,
            'descripcion_festivo' => $calendario->descripcion_festivo,
        ]);
    }

    public function agregarFestivo(Request $request)
    {
        $request->validate([
            'fecha'       => 'required|date',
            'descripcion' => 'required|string|max:100',
        ]);

        $cal = Calendario::where('fecha', $request->fecha)->first();

        if ($cal) {
            $cal->update([
                'es_festivo'          => true,
                'descripcion_festivo' => $request->descripcion,
            ]);
        } else {
            $fecha = Carbon::parse($request->fecha);
            Calendario::create([
                'fecha'               => $request->fecha,
                'dia_semana'          => $fecha->dayOfWeek,
                'es_festivo'          => true,
                'descripcion_festivo' => $request->descripcion,
            ]);
        }

        return back()->with('success', "Festivo '{$request->descripcion}' agregado.");
    }

    public function importarAnio(Request $request)
    {
        $anio = (int)($request->anio ?? date('Y'));
        $this->generarCalendarioAnio($anio);
        return back()->with('success', "Calendario {$anio} generado con festivos colombianos.");
    }

    // ─────────────────────────────────────────────────────────
    // Generar el año completo con festivos colombianos
    // ─────────────────────────────────────────────────────────
    private function generarCalendarioAnio(int $anio): void
    {
        $festivos = $this->festivosColombia($anio);

        $inicio = Carbon::create($anio, 1, 1);
        $fin    = Carbon::create($anio, 12, 31);

        DB::transaction(function () use ($inicio, $fin, $festivos) {
            $current = $inicio->copy();
            while ($current <= $fin) {
                $fecha = $current->format('Y-m-d');
                $esFestivo = isset($festivos[$fecha]);

                Calendario::updateOrCreate(
                    ['fecha' => $fecha],
                    [
                        'dia_semana'          => $current->dayOfWeek,
                        'es_festivo'          => $esFestivo,
                        'descripcion_festivo' => $esFestivo ? $festivos[$fecha] : null,
                    ]
                );
                $current->addDay();
            }
        });
    }

    // ─────────────────────────────────────────────────────────
    // Festivos colombianos — Ley 51/1983 (Emiliani)
    // ─────────────────────────────────────────────────────────
    private function festivosColombia(int $anio): array
    {
        $festivos = [];

        // Función para trasladar al siguiente lunes
        $nextLunes = function (Carbon $fecha): Carbon {
            if ($fecha->dayOfWeek === Carbon::MONDAY) return $fecha;
            return $fecha->next(Carbon::MONDAY);
        };

        // ── Festivos fijos (no se trasladan) ─────────────────
        $fijos = [
            "01-01" => "Año Nuevo",
            "05-01" => "Día del Trabajo",
            "07-20" => "Día de la Independencia",
            "08-07" => "Batalla de Boyacá",
            "12-08" => "Inmaculada Concepción",
            "12-25" => "Navidad",
        ];
        foreach ($fijos as $mmdd => $nombre) {
            $festivos["{$anio}-{$mmdd}"] = $nombre;
        }

        // ── Festivos trasladados al lunes (Ley Emiliani) ─────
        $emiliani = [
            "01-06" => "Reyes Magos",
            "03-19" => "San José",
            "06-29" => "San Pedro y San Pablo",
            "08-15" => "Asunción de la Virgen",
            "10-12" => "Día de la Raza",
            "11-01" => "Todos los Santos",
            "11-11" => "Independencia de Cartagena",
        ];
        foreach ($emiliani as $mmdd => $nombre) {
            [$mes, $dia] = explode('-', $mmdd);
            $fecha = Carbon::create($anio, (int)$mes, (int)$dia);
            $festivos[$nextLunes($fecha)->format('Y-m-d')] = $nombre;
        }

        // ── Semana Santa (basados en Pascua) ─────────────────
        $pascua = $this->calcularPascua($anio);

        // Jueves y Viernes Santo — fijos (no se trasladan)
        $festivos[$pascua->copy()->subDays(3)->format('Y-m-d')] = "Jueves Santo";
        $festivos[$pascua->copy()->subDays(2)->format('Y-m-d')] = "Viernes Santo";

        // Ascensión (+39 días) → siguiente lunes
        $festivos[$nextLunes($pascua->copy()->addDays(39))->format('Y-m-d')] = "Ascensión del Señor";

        // Corpus Christi (+60 días) → siguiente lunes
        $festivos[$nextLunes($pascua->copy()->addDays(60))->format('Y-m-d')] = "Corpus Christi";

        // Sagrado Corazón (+68 días) → siguiente lunes
        $festivos[$nextLunes($pascua->copy()->addDays(68))->format('Y-m-d')] = "Sagrado Corazón de Jesús";

        return $festivos;
    }

    // ─────────────────────────────────────────────────────────
    // Algoritmo de Meeus para calcular el Domingo de Pascua
    // ─────────────────────────────────────────────────────────
    private function calcularPascua(int $anio): Carbon
    {
        $a = $anio % 19;
        $b = (int)($anio / 100);
        $c = $anio % 100;
        $d = (int)($b / 4);
        $e = $b % 4;
        $f = (int)(($b + 8) / 25);
        $g = (int)(($b - $f + 1) / 3);
        $h = (19 * $a + $b - $d - $g + 15) % 30;
        $i = (int)($c / 4);
        $k = $c % 4;
        $l = (32 + 2 * $e + 2 * $i - $h - $k) % 7;
        $m = (int)(($a + 11 * $h + 22 * $l) / 451);
        $mes = (int)(($h + $l - 7 * $m + 114) / 31);
        $dia = (($h + $l - 7 * $m + 114) % 31) + 1;

        return Carbon::create($anio, $mes, $dia);
    }
}
