<?php

namespace Database\Seeders;

use App\Models\Auth\User;
use App\Models\System\Config;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

class RoleSeeder extends Seeder
{
    /**
     * Helper method to create permission and assign to roles
     */
    /**
     * Permisos que existen **a propósito y todavía no tienen pantalla**.
     *
     * **Por qué hace falta declararlos.** El reparto tenía **27 permisos que no gateaban
     * nada**: unos eran duplicados de otro con nombre distinto —`admin.types.edit` frente a
     * `admin.configurations.environments-types.edit`—, otros restos del Manager anterior, y
     * otros intención de verdad. Y desde fuera **no había forma de distinguirlos**: quien
     * reparte permisos en un rol veía veintisiete casillas que no hacen nada, y quien lee el
     * código no podía saber si faltaba una pantalla o sobraba una línea.
     *
     * Los duplicados y los restos se borraron el 2026-09-08. Estos siete se quedan porque
     * **nombran algo que se quiere**, y estar aquí es lo que los distingue de un olvido: 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 esta lista**.
     *
     * Es el mismo problema que llevaba seis apariciones en este release —MGR-039, MGR-045,
     * MGR-060, MGR-062, MGR-070 y PRODSECU-198—: *funcionalidad que parecía existir y no
     * tenía puerta*. La diferencia es que ahora la lista no puede crecer en silencio.
     *
     * @var array<string, string>  permiso => por qué sigue aquí
     */
    public const PERMISOS_DE_ROADMAP = [
        // El módulo de informes, que no existe todavía. Ver `pending-modules.md`.
        'admin.reports.environment' => 'Informes por entorno: el módulo está sin hacer',
        'admin.updates.environment' => 'Actualizaciones del core por entorno: sin pantalla',

        // Borrar un cliente o un entorno. **La decisión tomada hasta hoy es la baja
        // lógica** —con su impacto, su motivo y su rastro—, no el borrado; estos permisos
        // se quedan porque el borrado duro se acaba pidiendo, y PRODSECU-198 ya enseñó que
        // cuando se pide hay que tener dónde colgarlo.
        'admin.clients.destroy' => 'Borrar un cliente: hoy solo hay baja lógica',
        'admin.environments.destroy' => 'Borrar un entorno: hoy solo hay apagado',

        // Un contrato de soporte no tiene estado activo/inactivo. Si algún día lo tiene,
        // estos son sus permisos.
        'admin.environments.supports.activate' => 'Activar un contrato de soporte: no hay estado',
        'admin.environments.supports.disactivate' => 'Desactivar un contrato de soporte: no hay estado',

        // **El token de servicios web del Moodle del cliente no se enseña nunca**, a
        // propósito: el formulario es de solo escritura porque es una credencial de un
        // tercero (MGR-038). Este permiso se queda porque es la exclusión que documenta el
        // rol Support —lo único que un Soporte no debe poder ver— y borrarlo dejaría esa
        // explicación sin referencia.
        'admin.tokens.index' => 'Ver el token de servicios web: hoy no se muestra nunca',
    ];

    /**
     * Los permisos del rol Support: **la definición del rol, en un solo sitio.**
     *
     * Está aquí como constante y no repartida por las 37 llamadas a
     * `createPermissionAndAssign()` porque la lista la lee también la migración
     * `2026_09_03_180000_grant_support_role_its_permissions`, que es la que la aplica en
     * una base que ya tiene datos —el seeder completo no se vuelve a pasar—. Con la
     * lista en dos sitios, se desincronizan.
     *
     * **El criterio: Soporte lee todo y toca lo que no rompe nada.** Puede responder
     * «este cliente dice que no le llega el contenido» —encontrar el sitio, ver su
     * licencia, ver qué hay publicado, mirar el log— y **sincronizar**, que es la acción
     * de diagnóstico y no cambia datos comerciales.
     *
     * Lo que NO tiene, a propósito: crear/editar/borrar nada, `admin.configs.edit`
     * (bloquear IPs), `admin.tokens.index` (la credencial del Moodle del cliente,
     * MGR-038), `admin.api-logs.destroy`, y usuarios/roles/permisos.
     *
     * @var array<int, string>
     */
    public const PERMISOS_DE_SOPORTE = [
        // «¿Hay algo que atender?» — la pantalla de entrada.
        'admin.dashboard.index',

        // «¿De quién es este dominio y qué tiene contratado?»
        'admin.clients.index',
        'admin.license-tokens.index',
        'admin.license-tokens.show',

        // «¿Qué le pasa a este sitio?» — la pantalla que más se abre, más el
        // diagnóstico: sincronizar, ver sus plugins, sus datos y sus
        // actualizaciones pendientes.
        'admin.environments.index',
        'admin.environments.refresh',
        'admin.environments.supports.index',
        'admin.plugins.environment',
        'admin.datas.environment',
        'admin.updates.environment',
        'admin.reports.environment',
        'admin.types.index',
        'admin.supports.index',

        // «¿Qué versión hay publicada de esto?» — todo en lectura. Es la respuesta
        // cuando un cliente dice que no le llega algo.
        'admin.products.index',
        'admin.products.show',
        'admin.setups.index',
        'admin.setups.show',
        'admin.features.index',
        'admin.features.version.show',
        'admin.scss.index',
        'admin.scss.show',
        'admin.scss.file.show',
        'admin.scss.version.show',
        'admin.js.index',
        'admin.js.show',
        'admin.js.file.show',
        'admin.js.version.show',
        'admin.scss-cdn.index',
        'admin.scss-cdn.show',
        'admin.scss-cdn.bundle.show',
        'admin.tutorials.index',
        'admin.tutorials.version.show',
        'admin.resources.index',
        'admin.resources.version.show',

        // «¿Qué pasó?» — el log de peticiones, el del panel y los avisos enviados.
        // Los tres son lectura, y los tres responden preguntas que llegan a Soporte.
        'admin.api-logs.index',
        'admin.logs.index',
        'admin.notices.index',
    ];

    private function createPermissionAndAssign(string $name, string $model, string $description, array $roles): void
    {
        $perm = Permission::firstOrCreate(
            ['name' => $name],
            ['model' => $model, 'description' => $description, 'guard_name' => 'web']
        );

        foreach ($roles as $role) {
            if ($role && !$role->hasPermissionTo($perm)) {
                $role->givePermissionTo($perm);
            }
        }
    }

    public function run(): void
    {
        /**
         * USUARIOS INICIALES
         *
         * **Salen del entorno y solo del entorno**, a través de `config/seed.php`. Antes
         * había tres con el correo y el nombre de personas concretas escritos aquí
         * (`amanzano@tresipunt.com`, `sergio@tresipunt.com`), así que cualquier
         * instalación sembrada en cualquier sitio creaba cuentas a nombre de compañeros
         * que no tenían nada que ver con ella.
         *
         * **Si no hay correo, ese usuario no se crea.** No se adivina ninguno. Los roles
         * y los permisos se siembran igual, que es el trabajo de fondo de este seeder.
         *
         * La contraseña sí puede faltar: si hay correo pero no contraseña se genera una
         * aleatoria fuerte y se muestra UNA VEZ por consola, para que una instalación
         * nueva sea usable sin que ninguna contraseña viaje en git.
         *
         * Se usa firstOrCreate, así que a quien ya existe no se le toca la contraseña:
         * volver a sembrar no deja a nadie fuera.
         *
         * Ver known-issues MGR-026.
         */
        $creados = [];
        $porRol = [];

        foreach ((array) config('seed.usuarios', []) as $datos) {
            $email = trim((string) ($datos['email'] ?? ''));

            // Sin correo no hay usuario.
            if ($email === '') {
                continue;
            }

            $escrita = (string) ($datos['password'] ?? '');
            $generada = $escrita === '' ? Str::password(20) : null;

            $usuario = User::firstOrCreate(
                ['email' => $email],
                [
                    // Sin nombre se usa la parte local del correo: es lo único que se
                    // sabe de esa persona, y la columna no admite nulos.
                    'name' => trim((string) ($datos['name'] ?? '')) ?: Str::before($email, '@'),
                    'password' => bcrypt($generada ?? $escrita),
                ]
            );

            // Solo se anuncia la contraseña si el usuario se acaba de crear Y se generó
            // aquí: si venía del entorno, quien la puso ya la conoce.
            if ($usuario->wasRecentlyCreated && $generada !== null) {
                $creados[$email] = $generada;
            }

            $rol = trim((string) ($datos['rol'] ?? ''));

            if ($rol !== '') {
                $porRol[$rol][] = $usuario;
            }
        }

        if (!empty($creados)) {
            $this->command?->newLine();
            $this->command?->warn('Contraseñas generadas para los usuarios nuevos. Apúntalas: no se volverán a mostrar.');

            foreach ($creados as $email => $password) {
                $this->command?->line("  {$email}  →  {$password}");
            }

            $this->command?->newLine();
            $this->command?->line('Para fijarlas tú, define SEED_ADMIN_PASSWORD, SEED_ADMIN2_PASSWORD y SEED_WS_PASSWORD en el .env antes de sembrar.');
            $this->command?->newLine();
        }

        if (empty($porRol)) {
            /**
             * **Aviso, no error.** Los roles y los permisos quedan sembrados, y volver a
             * sembrar con las variables puestas es seguro. Pero sin ningún usuario nadie
             * puede entrar, y la aplicación no permite crear el primero sin haber
             * entrado: si se dejara pasar en silencio, la instalación quedaría cerrada
             * por dentro y nadie sabría por qué.
             */
            $this->command?->newLine();
            $this->command?->warn('No se ha creado ningún usuario: no hay ningún SEED_*_EMAIL definido en el .env.');
            $this->command?->line('Los roles y los permisos sí están sembrados. Define al menos SEED_ADMIN_EMAIL (y su SEED_ADMIN_PASSWORD, o se generará una) y vuelve a sembrar:');
            $this->command?->line('  php artisan db:seed --class=RoleSeeder');
            $this->command?->line('En producción, si la configuración está en caché, primero: php artisan config:clear');
            $this->command?->newLine();
        }

        /**
         * ROLES        /**
         * ROLES
         */
        $role_admin = Role::firstOrCreate(
            ['name' => 'Admin'],
            [
                'fullname' => 'Administrador',
                'description' => 'Administrador de la aplicación',
            ]
        );

        $role_system = Role::firstOrCreate(
            ['name' => 'System'],
            [
                'fullname' => 'Sistemas',
                'description' => 'Departamento de Sistemas',
            ]
        );

        $role_support = Role::firstOrCreate(
            ['name' => 'Support'],
            [
                'fullname' => 'Soporte',
                'description' => 'Departamento de Soporte',
            ]
        );

        $role_manager = Role::firstOrCreate(
            ['name' => 'Manager'],
            [
                'fullname' => 'Jefe de Proyecto',
                'description' => 'Jefe de Proyecto',
            ]
        );

        $role_developer = Role::firstOrCreate(
            ['name' => 'Developer'],
            [
                'fullname' => 'Desarrollador',
                'description' => 'Departamento de Desarrollo',
            ]
        );

        $role_ws = Role::firstOrCreate(
            ['name' => 'WebService'],
            [
                'fullname' => 'Servicios Web',
                'description' => 'Autenticación via API para servicios desde Moodle',
            ]
        );

        /**
         * PERMISOS
         */

        // Dashboard
        $this->createPermissionAndAssign('admin.dashboard.index', 'dashboard', 'Dashboard: Ver panel principal', [$role_admin]);

        // Permissions
        $this->createPermissionAndAssign('admin.users.index', 'users', 'Usuarios: Ver listado', [$role_admin]);
        $this->createPermissionAndAssign('admin.users.create', 'users', 'Usuarios: Crear', [$role_admin]);
        $this->createPermissionAndAssign('admin.users.edit', 'users', 'Usuarios: Editar', [$role_admin]);
        $this->createPermissionAndAssign('admin.users.destroy', 'users', 'Usuarios: Eliminar', [$role_admin]);

        // Roles.
        $this->createPermissionAndAssign('admin.roles.index', 'roles', 'Roles: Ver Listado', [$role_admin]);
        $this->createPermissionAndAssign('admin.roles.create', 'roles', 'Roles: Crear', [$role_admin]);
        $this->createPermissionAndAssign('admin.roles.edit', 'roles', 'Roles: Editar', [$role_admin]);
        $this->createPermissionAndAssign('admin.roles.destroy', 'roles', 'Roles: Eliminar', [$role_admin]);

        // Permisos.
        $this->createPermissionAndAssign('admin.permissions.index', 'permissions', 'Permisos: Ver listado', [$role_admin]);
        $this->createPermissionAndAssign('admin.permissions.create', 'permissions', 'Permisos: Crear', [$role_admin]);
        $this->createPermissionAndAssign('admin.permissions.edit', 'permissions', 'Permisos: Editar', [$role_admin]);
        $this->createPermissionAndAssign('admin.permissions.destroy', 'permissions', 'Permisos: Eliminar', [$role_admin]);

        // Entornos
        $this->createPermissionAndAssign('admin.environments.index', 'environments', 'Entornos: Ver listado', [$role_admin, $role_ws]);
        $this->createPermissionAndAssign('admin.environments.create', 'environments', 'Entornos: Crear', [$role_admin]);
        $this->createPermissionAndAssign('admin.environments.edit', 'environments', 'Entornos: Editar', [$role_admin]);
        $this->createPermissionAndAssign('admin.environments.destroy', 'environments', 'Entornos: Eliminar', [$role_admin]);
        $this->createPermissionAndAssign('admin.environments.refresh', 'environments', 'Entornos: Refrescar Plugin Moodle', [$role_admin]);

        // Clientes
        $this->createPermissionAndAssign('admin.clients.index', 'clients', 'Clientes: Ver listado', [$role_admin]);
        $this->createPermissionAndAssign('admin.clients.create', 'clients', 'Clientes: Crear', [$role_admin]);
        $this->createPermissionAndAssign('admin.clients.edit', 'clients', 'Clientes: Editar', [$role_admin]);
        $this->createPermissionAndAssign('admin.clients.destroy', 'clients', 'Clientes: Eliminar', [$role_admin]);

        // Tipos de Soporte
        $this->createPermissionAndAssign('admin.supports.index', 'supports', 'Soporte: Ver listado', [$role_admin]);
        $this->createPermissionAndAssign('admin.supports.create', 'supports', 'Soporte: Crear', [$role_admin]);
        $this->createPermissionAndAssign('admin.supports.edit', 'supports', 'Soporte: Editar', [$role_admin]);
        // Borrar un tipo del catálogo: solo Admin, igual que en los tipos de entorno.
        $this->createPermissionAndAssign('admin.supports.destroy', 'supports', 'Soporte: Borrar tipo del catálogo', [$role_admin]);

        // Soportes del Entorno
        $this->createPermissionAndAssign('admin.environments.supports.index', 'environment_support', 'Soporte Entorno: Ver', [$role_admin]);
        $this->createPermissionAndAssign('admin.environments.supports.create', 'environment_support', 'Soporte Entorno: Crear', [$role_admin]);
        $this->createPermissionAndAssign('admin.environments.supports.edit', 'environment_support', 'Soporte Entorno: Editar', [$role_admin]);
        $this->createPermissionAndAssign('admin.environments.supports.destroy', 'environment_support', 'Soporte Entorno: Borrar', [$role_admin]);
        $this->createPermissionAndAssign('admin.environments.supports.activate', 'environment_support', 'Soporte Entorno: Activar', [$role_admin]);
        $this->createPermissionAndAssign('admin.environments.supports.disactivate', 'environment_support', 'Soporte Entorno: Desactivar', [$role_admin]);


        // Tipos de Entornos

        // Data.
        $this->createPermissionAndAssign('admin.datas.environment', 'datas', 'Datos: Ver datos de Entorno', [$role_admin]);

        // Plugins
        $this->createPermissionAndAssign('admin.plugins.environment', 'plugins', 'Plugins: Ver datos de los Plugins de Entorno', [$role_admin]);

        // Updates
        $this->createPermissionAndAssign('admin.updates.environment', 'updates', 'Actualizaciones: Ver actualizaciones del core disponibles en el entorno', [$role_admin]);

        // Reports
        $this->createPermissionAndAssign('admin.reports.environment', 'reports', 'Reports: Ver reportes gráficos', [$role_admin]);

        // Configs
        $this->createPermissionAndAssign('admin.configs.index', 'configs', 'Configs: Ver parámetros de configuración', [$role_admin]);
        $this->createPermissionAndAssign('admin.configs.edit', 'configs', 'Configs: Editar parámetros de configuración', [$role_admin]);

        // Tokens
        $this->createPermissionAndAssign('admin.tokens.index', 'tokens', 'Tokens: Ver token WS', [$role_admin]);

        // Logs (visor de API Logs en /api-logs)
        // El permiso que comprueban la ruta, el componente Livewire y el menú es
        // admin.api-logs.index (no admin.logs.index, que quedaba huérfano). Se
        // otorga a Admin, Support y Manager, alineado con la migración 2026_03_05.
        $this->createPermissionAndAssign('admin.api-logs.index', 'api_logs', 'API Logs: Ver listado de peticiones', [$role_admin, $role_support, $role_manager]);
        // Borrar solo Admin: el log es rastro de auditoría y quien lo vacía tapa
        // huellas. Manager y Support lo ven pero no lo borran.
        $this->createPermissionAndAssign('admin.api-logs.destroy', 'api_logs', 'API Logs: Borrar registros', [$role_admin]);

        // Notices

        // Products
        $this->createPermissionAndAssign('admin.products.index', 'products', 'Productos: Ver listado', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.products.create', 'products', 'Productos: Crear', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.products.edit', 'products', 'Productos: Editar', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.products.destroy', 'products', 'Productos: Eliminar', [$role_admin]);
        $this->createPermissionAndAssign('admin.products.show', 'products', 'Productos: Ver detalle', [$role_admin, $role_manager, $role_developer]);

        // Setups
        $this->createPermissionAndAssign('admin.setups.index', 'setups', 'Setups: Ver listado', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.setups.create', 'setups', 'Setups: Crear', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.setups.edit', 'setups', 'Setups: Editar', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.setups.show', 'setups', 'Setups: Ver detalle', [$role_admin, $role_manager, $role_developer]);

        // Features
        $this->createPermissionAndAssign('admin.features.index', 'features', 'Features: Ver listado', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.features.create', 'features', 'Features: Crear', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.features.edit', 'features', 'Features: Editar', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.features.destroy', 'features', 'Features: Eliminar', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.features.version.create', 'features', 'Features: Crear versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.features.version.edit', 'features', 'Features: Editar versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.features.version.show', 'features', 'Features: Ver versión', [$role_admin, $role_manager, $role_developer]);

        // Tutorials
        $this->createPermissionAndAssign('admin.tutorials.index', 'tutorials', 'Tutoriales: Ver listado', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.tutorials.create', 'tutorials', 'Tutoriales: Crear', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.tutorials.edit', 'tutorials', 'Tutoriales: Editar', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.tutorials.destroy', 'tutorials', 'Tutoriales: Eliminar', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.tutorials.version.create', 'tutorials', 'Tutoriales: Crear versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.tutorials.version.edit', 'tutorials', 'Tutoriales: Editar versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.tutorials.version.show', 'tutorials', 'Tutoriales: Ver versión', [$role_admin, $role_manager, $role_developer]);

        // Resources
        $this->createPermissionAndAssign('admin.resources.index', 'resources', 'Recursos: Ver listado', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.resources.create', 'resources', 'Recursos: Crear', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.resources.edit', 'resources', 'Recursos: Editar', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.resources.destroy', 'resources', 'Recursos: Eliminar', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.resources.version.create', 'resources', 'Recursos: Crear versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.resources.version.edit', 'resources', 'Recursos: Editar versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.resources.version.show', 'resources', 'Recursos: Ver versión', [$role_admin, $role_manager, $role_developer]);

        // SCSS
        $this->createPermissionAndAssign('admin.scss.index', 'scss', 'SCSS: Ver listado', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss.version.create', 'scss', 'SCSS: Crear versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss.version.edit', 'scss', 'SCSS: Editar versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss.version.show', 'scss', 'SCSS: Ver versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss.files.upload', 'scss', 'SCSS: Subir archivos', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss.file.create', 'scss', 'SCSS: Crear archivo', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss.file.show', 'scss', 'SCSS: Ver archivo', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss.file.edit', 'scss', 'SCSS: Editar archivo', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss.file.destroy', 'scss', 'SCSS: Eliminar archivo', [$role_admin, $role_manager, $role_developer]);

        // JS
        $this->createPermissionAndAssign('admin.js.index', 'js', 'JS: Ver listado', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.js.version.create', 'js', 'JS: Crear versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.js.version.edit', 'js', 'JS: Editar versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.js.version.show', 'js', 'JS: Ver versión', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.js.files.upload', 'js', 'JS: Subir archivos', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.js.file.create', 'js', 'JS: Crear archivo', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.js.file.show', 'js', 'JS: Ver archivo', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.js.file.edit', 'js', 'JS: Editar archivo', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.js.file.destroy', 'js', 'JS: Eliminar archivo', [$role_admin, $role_manager, $role_developer]);

        // SCSS CDN
        $this->createPermissionAndAssign('admin.scss-cdn.index', 'scss_cdn', 'SCSS CDN: Ver listado', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss-cdn.create', 'scss_cdn', 'SCSS CDN: Crear bundle', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss-cdn.bundle.show', 'scss_cdn', 'SCSS CDN: Ver bundle', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss-cdn.bundle.edit', 'scss_cdn', 'SCSS CDN: Editar bundle', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss-cdn.bundle.upload', 'scss_cdn', 'SCSS CDN: Subir bundle', [$role_admin, $role_manager, $role_developer]);
        $this->createPermissionAndAssign('admin.scss-cdn.file.edit', 'scss_cdn', 'SCSS CDN: Editar archivo', [$role_admin, $role_manager, $role_developer]);

        // License Tokens
        $this->createPermissionAndAssign('admin.license-tokens.index', 'license_tokens', 'Tokens de Licencia: Ver listado', [$role_admin, $role_manager]);
        $this->createPermissionAndAssign('admin.license-tokens.create', 'license_tokens', 'Tokens de Licencia: Crear', [$role_admin, $role_manager]);
        $this->createPermissionAndAssign('admin.license-tokens.edit', 'license_tokens', 'Tokens de Licencia: Editar', [$role_admin, $role_manager]);
        $this->createPermissionAndAssign('admin.license-tokens.destroy', 'license_tokens', 'Tokens de Licencia: Eliminar', [$role_admin]);
        $this->createPermissionAndAssign('admin.license-tokens.show', 'license_tokens', 'Tokens de Licencia: Ver detalle', [$role_admin, $role_manager]);
        $this->createPermissionAndAssign('admin.license-tokens.manage-environments', 'license_tokens', 'Tokens de Licencia: Gestionar entornos', [$role_admin, $role_manager]);
        $this->createPermissionAndAssign('admin.license-tokens.associate-license', 'license_tokens', 'Tokens de Licencia: Asociar licencia', [$role_admin, $role_manager]);

        // Configurations - Environments Types
        $this->createPermissionAndAssign('admin.configurations.environments-types.index', 'configurations', 'Configuraciones: Ver tipos de entornos', [$role_admin, $role_system]);
        $this->createPermissionAndAssign('admin.configurations.environments-types.create', 'configurations', 'Configuraciones: Crear tipo de entorno', [$role_admin, $role_system]);
        $this->createPermissionAndAssign('admin.configurations.environments-types.edit', 'configurations', 'Configuraciones: Editar tipo de entorno', [$role_admin, $role_system]);
        // **No existía.** El botón de borrar estaba comentado en el blade y apuntaba a
        // una ruta inexistente, así que no se podía retirar un tipo de entorno desde el
        // panel. Solo Admin: un tipo con entornos no se puede borrar, y decidir que uno
        // ya no vale es una decisión de catálogo.
        $this->createPermissionAndAssign('admin.configurations.environments-types.destroy', 'configurations', 'Configuraciones: Borrar tipo de entorno', [$role_admin]);

        // Configurations - Usos del entorno (pro, pre, develop, local)
        //
        // **Aparte de los tipos**, aunque se vean en la misma hoja: son dos catálogos y
        // este es el delicado —de él dependen la validación de la API pública y qué se ve
        // al abrir el listado de entornos—. Y sin `index` propio a propósito: el listado
        // vive dentro de la hoja de Catálogos, que ya está gateada, y un permiso para ver
        // una tabla dentro de una pantalla que ya se está viendo no gatearía nada
        // (MGR-101).
        $this->createPermissionAndAssign('admin.configurations.envs.create', 'configurations', 'Configuraciones: Crear uso de entorno', [$role_admin, $role_system]);
        $this->createPermissionAndAssign('admin.configurations.envs.edit', 'configurations', 'Configuraciones: Editar uso de entorno', [$role_admin, $role_system]);
        // Solo Admin, igual que en el resto de catálogos: un uso con entornos no se puede
        // borrar, y decidir que uno ya no vale es una decisión de catálogo.
        $this->createPermissionAndAssign('admin.configurations.envs.destroy', 'configurations', 'Configuraciones: Borrar uso de entorno', [$role_admin]);

        // Configurations - Products
        $this->createPermissionAndAssign('admin.configurations.products.index', 'configurations', 'Configuraciones: Ver productos', [$role_admin, $role_system]);

        /**
         * Los roles de los usuarios iniciales, por nombre y solo de los que existen. Si
         * el rol de `config/seed.php` no es uno de los del sistema se avisa en vez de
         * reventar: es una errata en el `.env`, no un fallo del seeder.
         */
        foreach ($porRol as $nombreDeRol => $usuariosDelRol) {
            $rol = Role::where('name', $nombreDeRol)->first();

            if (!$rol) {
                $this->command?->warn("El rol «{$nombreDeRol}» de config/seed.php no existe: esos usuarios se han creado sin rol.");

                continue;
            }

            foreach ($usuariosDelRol as $usuario) {
                $usuario->assignRole($rol);
            }
        }

        // Asegurar que el rol Admin tenga TODOS los permisos existentes
        // Esto es necesario porque la migración puede crear permisos adicionales
        // que no están en este seeder
        $allPermissions = Permission::all();
        foreach ($allPermissions as $permission) {
            if (!$role_admin->hasPermissionTo($permission)) {
                $role_admin->givePermissionTo($permission);
            }
        }

        // ============ El rol Support ============
        // **Tenía cero permisos**: entraba al panel y no veía nada, cuando revisar
        // incidencias es precisamente su trabajo —cinco pantallas del panel están
        // construidas diciendo «esto lo mira Soporte»—.
        //
        // Se asigna de golpe desde la constante y con `syncPermissions`, no permiso a
        // permiso: la constante **es** la definición del rol, así que quitar uno de la
        // lista tiene que quitarlo del rol.
        $role_support->syncPermissions(
            Permission::whereIn('name', self::PERMISOS_DE_SOPORTE)->pluck('name')->all()
        );

        // Limpiar caché de permisos
        app()['cache']->forget('spatie.permission.cache');
    }
}
