<?php

use App\Models\System\Config;
use App\Services\System\Settings;
use Illuminate\Database\Migrations\Migration;

/**
 * Las dos retenciones del registro de cortes, con un valor que sí borra.
 *
 * **El problema que resuelve.** `blocks:retention_days` y `rate_events:retention_days`
 * estaban declaradas en el catálogo pero **no las sembraba ninguna migración**, así que ni
 * siquiera existían como fila: `get(clave, 0)` devolvía 0, y 0 significa «no borrar nada».
 * La tarea `api-blocks:purge --retention` se ejecutaba cada noche a las 03:45 y no borraba
 * nunca nada. Las dos tablas solo crecían, y la pantalla de Tráfico iba acumulando ruido sin
 * final.
 *
 * **Por qué aquí sí se siembra con un valor y no con 0**, al contrario que la retención del
 * log de peticiones: porque lo que se borra no es auditoría.
 *
 * - `api_blocks` solo pierde los episodios **cerrados** —un episodio pendiente no caduca
 *   nunca, por mucha antigüedad que tenga: es algo que nadie ha mirado—. Un episodio cerrado
 *   hace medio año es historia que ya se atendió.
 * - `api_rate_events` es telemetría de un minuto concreto. A los treinta días no responde
 *   ninguna pregunta, y es la tabla que más filas mete por unidad de tráfico.
 *
 * El log de peticiones (`logs:retention_days`) **se queda en 0 a propósito**: ese sí es el
 * rastro de auditoría de la API, y cuánto se conserva es una decisión de negocio que tiene
 * que tomar alguien, no una migración.
 *
 * Si la fila ya existe se respeta su valor: volver a pasar la migración no devuelve un ajuste
 * tocado a su valor de fábrica.
 */
return new class extends Migration
{
    /**
     * Los días de cada una y por qué ese número.
     *
     * @return array<string, array{nombre: string, desc: string, valor: string}>
     */
    private function ajustes(): array
    {
        return [
            Settings::CORTES_RETENCION => [
                'nombre' => 'Cortes → Retención de los episodios revisados (días)',
                'desc' => 'Cuántos días se conservan los episodios de corte ya revisados. Los '
                    . 'pendientes no caducan nunca: un episodio sin revisar es algo que nadie ha '
                    . 'mirado todavía. 0 = no se borra nada.',
                // Medio año: un episodio cerrado más antiguo que eso ya no se consulta para
                // decidir nada, y sigue siendo tiempo de sobra para mirar atrás en una
                // revisión trimestral.
                'valor' => '180',
            ],
            Settings::VENTANAS_RETENCION => [
                'nombre' => 'Cortes → Retención de las ventanas del limitador (días)',
                'desc' => 'Cuántos días se conservan las ventanas de un minuto que cruzaron el '
                    . 'margen de aviso. Es telemetría, no auditoría. 0 = no se borra nada.',
                // Un mes: es el plazo de la pantalla que las usa —«quién va a acabar cortado»
                // mira 24 h— y la tabla que más filas mete por unidad de tráfico.
                'valor' => '30',
            ],
        ];
    }

    public function up(): void
    {
        foreach ($this->ajustes() as $clave => $ajuste) {
            Config::updateOrCreate(
                [
                    'model' => Settings::AMBITO,
                    'model_id' => '0',
                    'shortname' => $clave,
                ],
                [
                    'name' => $ajuste['nombre'],
                    'type' => 'text',
                    'mode' => 'wr',
                    'permission' => 'admin.configs.edit',
                    'desc' => $ajuste['desc'],
                    'value' => Config::where('model', Settings::AMBITO)
                        ->where('shortname', $clave)
                        ->value('value') ?? $ajuste['valor'],
                ]
            );
        }

        app(Settings::class)->olvidar();
    }

    public function down(): void
    {
        Config::where('model', Settings::AMBITO)
            ->whereIn('shortname', array_keys($this->ajustes()))
            ->delete();

        app(Settings::class)->olvidar();
    }
};
