<?php

use Illuminate\Database\Migrations\Migration;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\PermissionRegistrar;

/**
 * Fuera los veinte permisos que no gatean nada.
 *
 * **El hallazgo.** El reparto tenía **27 permisos que ninguna pantalla, ruta ni
 * `authorize()` comprueba**. Se vio comparando los 126 que creaba el seeder con todas las
 * cadenas `admin.*` y `api.*` que aparecen en `app/`, `routes/` y las vistas.
 *
 * **Lo que NO era**, y era lo primero que había que descartar: **ninguno es una puerta que
 * falte**. Se comprobó uno a uno que las acciones destructivas que existen están todas
 * gateadas —el borrado de un contrato de soporte usa
 * `admin.environments.supports.destroy`— y que **la API no comprueba permisos en absoluto**:
 * autentica por token de licencia, así que los tres `api.*.store` nunca se han mirado. O sea
 * que no había ningún agujero: había promesas vacías.
 *
 * ## Por qué molestan
 *
 * Quien reparte permisos en un rol ve veintisiete casillas que no hacen nada, y **no puede
 * distinguir «esto es una función que aún no está» de «esto es basura»**. Marcarlas da una
 * sensación de haber concedido algo. Y al revés: quien lee el código no sabe si falta una
 * pantalla o sobra una línea.
 *
 * ## Los tres motivos por los que se borran estos veinte
 *
 * | Motivo | Cuáles |
 * |---|---|
 * | **Duplicado con otro nombre del que sí se usa** | `admin.types.*` (el vivo es `admin.configurations.environments-types.*`), `admin.scss.{create,edit,show}` (los vivos llevan `.file.` o `.version.`), `admin.js.{create,edit,show}`, `admin.scss-cdn.{edit,show}` (los vivos llevan `.bundle.`) |
 * | **De una pantalla que ya no existe** | `admin.configurations.products.{create,edit}` — la gemela de Productos se eliminó y sus URLs redirigen a `/products`, que usa `admin.products.*` |
 * | **De algo que nunca se comprobó** | `api.datas.store`, `api.plugins.store`, `api.updates.store` (la API va por token), `admin.types.list` (un servicio web que no existe), `admin.notices.index` (la pantalla de Avisos usa `admin.api-logs.index` a propósito), `admin.supports.destroy` (el catálogo de tipos de soporte no borra) |
 *
 * > **Nota de después, el mismo día.** `admin.supports.destroy` está en la lista de abajo
 * > y **ha vuelto** en `2026_09_08_170000_add_support_destroy_permission`: el usuario pidió
 * > poder borrar un tipo de soporte del catálogo, así que se hizo la pantalla y el permiso
 * > entró con ella. No es una contradicción, es el orden correcto — y esta migración
 * > sigue siendo válida tal cual, porque cuando se escribió el permiso no gateaba nada.
 * > Las dos migraciones se aplican en orden y el resultado es el que se quiere.
 *
 * **Los otros siete se quedan** y ahora están declarados en
 * `RoleSeeder::PERMISOS_DE_ROADMAP`, con el motivo de cada uno. La pantalla de Permisos los
 * marca «sin pantalla todavía» y hay un test que **falla si aparece un permiso nuevo que no
 * gatea nada y no está en esa lista**. Eso es lo que impide que la lista vuelva a crecer sin
 * que nadie se entere, que es el problema de fondo.
 *
 * ## Qué pasa al aplicarla
 *
 * **Nadie pierde acceso a nada.** Borrar un permiso quita también su asignación a los roles
 * —Spatie lo hace en cascada—, pero como ninguna pantalla lo comprueba, ninguna pantalla
 * cambia de comportamiento. Es la definición de lo que se está borrando.
 */
return new class extends Migration
{
    /**
     * @var list<string>
     */
    private const MUERTOS = [
        // Duplicados de `admin.configurations.environments-types.*`.
        'admin.types.index',
        'admin.types.create',
        'admin.types.edit',
        'admin.types.destroy',
        // Un servicio web de tipos que no existe.
        'admin.types.list',

        // Los vivos llevan `.file.` o `.version.` en medio.
        'admin.scss.create',
        'admin.scss.edit',
        'admin.scss.show',
        'admin.js.create',
        'admin.js.edit',
        'admin.js.show',

        // Los vivos son `admin.scss-cdn.bundle.edit` y `.bundle.show`.
        'admin.scss-cdn.edit',
        'admin.scss-cdn.show',

        // El catálogo de tipos de soporte no tiene borrado; el de contratos usa
        // `admin.environments.supports.destroy`.
        'admin.supports.destroy',

        // La pantalla gemela de Productos se eliminó; sus URLs redirigen a `/products`.
        'admin.configurations.products.create',
        'admin.configurations.products.edit',

        // La pantalla de Avisos va con `admin.api-logs.index`, a propósito: es la misma
        // sección de Monitorización.
        'admin.notices.index',

        // La API autentica por token de licencia y **no comprueba permisos**.
        'api.datas.store',
        'api.plugins.store',
        'api.updates.store',
    ];

    public function up(): void
    {
        $borrados = Permission::whereIn('name', self::MUERTOS)->get();

        foreach ($borrados as $permiso) {
            // El `delete()` de Spatie ya quita las filas de `role_has_permissions` y
            // `model_has_permissions` por la clave ajena en cascada.
            $permiso->delete();
        }

        // El caché de permisos de Spatie hay que tirarlo o los roles siguen anunciando lo
        // que ya no existe hasta que caduque solo.
        app(PermissionRegistrar::class)->forgetCachedPermissions();
    }

    /**
     * **No se restauran.**
     *
     * Deshacer esta migración no debería volver a crear veinte permisos que no gatean nada:
     * eso es restaurar el problema, no el estado. Si alguno hiciera falta de verdad, lo que
     * toca es añadirlo **con su pantalla** —y entonces lo crea el seeder como cualquier
     * otro—, o declararlo en `PERMISOS_DE_ROADMAP` si es una intención.
     *
     * Es el mismo criterio que en las migraciones de limpieza de esta release: el `down()`
     * de un borrado deliberado no resucita basura.
     */
    public function down(): void
    {
        // A propósito, nada.
    }
};
