-- === LOGIN HARDENING ===

ALTER TABLE refresh_token
  ADD COLUMN IF NOT EXISTS revoked_at TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS replaced_by_token_id BIGINT REFERENCES refresh_token(id) ON DELETE SET NULL,
  ADD COLUMN IF NOT EXISTS user_agent TEXT,
  ADD COLUMN IF NOT EXISTS ip_address INET,
  ADD COLUMN IF NOT EXISTS device_name VARCHAR(120);

CREATE TABLE IF NOT EXISTS auth_login_attempt (
  id BIGSERIAL PRIMARY KEY,
  email_attempted VARCHAR(255),
  user_id BIGINT REFERENCES app_user(id) ON DELETE SET NULL,
  success BOOLEAN NOT NULL DEFAULT FALSE,
  failure_reason VARCHAR(100),
  ip_address INET,
  user_agent TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS auth_lockout (
  user_id BIGINT PRIMARY KEY REFERENCES app_user(id) ON DELETE CASCADE,
  failed_attempts INTEGER NOT NULL DEFAULT 0,
  locked_until TIMESTAMPTZ,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS password_reset_token (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
  token_hash TEXT NOT NULL,
  expires_at TIMESTAMPTZ NOT NULL,
  used_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

ALTER TABLE app_user
  ADD COLUMN IF NOT EXISTS password_changed_at TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS email_verified_at TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS locked_until TIMESTAMPTZ,
  ADD COLUMN IF NOT EXISTS failed_login_attempts INTEGER NOT NULL DEFAULT 0,
  ADD COLUMN IF NOT EXISTS must_enroll_webauthn BOOLEAN NOT NULL DEFAULT FALSE,
  ADD COLUMN IF NOT EXISTS must_enroll_totp BOOLEAN NOT NULL DEFAULT FALSE;

ALTER TABLE user_totp_secret
  ADD COLUMN IF NOT EXISTS secret_ciphertext BYTEA,
  ADD COLUMN IF NOT EXISTS secret_key_version INTEGER NOT NULL DEFAULT 1;

ALTER TABLE webauthn_credential
  ADD COLUMN IF NOT EXISTS aaguid UUID,
  ADD COLUMN IF NOT EXISTS rp_id VARCHAR(255),
  ADD COLUMN IF NOT EXISTS origin VARCHAR(255),
  ADD COLUMN IF NOT EXISTS attestation_format VARCHAR(50),
  ADD COLUMN IF NOT EXISTS last_ip INET,
  ADD COLUMN IF NOT EXISTS is_primary BOOLEAN NOT NULL DEFAULT FALSE;

CREATE INDEX IF NOT EXISTS idx_refresh_token_user_id ON refresh_token(user_id);
CREATE INDEX IF NOT EXISTS idx_refresh_token_expires_at ON refresh_token(expires_at);
CREATE INDEX IF NOT EXISTS idx_auth_challenge_expires_at ON auth_challenge(expires_at);
CREATE INDEX IF NOT EXISTS idx_webauthn_challenge_expires_at ON webauthn_challenge(expires_at);
CREATE UNIQUE INDEX IF NOT EXISTS idx_app_user_email_lower ON app_user (LOWER(email));
