"""View As: DFP's policy over the vendored `bw_view_as` mechanism, and its reporting.

Sources of truth: this module, `app/vendor/bw_view_as.py` (the guards: server-side
authorisation on start, per-request re-authorisation, the no-escalation rank check, the
nesting refusal), `app/services/sessions.py` (the state lives on the session row),
`docs/ACCOUNTS.md`. Design: `.logs/planning/accounts-2026-09.md` §4.9.

Policy: the owner, or a level holding `accounts.view_as`, may view as any active account
that is not the owner, membership not required (a consumer's `can()` misses and the rank
hook returns 0, so the rank guard still holds); act mode is the owner's alone. Data and
permissions follow the EFFECTIVE user; identity and audit follow the REAL one. Explicit
start and stop are recorded by the directory's `report_impersonation`; the fail-closed
auto-stop inside `verify` is recorded by the audit sink with `auto: true`, so no start or
stop is ever written twice.
"""

from __future__ import annotations

import logging

from sqlalchemy import select
from starlette.requests import Request

from app import db as appdb
from app.models import Account
from app.services import accounts, audit_log, sessions
from app.vendor import bw_accounts as bwa
from app.vendor import bw_view_as

log = logging.getLogger(__name__)

ViewAsError = bw_view_as.ViewAsError

# Rank derives from the permissions a level holds, never its name: a fresh custom level has
# no entry in a name-keyed map and would be refused against everyone.
rank_of = bw_view_as.permission_weighted_rank_of(bwa)


def can_view_as(real: str, target: str) -> bool:
    return accounts.is_owner(real) or accounts.can(real, bwa.PERM_ACCOUNTS_VIEW_AS)


def target_valid(username: str) -> bool:
    """Any active account that is not the owner, so a deleted or disabled target auto-stops on
    the next request and growth to consumers changes nothing here."""
    name = (username or "").strip().lower()
    if not name or accounts.is_owner(name):
        return False
    with appdb.SessionLocal() as db:
        status = db.scalar(select(Account.status).where(Account.username == name))
    return status == "active"


def verify_and_effective(request: Request) -> str | None:
    """Re-authorise any active View As (fail-closed auto-stop), then the EFFECTIVE username.
    The identity resolver calls this on every request; nothing reads the row's target
    directly for a data decision."""
    row = sessions.of_request(request)
    if row is None or not row.active:
        return None
    bw_view_as.verify(row, can_view_as=can_view_as, rank_of=rank_of,
                      target_valid=target_valid, audit=audit_log.view_as_sink)
    return bw_view_as.effective_username(row)


def read_only(request: Request) -> bool:
    """True while impersonating in read-only mode: the access policy blocks every mutation
    but stop and logout."""
    row = sessions.of_request(request)
    return row is not None and bool(row.acting_as) and not bw_view_as.can_write(row)


def start(request: Request, target: str, mode: str = "readonly") -> None:
    """Begin impersonation. Act mode is the owner's alone: acting writes real rows under the
    target's name (rian's "view and act as any user")."""
    row = sessions.of_request(request)
    if row is None:
        raise ViewAsError("You are not signed in.", "NOT_SIGNED_IN")
    real = bw_view_as.real_username(row)
    if mode == "act" and not accounts.is_owner(real):
        raise ViewAsError("Only the owner may act as another user.", "FORBIDDEN")
    bw_view_as.start(row, target, can_view_as=can_view_as, rank_of=rank_of,
                     target_valid=target_valid, mode=mode)
    _report(real, bw_view_as.effective_username(row), mode=mode, active=True)


def stop(request: Request) -> None:
    row = sessions.of_request(request)
    if row is None:
        return
    real = bw_view_as.real_username(row)
    target = bw_view_as.effective_username(row)  # capture BEFORE stopping
    was_active = bw_view_as.is_impersonating(row)
    mode = bw_view_as.mode(row)
    bw_view_as.stop(row)
    if was_active:
        _report(real, target, mode=mode, active=False)


def _report(real: str, target: str, mode: str = "readonly", active: bool = True) -> None:
    """The audit row for an explicit start or stop, through the directory (what the kit calls
    central oversight). Best-effort: a failure here never breaks the request."""
    try:
        accounts.directory_instance().report_impersonation(real, target, mode=mode, active=active)
    except Exception as exc:  # noqa: BLE001
        log.warning("report_impersonation failed: %s", exc)
