-- =============================================================================
-- Migración:    0008_create_audit_log_table
-- Sprint:       1.1 — auth + RBAC + audit
-- Tabla:        audit_log
-- Aplica en:    BD de cada tenant (innovium_<slug>)
-- Dependencias: 0001 (users).
--
-- Descripción:
--   Registro INMUTABLE de todo lo mutativo del sistema. Solo se hacen
--   INSERTs — NUNCA UPDATE ni DELETE. La inmutabilidad es convención de
--   código (App\Core\AuditLog::record), no constraint físico.
--
--   En Sprint 1.1 registra acciones de auth:
--     - user.login            → login exitoso
--     - user.login_fallido    → intento fallido (user_id NULL si email
--                               no existe)
--     - user.logout
--     - user.password_cambiado
--   Sprints siguientes agregan más acciones (contrato.creado, pago.registrado…).
--
-- Notas:
--   - user_id NULL: hay acciones del sistema (jobs cron, login fallido
--     por email inexistente) sin user.
--   - ON DELETE RESTRICT en user_id: nunca borrar un user que tenga
--     audit_log. Combinado con soft delete en users, esto preserva
--     trazabilidad histórica completa.
--   - entidad_tipo / entidad_id: relación polimórfica (no FK), permite
--     loguear acciones sobre cualquier entidad (Contrato, Cuota, Cliente…).
--   - datos_antes / datos_despues: JSON con snapshot del estado.
--   - Índice (entidad_tipo, entidad_id): "dame el historial de
--     este contrato".
--   - Índice (user_id, creado_en): "dame el historial de este usuario".
--   - Índice (accion, creado_en): "dame todos los login_fallido de la
--     última hora" (útil para Sprint 2.x cuando agreguemos lockout).
-- =============================================================================

CREATE TABLE audit_log (
    id             BIGINT UNSIGNED NOT NULL AUTO_INCREMENT
                   COMMENT 'PK auto-incremental.',
    user_id        BIGINT UNSIGNED     NULL
                   COMMENT 'FK → users.id (RESTRICT). NULL si la acción fue del sistema o login_fallido por email inexistente.',
    accion         VARCHAR(100)    NOT NULL
                   COMMENT 'Verbo dotted (ej: "user.login", "contrato.creado").',
    entidad_tipo   VARCHAR(50)         NULL
                   COMMENT 'Clase de la entidad afectada (ej: "Contrato"). Polimórfico, no FK.',
    entidad_id     BIGINT UNSIGNED     NULL
                   COMMENT 'PK de la entidad afectada. Polimórfico, no FK.',
    datos_antes    JSON                NULL
                   COMMENT 'Snapshot del estado previo (en updates/deletes). NULL en creates.',
    datos_despues  JSON                NULL
                   COMMENT 'Snapshot del estado nuevo (en creates/updates). NULL en deletes.',
    ip             VARCHAR(45)     NOT NULL
                   COMMENT 'IPv4 o IPv6 desde donde se hizo la acción.',
    user_agent     VARCHAR(500)        NULL
                   COMMENT 'Navegador/dispositivo. NULL si la acción fue de un job o CLI.',
    creado_en      DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP
                   COMMENT 'UTC del evento. Inmutable.',
    PRIMARY KEY (id),
    KEY idx_audit_log_user_creado (user_id, creado_en),
    KEY idx_audit_log_entidad (entidad_tipo, entidad_id),
    KEY idx_audit_log_accion_creado (accion, creado_en),
    CONSTRAINT fk_audit_log_user
        FOREIGN KEY (user_id) REFERENCES users (id)
        ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  COMMENT='Registro inmutable de acciones mutativas. Solo INSERTs (convención de código).';
