"""create user_mfa table

Revision ID: c5e7a9b3f2d1
Revises: a2c4e6f8b1d3
Create Date: 2026-05-03 00:00:00.000000

Adds SMS-based multi-factor authentication support for local-auth users.
One row per user. `pending_*` columns hold enrollment state and are
cleared on successful verification.
"""
from typing import Sequence, Union

import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision: str = "c5e7a9b3f2d1"
down_revision: Union[str, Sequence[str], None] = "a2c4e6f8b1d3"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def _has_table(table: str) -> bool:
    bind = op.get_bind()
    inspector = sa.inspect(bind)
    try:
        return inspector.has_table(table)
    except Exception:  # noqa: BLE001
        return False


def upgrade() -> None:
    if not _has_table("user_mfa"):
        op.create_table(
            "user_mfa",
            sa.Column("user_id", sa.String(length=255), primary_key=True, nullable=False),
            sa.Column("enabled", sa.Boolean(), nullable=False, server_default=sa.text("false")),
            sa.Column("method", sa.String(length=16), nullable=False, server_default="sms"),
            sa.Column("phone_e164", sa.String(length=32), nullable=True),
            sa.Column("pending_phone", sa.String(length=32), nullable=True),
            sa.Column("pending_code_hash", sa.String(length=128), nullable=True),
            sa.Column("pending_expires_at", sa.DateTime(timezone=True), nullable=True),
            sa.Column("pending_attempts", sa.Integer(), nullable=False, server_default=sa.text("0")),
            sa.Column("last_challenge_sent_at", sa.DateTime(timezone=True), nullable=True),
            sa.Column("last_verified_at", sa.DateTime(timezone=True), nullable=True),
            sa.Column(
                "created_at",
                sa.DateTime(timezone=True),
                server_default=sa.func.now(),
                nullable=False,
            ),
            sa.Column(
                "updated_at",
                sa.DateTime(timezone=True),
                server_default=sa.func.now(),
                nullable=False,
            ),
        )
        op.create_index("ix_user_mfa_user_id", "user_mfa", ["user_id"], unique=False)


def downgrade() -> None:
    if _has_table("user_mfa"):
        try:
            op.drop_index("ix_user_mfa_user_id", table_name="user_mfa")
        except Exception:  # noqa: BLE001
            pass
        op.drop_table("user_mfa")