<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

/**
 * Registro de avisos automáticos enviados: qué se avisó, de qué, a quién y cuándo.
 *
 * **Para qué sirve exactamente**: para no repetir un aviso. Sin esto, una tarea diaria
 * que avise de una licencia a punto de caducar manda el mismo correo todos los días
 * hasta que caduque, y a los tres días nadie lo lee.
 *
 * **Reemplaza la tabla `notices` que venía del Manager antiguo**, y conviene explicar
 * por qué se sustituye en vez de extenderse. La que había era
 * `(environment_id, model, method, type, request, response, response_id, status)`, con
 * clave única `(environment_id, method, type)`: estaba atada a un **entorno**, y una
 * licencia no es un entorno. Encajarla a la fuerza dejaba `environment_id` nulo en la
 * mitad de las filas y una clave única que no agrupa lo que hay que agrupar.
 *
 * Se puede reemplazar sin perder nada, comprobado antes de hacerlo: **0 filas**, ningún
 * modelo de Eloquent, ninguna pantalla y ninguna referencia en el código. Solo existía
 * el permiso `admin.notices.index` reservado en el seeder. Ver
 * [`manager-anterior.md`] y `pending-modules.md`.
 *
 * **La clave está en `reference`.** Guarda el dato que motivó el aviso —para una
 * licencia, su fecha de fin—. Si la licencia se renueva, la fecha cambia y los avisos
 * viejos dejan de casar: el ciclo empieza de cero **sin ningún `reset()` explícito** ni
 * un observador del modelo que alguien pueda olvidar. Es lo que el Manager antiguo
 * resolvía llamando a `Notice::reset()` a mano desde cinco sitios distintos.
 *
 * **Genérica y no `licence_notices`** porque hacen falta los mismos avisos para
 * soportes que caducan y entornos que dejan de sincronizar, y todos comparten el
 * problema de no repetirse. Ver `alerts-and-settings.md`.
 */
return new class extends Migration
{
    public function up(): void
    {
        // Determinista en los dos escenarios: instalación nueva (donde la migración de
        // 2025 ya la ha creado) e instalación existente.
        Schema::dropIfExists('notices');

        Schema::create('notices', function (Blueprint $table) {
            $table->id();

            // De qué se avisa. No se usa una relación polimórfica de Eloquent a
            // propósito: aquí interesa que la fila sobreviva al borrado del sujeto —el
            // histórico de "se avisó de esto" no debe desaparecer con él—.
            $table->string('subject_type', 40);
            $table->unsignedBigInteger('subject_id');

            // Qué aviso es (ej. `licence:expiring`, `licence:expired`).
            $table->string('kind', 40);

            // Umbral que lo disparó, en días. 0 = ya ha pasado la fecha.
            $table->unsignedSmallInteger('threshold')->default(0);

            // El dato que motivó el aviso. Ver la explicación de arriba.
            $table->string('reference', 100)->default('');

            $table->dateTime('sent_at')->nullable();
            $table->string('sent_to', 500)->nullable();
            $table->text('error')->nullable();
            $table->json('payload')->nullable();

            $table->timestamps();

            // Un aviso por sujeto, tipo, umbral y referencia. Es lo que impide repetir.
            $table->unique(
                ['subject_type', 'subject_id', 'kind', 'threshold', 'reference'],
                'notices_unique'
            );
            $table->index(['subject_type', 'subject_id']);
            $table->index('sent_at');
        });
    }

    /**
     * Vuelve a la tabla del Manager antiguo, para que revertir deje la base como estaba.
     */
    public function down(): void
    {
        Schema::dropIfExists('notices');

        Schema::create('notices', function (Blueprint $table) {
            $table->id();
            $table->foreignId('environment_id')
                ->constrained('environments')
                ->cascadeOnDelete()
                ->cascadeOnUpdate();
            $table->string('model');
            $table->string('method');
            $table->string('type');
            $table->text('request')->nullable();
            $table->text('response')->nullable();
            $table->string('response_id')->nullable();
            $table->integer('status')->default(1);
            $table->timestamps();
            $table->softDeletes();
            $table->unique(['environment_id', 'method', 'type']);
        });
    }
};
