<?php

namespace App\Services;

use App\Models\Alerta;
use App\Models\Proceso;
use App\Models\User;
use Carbon\Carbon;

class NotificationService
{
    /**
     * Crear una alerta para un proceso
     */
    public static function crearAlerta(
        Proceso $proceso,
        string $tipo,
        string $titulo,
        ?string $mensaje = null,
        ?int $userId = null,
        string $prioridad = 'media',
        ?string $fechaVencimiento = null
    ): Alerta {
        return Alerta::create([
            'proceso_id' => $proceso->id,
            'user_id' => $userId,
            'tipo' => $tipo,
            'prioridad' => $prioridad,
            'titulo' => $titulo,
            'mensaje' => $mensaje,
            'fecha_disparo' => now()->toDateString(),
            'fecha_vencimiento' => $fechaVencimiento,
        ]);
    }

    /**
     * Generar alertas de vencimiento SLA para todos los procesos activos
     */
    public static function verificarSLA(): int
    {
        $count = 0;
        $procesos = Proceso::activos()
            ->with(['cliente', 'asignacionesActivas'])
            ->whereNotIn('estado', ['radicado', 'seguimiento', 'sentencia', 'liquidacion', 'terminado'])
            ->get();

        foreach ($procesos as $proceso) {
            $sla = $proceso->cliente->sla_dias_radicacion ?? 5;
            $dias = $proceso->dias_en_proceso;

            $tieneAlerta = $proceso->alertas()
                ->where('tipo', 'vencimiento_sla')
                ->noResueltas()
                ->exists();

            if ($dias >= $sla && !$tieneAlerta) {
                $asignado = $proceso->asignacionesActivas->first();

                self::crearAlerta(
                    $proceso,
                    'vencimiento_sla',
                    "SLA excedido: {$proceso->radicado_interno} ({$dias} días)",
                    "El proceso {$proceso->radicado_interno} lleva {$dias} días (SLA: {$sla} días). Cliente: {$proceso->cliente->nombre}.",
                    $asignado?->user_id,
                    $dias >= ($sla + 3) ? 'critica' : 'alta'
                );
                $count++;
            }
        }

        return $count;
    }

    /**
     * Generar alertas de vencimiento de términos procesales
     */
    public static function verificarTerminos(): int
    {
        $count = 0;
        $hoy = Carbon::now();

        $procesos = Proceso::activos()
            ->whereNotNull('fecha_vencimiento_terminos')
            ->where('fecha_vencimiento_terminos', '<=', $hoy->copy()->addDays(3))
            ->where('fecha_vencimiento_terminos', '>=', $hoy->copy()->subDays(1))
            ->with('asignacionesActivas')
            ->get();

        foreach ($procesos as $proceso) {
            $tieneAlerta = $proceso->alertas()
                ->where('tipo', 'vencimiento_terminos')
                ->noResueltas()
                ->whereDate('created_at', '>=', $hoy->copy()->subDays(2))
                ->exists();

            if (!$tieneAlerta) {
                $diasRestantes = (int) $hoy->diffInDays($proceso->fecha_vencimiento_terminos, false);
                $label = $diasRestantes > 0
                    ? "Vence en {$diasRestantes} día(s)"
                    : ($diasRestantes === 0 ? "Vence HOY" : "VENCIDO hace " . abs($diasRestantes) . " día(s)");

                $asignado = $proceso->asignacionesActivas->first();

                self::crearAlerta(
                    $proceso,
                    'vencimiento_terminos',
                    "Términos: {$proceso->radicado_interno} — {$label}",
                    "Vencimiento de términos del proceso {$proceso->radicado_interno}: {$proceso->fecha_vencimiento_terminos->format('d/m/Y')}.",
                    $asignado?->user_id,
                    $diasRestantes <= 0 ? 'critica' : ($diasRestantes <= 1 ? 'alta' : 'media'),
                    $proceso->fecha_vencimiento_terminos->toDateString()
                );
                $count++;
            }
        }

        return $count;
    }

    /**
     * Generar recordatorio de revisión de autos (Lunes y Jueves)
     */
    public static function generarRecordatorioRevision(): int
    {
        $hoy = Carbon::now();
        $diaSemana = $hoy->dayOfWeek; // 1=Lunes, 4=Jueves

        if (!in_array($diaSemana, [1, 4])) {
            return 0;
        }

        $count = 0;
        $procesosEnSeguimiento = Proceso::whereIn('estado', ['radicado', 'seguimiento'])
            ->with('asignacionesActivas')
            ->get();

        foreach ($procesosEnSeguimiento as $proceso) {
            $tieneHoy = $proceso->alertas()
                ->where('tipo', 'revision_auto')
                ->whereDate('fecha_disparo', $hoy->toDateString())
                ->exists();

            if (!$tieneHoy) {
                $dependiente = $proceso->asignacionesActivas
                    ->where('rol_asignado', 'dependiente')
                    ->first();

                $dia = $diaSemana === 1 ? 'Lunes' : 'Jueves';
                self::crearAlerta(
                    $proceso,
                    'revision_auto',
                    "📋 Revisar autos ({$dia}): {$proceso->radicado_interno}",
                    "Revisión programada de autos en el juzgado para {$proceso->radicado_interno}. Juzgado: {$proceso->juzgado}.",
                    $dependiente?->user_id,
                    'media'
                );
                $count++;
            }
        }

        return $count;
    }

    /**
     * Generar alertas de firmas pendientes en FO-SG-025
     * CORREGIDO: columnas reales = firmado_asistente_at, firmado_sustanciador_at, firmado_gerente_at
     */
    public static function verificarFirmasPendientes(): int
    {
        $count = 0;
        $procesos = Proceso::activos()
            ->whereHas('ordenGestion', function ($q) {
                $q->where(function ($sub) {
                    $sub->whereNull('firmado_asistente_at')
                        ->orWhereNull('firmado_sustanciador_at')
                        ->orWhereNull('firmado_gerente_at');
                });
            })
            ->with(['ordenGestion', 'asignacionesActivas'])
            ->get();

        foreach ($procesos as $proceso) {
            $tieneAlerta = $proceso->alertas()
                ->where('tipo', 'firma_pendiente')
                ->noResueltas()
                ->whereDate('created_at', '>=', now()->subDays(2))
                ->exists();

            if (!$tieneAlerta) {
                $orden = $proceso->ordenGestion;
                $pendientes = 3 - $orden->firmas_count;

                self::crearAlerta(
                    $proceso,
                    'firma_pendiente',
                    "FO-SG-025 pendiente: {$proceso->radicado_interno} ({$pendientes} firma(s))",
                    "La Orden de Gestión del proceso {$proceso->radicado_interno} tiene {$pendientes} firma(s) pendiente(s).",
                    null,
                    'media'
                );
                $count++;
            }
        }

        return $count;
    }

    /**
     * Obtener resumen de alertas para un usuario
     */
    /**
     * Generar alertas para acuerdos con cuotas vencidas.
     * Crea UNA alerta resumen por proceso (no una por cuota).
     * Idempotente: si ya hay alerta cuota_vencida sin resolver para el proceso, no duplica.
     */
    public static function verificarCuotasVencidas(): int
    {
        $count = 0;
        $hoy = Carbon::now();

        $acuerdos = \App\Models\AcuerdoPago::with(['cuotas', 'proceso.asignacionesActivas'])
            ->whereHas('cuotas', function ($q) use ($hoy) {
                $q->where('fecha_vencimiento', '<', $hoy->toDateString())
                  ->whereIn('estado', ['pendiente', 'parcial']);
            })
            ->whereIn('estado', ['vigente', 'incumplido'])
            ->get();

        foreach ($acuerdos as $acuerdo) {
            if (!$acuerdo->proceso) {
                continue;
            }
            $proceso = $acuerdo->proceso;

            // Idempotencia
            $tieneAlerta = $proceso->alertas()
                ->where('tipo', 'cuota_vencida')
                ->noResueltas()
                ->exists();
            if ($tieneAlerta) {
                continue;
            }

            // Cuotas vencidas de este acuerdo
            $cuotasVencidas = $acuerdo->cuotas
                ->filter(function ($c) use ($hoy) {
                    return $c->fecha_vencimiento
                        && $c->fecha_vencimiento->lt($hoy)
                        && in_array($c->estado, ['pendiente', 'parcial']);
                });

            $cantidad = $cuotasVencidas->count();
            if ($cantidad === 0) {
                continue;
            }

            $masAntigua = $cuotasVencidas->sortBy('fecha_vencimiento')->first();
            $diasVencido = (int) abs($hoy->diffInDays($masAntigua->fecha_vencimiento, false));

            $prioridad = match (true) {
                $diasVencido > 30 => 'critica',
                $diasVencido > 15 => 'alta',
                default => 'media',
            };

            $asignado = $proceso->asignacionesActivas->first();
            $monto = number_format($acuerdo->monto_acordado, 0, ',', '.');
            $fechaCuota = $masAntigua->fecha_vencimiento->format('d/m/Y');

            $titulo  = "Cuotas vencidas: {$proceso->radicado_interno} ({$cantidad} pdte, +{$diasVencido}d)";
            $mensaje = "El acuerdo de pago tiene {$cantidad} cuota(s) vencida(s). "
                     . "La más antigua venció el {$fechaCuota} ({$diasVencido} día(s) atrás). "
                     . "Monto acordado: \${$monto}.";

            self::crearAlerta(
                $proceso,
                'cuota_vencida',
                $titulo,
                $mensaje,
                $asignado?->user_id,
                $prioridad,
                $masAntigua->fecha_vencimiento->toDateString()
            );
            $count++;
        }

        return $count;
    }

    public static function resumenUsuario(int $userId): array
    {
        $base = Alerta::deUsuario($userId)->pendientes();

        return [
            'total' => (clone $base)->count(),
            'criticas' => (clone $base)->criticas()->count(),
            'no_leidas' => (clone $base)->noLeidas()->count(),
        ];
    }
}
