"""Thin wrapper over the BW Auth drop-in.

Everything that talks to id-auth goes through here so the rest of the app never
imports `bw_auth` directly — and so the best-effort calls (access/presence
reporting) can never fail a request.

`bw_auth.py` reads its config from the process environment, not from Settings.
The container gets BW_CLIENT_ID / BW_CLIENT_SECRET / BW_AUTH / BW_APP_DOMAIN via
env_file, which is exactly what it expects.
"""

import logging
import time

from app import bw_auth
from app.config import get_settings

log = logging.getLogger(__name__)

BWAuthError = bw_auth.BWAuthError

# Re-exported so routers can name the cookies without importing bw_auth.
PKCE_COOKIE = bw_auth.PKCE_COOKIE
STATE_COOKIE = bw_auth.STATE_COOKIE
PROBED_COOKIE = bw_auth.PROBED_COOKIE
OPTOUT_COOKIE = bw_auth.OPTOUT_COOKIE

# Presence is a heartbeat, and the SPA polls /api/me. Reporting on every poll
# would put a blocking HTTP call in a hot path, so throttle per user.
_PRESENCE_INTERVAL = 60
_last_presence: dict[str, float] = {}


def lookup_identity(username: str) -> dict:
    """Resolve a BW username to {username, email, first, last}.

    Used when an admin grants access to someone: it both validates that the BW
    account exists and gives the row a real name before that person's first
    sign-in. Raises BWAuthError when the account is unknown or inactive.
    """
    return bw_auth.userinfo(username.strip().lower())


def report_presence(username: str, ip: str | None = None) -> None:
    """Heartbeat so the access console shows this user by name. Throttled,
    fire-and-forget."""
    if not get_settings().has_bw_client:
        return
    now = time.monotonic()
    if now - _last_presence.get(username, 0.0) < _PRESENCE_INTERVAL:
        return
    _last_presence[username] = now
    try:
        bw_auth.report_presence(username, ip=ip)
    except BWAuthError as exc:
        log.warning("report_presence failed for %s: %s", username, exc)


def logout_url() -> str:
    return bw_auth.logout_url()
