-- 0002_auth.sql - 用户认证 + 防撞库 (MySQL)

CREATE TABLE IF NOT EXISTS users (
    id              INT AUTO_INCREMENT PRIMARY KEY,
    username        VARCHAR(50)     NOT NULL UNIQUE,
    password_hash   VARCHAR(255)    NOT NULL,
    role            VARCHAR(20)     NOT NULL DEFAULT 'user',
    is_active       TINYINT(1)     NOT NULL DEFAULT 1,
    last_login_at   DATETIME        DEFAULT NULL,
    last_login_ip   VARCHAR(45)     DEFAULT NULL,
    created_at      DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at      DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    CONSTRAINT chk_role CHECK (role IN ('user','admin'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE INDEX idx_users_active ON users(is_active);

CREATE TABLE IF NOT EXISTS login_attempts (
    id              INT AUTO_INCREMENT PRIMARY KEY,
    attempted_at    DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP,
    ip_address      VARCHAR(45)     NOT NULL,
    username        VARCHAR(50)     NOT NULL,
    success         TINYINT(1)     NOT NULL,
    user_agent      VARCHAR(500)    DEFAULT NULL,
    failure_reason  VARCHAR(100)    DEFAULT NULL,
    CONSTRAINT chk_success CHECK (success IN (0, 1))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE INDEX idx_attempts_ip_time   ON login_attempts(ip_address, attempted_at);
CREATE INDEX idx_attempts_user_time ON login_attempts(username, attempted_at);
CREATE INDEX idx_attempts_time      ON login_attempts(attempted_at);

CREATE TABLE IF NOT EXISTS auth_locks (
    lock_key       VARCHAR(100)    PRIMARY KEY,
    lock_type      VARCHAR(10)     NOT NULL,
    target         VARCHAR(50)     NOT NULL,
    locked_until   DATETIME        NOT NULL,
    reason         VARCHAR(255)    DEFAULT NULL,
    attempts       INT             NOT NULL DEFAULT 0,
    created_at     DATETIME        NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT chk_lock_type CHECK (lock_type IN ('ip','user'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE INDEX idx_locks_until ON auth_locks(locked_until);

INSERT IGNORE INTO settings (`key`, value, is_secret, description) VALUES
    ('session_lifetime_days', '30', 0, '登录 session 有效期（天）'),
    ('session_cookie_secure', 'auto', 0, 'Cookie secure 标志：true/false/auto'),
    ('login_max_failures_ip', '5', 0, '每 IP 允许的最大连续失败次数'),
    ('login_max_failures_user', '5', 0, '每用户名允许的最大连续失败次数'),
    ('login_lock_minutes_ip', '15', 0, 'IP 级别锁定时长（分钟）'),
    ('login_lock_minutes_user', '30', 0, '用户名级别锁定时长（分钟）'),
    ('login_global_max_failures', '10', 0, '触发全局 IP 封锁的失败次数'),
    ('login_global_lock_hours', '1', 0, '全局 IP 封锁时长（小时）'),
    ('login_attempts_retention_days', '30', 0, 'login_attempts 保留天数'),
    ('csrf_token_lifetime_hours', '12', 0, 'CSRF token 有效期（小时）'),
    ('bcrypt_cost', '12', 0, 'bcrypt cost factor');
