"""app_accounts — the app's own user table, keyed on the BW username.

Scout stores no passwords and no credentials of any kind. Identity comes from the
BW id-auth gate (Pattern B); this table holds only what the app owns about a
person: their level, whether they are still active, and app-local profile fields.

A row may exist before the person has ever signed in: an admin pre-provisions one
when granting access. The login upsert is COLUMN-SCOPED so it fills in the
BW-derived columns without ever clobbering app-local ones.
"""

from datetime import datetime

from sqlalchemy import Boolean, DateTime, String, func
from sqlalchemy.orm import Mapped, mapped_column

from app.models.base import Base


class Account(Base):
    __tablename__ = "app_accounts"

    # The BW account username — the stable app-wide primary key.
    username: Mapped[str] = mapped_column(String(64), primary_key=True)

    # BW-derived columns. Empty until the person's first sign-in; refreshed from
    # the verified identity on every login.
    email: Mapped[str] = mapped_column(String(255), default="", server_default="")
    first: Mapped[str] = mapped_column(String(120), default="", server_default="")
    last: Mapped[str] = mapped_column(String(120), default="", server_default="")

    # App-owned columns. BW never reads or writes these.
    # `level` is the APP-WIDE level (a name in app_levels). Per-project levels
    # live on project_members; see app/services/levels.py for which question
    # each answers. `all_instances` means the app-wide level applies to every
    # project without an explicit grant.
    level: Mapped[str] = mapped_column(String(40), default="reviewer", server_default="reviewer")
    all_instances: Mapped[bool] = mapped_column(Boolean, default=False, server_default="false")
    active: Mapped[bool] = mapped_column(Boolean, default=True, server_default="true")

    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    last_login: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)

    @property
    def display_name(self) -> str:
        full = f"{self.first} {self.last}".strip()
        return full or self.username
