<?php

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

/**
 * `logs.entity_id` era un entero, y hay referencias que no son números.
 *
 * **El fallo, y cómo se encontró.** Al escribir la migración de limpieza de ajustes pasé
 * `alerts:support:email` como `entity_id` y el log no se escribió. Probándolo a mano:
 *
 * ```
 * SQLSTATE[HY000]: General error: 1366 Incorrect integer value:
 * 'x' for column 'entity_id' at row 1
 * ```
 *
 * La columna es `int`, y `Log::db()` declara `?string $id`. Cualquier referencia que no
 * sea numérica **hace saltar una excepción en MySQL/MariaDB**.
 *
 * **Y ya había dos llamadas así, una de hoy mismo:**
 *
 * - `Monitoring\IpBlockModal` registra el bloqueo manual con `entity_id = $ip`
 *   —`'203.0.113.5'`—. O sea que **bloquear una IP a mano habría petado en producción**.
 * - La migración de ajustes, con la clave del ajuste.
 *
 * **Por qué los tests no lo cogieron.** Corren en **sqlite**, que guarda `'203.0.113.5'`
 * en una columna `integer` sin protestar —tipado dinámico—. `test_un_administrador_
 * bloquea_una_ip_a_mano` comprueba `assertDatabaseHas('logs', ['code' => '16011'])` y
 * pasa. En MariaDB, en modo estricto, la misma línea lanza. Es exactamente la trampa de
 * MGR-050: **la suite es más permisiva que producción**, y eso es peor que ser más
 * estricta, porque no avisa.
 *
 * **Por qué se cambia la columna y no las llamadas.** `entity_id` es «a qué se refiere
 * esta entrada», y para un bloqueo por IP **la referencia es la IP**: forzar un id
 * numérico obligaría a inventar uno o a perder el dato. La firma de `Log::db()` ya decía
 * `string`; era la columna la que no acompañaba.
 *
 * ---
 *
 * **El número del archivo importa: `185000` va antes de `190000` a propósito.**
 *
 * Esta migración se escribió porque `clean_dead_settings` —la `190000`— registra en el
 * log el rescate del destinatario de soporte usando la clave del ajuste como
 * `entity_id`. Estaba numerada `200000`, o sea **después** de la que la necesita, y en
 * pre el despliegue murió exactamente ahí:
 *
 * ```
 * SQLSTATE[22007]: Incorrect integer value: 'alerts:support:email'
 *   for column laravel.logs.entity_id at row 1
 * ```
 *
 * Y no murió limpiamente: MariaDB no envuelve las migraciones en transacción, así que
 * el rescate del correo **ya se había guardado** y el borrado de los cinco ajustes
 * muertos no llegó a ejecutarse. Un despliegue a medias en el peor sitio posible.
 *
 * Los tests no lo cogieron por la misma razón que el fallo original —sqlite acepta un
 * texto en una columna `integer`— y **tampoco lo habrían cogido con la columna ya
 * arreglada**: el orden entre migraciones no se prueba, porque `RefreshDatabase` las
 * corre todas y cualquier orden acaba en el mismo esquema. Lo único que protege esto es
 * el número del archivo. No lo cambies sin mirar quién escribe en `logs.entity_id`.
 *
 * `Log::enlace()` sigue funcionando: hace `(int) $this->entity_id` solo para las entidades
 * que tienen pantalla —`Client`, `Environment`, `LicenseToken`—, y esas siguen guardando
 * ids numéricos.
 */
return new class extends Migration
{
    public function up(): void
    {
        Schema::table('logs', function (Blueprint $table) {
            // 191 y no 255: si algún día hay que indexar esta columna, cabe en un índice
            // con `utf8mb4` sin tocar nada más.
            $table->string('entity_id', 191)->nullable()->change();
        });
    }

    public function down(): void
    {
        Schema::table('logs', function (Blueprint $table) {
            // Al volver a `int`, las referencias no numéricas se perderían. No se
            // convierten a null a propósito: que falle y se vea, en lugar de borrar
            // entradas de auditoría en silencio.
            $table->integer('entity_id')->nullable()->change();
        });
    }
};
