"""View-As policy + wiring over the vendored `bw_view_as` drop-in.

The drop-in owns the mechanism and every guard (server-side authorization on
start, per-request re-authorization, the no-escalation rank check, nesting
refusal). This module owns only POLICY — who may impersonate whom — plus the
central-oversight reporting glue.

The rule the rest of the app relies on: **data and permissions follow the
EFFECTIVE user; identity and audit follow the REAL one.** `identity.optional_user`
returns the effective username (this module's `verify_and_effective` runs first,
fail-closed), and the middleware blocks writes in read-only mode, so no route has
to remember either.
"""

import logging

from starlette.requests import Request

from app import accounts
from app import bw_accounts as bwa
from app import bw_auth, bw_view_as
from app.config import get_settings

log = logging.getLogger(__name__)

ViewAsError = bw_view_as.ViewAsError

# Rank derives from the permissions a level holds (never its NAME — levels are
# editable data, so a name-keyed rank would fall to zero for a custom level and
# be refused against everyone). The kit builds this from PERMISSION_INFO weights.
rank_of = bw_view_as.permission_weighted_rank_of(bwa)


def can_view_as(real: str, target: str) -> bool:
    """The owner always may; otherwise a level holding `accounts.view_as` may (the
    rank guard in the drop-in still limits WHICH targets)."""
    return accounts.is_owner(real) or accounts.app_can(real, bwa.PERM_ACCOUNTS_VIEW_AS)


def target_valid(username: str) -> bool:
    """A target must be an active member, so a deleted/deactivated account can't be
    impersonated and any live impersonation of them auto-stops next request."""
    member = bwa.member((username or "").strip().lower())
    return member is not None


def verify_and_effective(request: Request) -> str | None:
    """Re-authorize any active view-as (fail-closed auto-stop), then return the
    EFFECTIVE username. Called by the identity resolver on every request — never
    read the session's user directly for a data decision."""
    session = request.session
    if not session.get("user"):
        return None
    bw_view_as.verify(
        session,
        can_view_as=can_view_as,
        rank_of=rank_of,
        target_valid=target_valid,
        audit=accounts.audit,
    )
    return bw_view_as.effective_username(session)


def start(request: Request, target: str, mode: str = "readonly") -> None:
    """Begin impersonation. `mode='act'` is owner-only — acting writes real rows
    under the target's name; it is a testing tool, not delegation."""
    real = bw_view_as.real_username(request.session)
    if mode == "act" and not accounts.is_owner(real):
        raise ViewAsError("Only the app owner may act as another user.", "FORBIDDEN")
    bw_view_as.start(
        request.session, target,
        can_view_as=can_view_as, rank_of=rank_of, target_valid=target_valid,
        mode=mode, audit=accounts.audit,
    )
    _report(real, bw_view_as.effective_username(request.session), mode=mode, active=True)


def stop(request: Request) -> None:
    session = request.session
    real = bw_view_as.real_username(session)
    target = bw_view_as.effective_username(session)  # capture BEFORE stopping
    was_active = bw_view_as.is_impersonating(session)
    bw_view_as.stop(session, audit=accounts.audit)
    if was_active:
        _report(real, target, active=False)


def _report(real: str, target: str, mode: str = "readonly", active: bool = True) -> None:
    """Owner oversight on the central Live page. Display-only, best-effort; a
    failure here must never break the app."""
    if not get_settings().has_bw_client:
        return
    try:
        bw_auth.report_impersonation(real, target, mode=mode, active=active)
    except Exception as exc:  # noqa: BLE001 - oversight must never break a request
        log.warning("report_impersonation failed: %s", exc)
