# @File: backend/models/mfa.py
# @Desc: Multi-Factor Authentication storage for local-auth users.
#
# One row per user who has ever enrolled in MFA. If MFA is disabled the row
# may linger with `enabled=False` so admins can see historical enrollment.
#
# `pending_*` columns are used during the enrollment flow: the user posts a
# phone number, we SMS them a code and store its SHA-256 hash here. On
# successful verification the hash is cleared and `phone_e164` is promoted
# to the verified column, `enabled` is flipped on.
from core.database import Base
from sqlalchemy import Boolean, Column, DateTime, Integer, String
from sqlalchemy.sql import func


class UserMFA(Base):
    """Per-user MFA settings. Keyed by ``user_id`` (the platform/local User id)."""

    __tablename__ = "user_mfa"
    __table_args__ = ({"extend_existing": True},)

    user_id = Column(String(255), primary_key=True, index=True)

    # Whether MFA is currently required for this user at login time.
    enabled = Column(Boolean, default=False, nullable=False)
    # Delivery method. For now only "sms" is implemented; the column is here so
    # a future "totp" method can reuse the same row without a schema change.
    method = Column(String(16), default="sms", nullable=False)

    # E.164 verified phone number, e.g. "+966501234567". NULL until verified.
    phone_e164 = Column(String(32), nullable=True)

    # Pending enrollment state — cleared on success or abandon.
    pending_phone = Column(String(32), nullable=True)
    pending_code_hash = Column(String(128), nullable=True)
    pending_expires_at = Column(DateTime(timezone=True), nullable=True)
    pending_attempts = Column(Integer, default=0, nullable=False)

    # Login challenge counters (updated on each /challenge/send)
    last_challenge_sent_at = Column(DateTime(timezone=True), nullable=True)
    last_verified_at = Column(DateTime(timezone=True), nullable=True)

    created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    updated_at = Column(
        DateTime(timezone=True),
        server_default=func.now(),
        onupdate=func.now(),
        nullable=False,
    )