"""Add backup_codes table and password_must_change column to users.

Revision ID: 0002
Revises: 0001
Create Date: 2026-05-22

Changes:
  1. Add `password_must_change` BOOLEAN NOT NULL DEFAULT false to users table (ADMIN-01)
  2. Create `backup_codes` table for TOTP recovery codes (AUTH-02)

Note: documents.user_id stays nullable per D-03 — NOT NULL is deferred to Phase 3.
"""
from __future__ import annotations

import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
from alembic import op

# revision identifiers, used by Alembic.
revision = "0002"
down_revision = "0001"
branch_labels = None
depends_on = None


def upgrade() -> None:
    # ── 1. Add password_must_change to users ──────────────────────────────────
    op.add_column(
        "users",
        sa.Column(
            "password_must_change",
            sa.Boolean(),
            nullable=False,
            server_default="false",
        ),
    )

    # ── 2. Create backup_codes table ──────────────────────────────────────────
    op.create_table(
        "backup_codes",
        sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column("user_id", postgresql.UUID(as_uuid=True), nullable=False),
        sa.Column("code_hash", sa.Text(), nullable=False),
        sa.Column("used_at", sa.TIMESTAMP(timezone=True), nullable=True),
        sa.ForeignKeyConstraint(["user_id"], ["users.id"], ondelete="CASCADE"),
        sa.PrimaryKeyConstraint("id"),
    )
    op.create_index("ix_backup_codes_user_id", "backup_codes", ["user_id"])

    # ── Privilege grants (Pitfall 4) ───────────────────────────────────────────
    op.execute(
        "GRANT SELECT, INSERT, UPDATE, DELETE ON backup_codes TO docuvault_app;"
    )


def downgrade() -> None:
    # ── Drop backup_codes ─────────────────────────────────────────────────────
    op.drop_index("ix_backup_codes_user_id", table_name="backup_codes")
    op.drop_table("backup_codes")

    # ── Remove password_must_change from users ────────────────────────────────
    op.drop_column("users", "password_must_change")
