
ALTER TABLE `access_attempts`
  MODIFY `tipo` ENUM(
    'login','logout','recuperacion','restablecer','mfa',
    'usuario_crear','usuario_actualizar','usuario_toggle','usuario_forzar_clave','usuario_roles_actualizar',
    'rol_crear','rol_actualizar','rol_toggle','rol_permisos_actualizar'
  ) NOT NULL;

CREATE TABLE IF NOT EXISTS `roles` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `codigo` VARCHAR(80) NOT NULL,
  `nombre` VARCHAR(120) NOT NULL,
  `descripcion` VARCHAR(255) NULL,
  `estado` ENUM('activo','inactivo') NOT NULL DEFAULT 'activo',
  `protegido` TINYINT(1) NOT NULL DEFAULT 0,
  `creado_por` BIGINT UNSIGNED NULL,
  `actualizado_por` BIGINT UNSIGNED NULL,
  `creado_en` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `actualizado_en` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_roles_codigo` (`codigo`),
  KEY `idx_roles_estado` (`estado`),
  KEY `idx_roles_protegido` (`protegido`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS `permisos` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `codigo` VARCHAR(120) NOT NULL,
  `nombre` VARCHAR(150) NOT NULL,
  `descripcion` VARCHAR(255) NULL,
  `modulo` VARCHAR(80) NOT NULL,
  `estado` ENUM('activo','inactivo') NOT NULL DEFAULT 'activo',
  `creado_en` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `actualizado_en` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_permisos_codigo` (`codigo`),
  KEY `idx_permisos_modulo_estado` (`modulo`, `estado`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS `rol_permisos` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `rol_id` BIGINT UNSIGNED NOT NULL,
  `permiso_id` BIGINT UNSIGNED NOT NULL,
  `asignado_por` BIGINT UNSIGNED NULL,
  `creado_en` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `actualizado_en` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_rol_permisos_rol_permiso` (`rol_id`, `permiso_id`),
  KEY `idx_rol_permisos_permiso` (`permiso_id`),
  CONSTRAINT `fk_rol_permisos_rol` FOREIGN KEY (`rol_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_rol_permisos_permiso` FOREIGN KEY (`permiso_id`) REFERENCES `permisos` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `roles` (`codigo`, `nombre`, `descripcion`, `estado`, `protegido`, `creado_en`, `actualizado_en`)
VALUES
  ('superadmin_total', 'Control total', 'Puede gestionar accesos, usuarios, roles y permisos del panel principal.', 'activo', 1, NOW(), NOW()),
  ('acceso_seguridad', 'Acceso y seguridad', 'Puede ordenar accesos, cuentas y refuerzos de protección del panel principal.', 'activo', 1, NOW(), NOW()),
  ('seguimiento_general', 'Seguimiento general', 'Puede revisar el panel principal y dar seguimiento sin control total.', 'activo', 1, NOW(), NOW()),
  ('solo_lectura', 'Solo lectura', 'Puede revisar el estado general sin realizar cambios.', 'activo', 1, NOW(), NOW())
ON DUPLICATE KEY UPDATE
  `nombre` = VALUES(`nombre`),
  `descripcion` = VALUES(`descripcion`),
  `actualizado_en` = NOW();

INSERT INTO `permisos` (`codigo`, `nombre`, `descripcion`, `modulo`, `estado`, `creado_en`, `actualizado_en`)
VALUES
  ('dashboard.read', 'Ver dashboard', 'Permite revisar el resumen principal del panel.', 'dashboard', 'activo', NOW(), NOW()),
  ('users.read', 'Ver usuarios', 'Permite revisar el listado de cuentas.', 'usuarios', 'activo', NOW(), NOW()),
  ('users.write', 'Gestionar usuarios', 'Permite crear, editar y cambiar el estado de cuentas.', 'usuarios', 'activo', NOW(), NOW()),
  ('roles.read', 'Ver roles', 'Permite revisar el catálogo de roles.', 'roles', 'activo', NOW(), NOW()),
  ('roles.write', 'Gestionar roles', 'Permite crear, editar y cambiar el estado de roles.', 'roles', 'activo', NOW(), NOW()),
  ('permissions.read', 'Ver permisos', 'Permite revisar el catálogo de permisos.', 'permisos', 'activo', NOW(), NOW()),
  ('permissions.assign', 'Asignar permisos', 'Permite definir qué permisos tendrá cada rol.', 'permisos', 'activo', NOW(), NOW()),
  ('security.read', 'Revisar seguridad base', 'Permite revisar el estado general de acceso protegido.', 'seguridad', 'activo', NOW(), NOW())
ON DUPLICATE KEY UPDATE
  `nombre` = VALUES(`nombre`),
  `descripcion` = VALUES(`descripcion`),
  `modulo` = VALUES(`modulo`),
  `actualizado_en` = NOW();

INSERT INTO `rol_permisos` (`rol_id`, `permiso_id`, `asignado_por`, `creado_en`, `actualizado_en`)
SELECT r.id, p.id, NULL, NOW(), NOW()
FROM `roles` r
JOIN `permisos` p ON (
      r.codigo = 'superadmin_total'
   OR (r.codigo = 'acceso_seguridad' AND p.codigo IN ('dashboard.read','users.read','users.write','roles.read','roles.write','permissions.read','permissions.assign','security.read'))
   OR (r.codigo = 'seguimiento_general' AND p.codigo IN ('dashboard.read','users.read','roles.read','permissions.read'))
   OR (r.codigo = 'solo_lectura' AND p.codigo IN ('dashboard.read','users.read','roles.read','permissions.read'))
)
LEFT JOIN `rol_permisos` rp ON rp.rol_id = r.id AND rp.permiso_id = p.id
WHERE rp.id IS NULL;

ALTER TABLE `usuario_roles`
  ADD COLUMN IF NOT EXISTS `rol_id` BIGINT UNSIGNED NULL AFTER `usuario_id`;

UPDATE `usuario_roles` ur
JOIN `roles` r ON r.codigo = ur.rol_codigo
SET ur.rol_id = r.id
WHERE ur.rol_id IS NULL;

SET @db_name = DATABASE();
SET @has_idx_rol_id = (
  SELECT COUNT(*) FROM information_schema.statistics
  WHERE table_schema = @db_name AND table_name = 'usuario_roles' AND index_name = 'idx_usuario_roles_rol_id'
);
SET @sql_idx_rol_id = IF(@has_idx_rol_id = 0,
  'ALTER TABLE `usuario_roles` ADD KEY `idx_usuario_roles_rol_id` (`rol_id`)',
  'SELECT 1'
);
PREPARE stmt_idx_rol_id FROM @sql_idx_rol_id;
EXECUTE stmt_idx_rol_id;
DEALLOCATE PREPARE stmt_idx_rol_id;

SET @has_fk_rol = (
  SELECT COUNT(*) FROM information_schema.table_constraints
  WHERE table_schema = @db_name AND table_name = 'usuario_roles' AND constraint_name = 'fk_usuario_roles_rol'
);
SET @sql_fk_rol = IF(@has_fk_rol = 0,
  'ALTER TABLE `usuario_roles` ADD CONSTRAINT `fk_usuario_roles_rol` FOREIGN KEY (`rol_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE',
  'SELECT 1'
);
PREPARE stmt_fk_rol FROM @sql_fk_rol;
EXECUTE stmt_fk_rol;
DEALLOCATE PREPARE stmt_fk_rol;

SET @has_uq_usuario_role = (
  SELECT COUNT(*) FROM information_schema.statistics
  WHERE table_schema = @db_name AND table_name = 'usuario_roles' AND index_name = 'uq_usuario_roles_usuario_role_id'
);
SET @sql_uq_usuario_role = IF(@has_uq_usuario_role = 0,
  'ALTER TABLE `usuario_roles` ADD UNIQUE KEY `uq_usuario_roles_usuario_role_id` (`usuario_id`, `rol_id`)',
  'SELECT 1'
);
PREPARE stmt_uq_usuario_role FROM @sql_uq_usuario_role;
EXECUTE stmt_uq_usuario_role;
DEALLOCATE PREPARE stmt_uq_usuario_role;

UPDATE `usuario_roles` ur
JOIN `roles` r ON r.id = ur.rol_id
SET ur.rol_codigo = r.codigo,
    ur.rol_nombre = r.nombre,
    ur.actualizado_en = NOW();

