"""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 (presence, account URL)
can never fail a request. `bw_auth.py` reads its own config from the process
environment (BW_CLIENT_ID / BW_CLIENT_SECRET / BW_AUTH / BW_APP_DOMAIN via the
container's 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

# Presence is a heartbeat and the SPA polls /api/bw/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 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 account_url(return_to: str | None = None) -> str:
    """The central manage-account page (password change, Google link)."""
    base = get_settings().bw_auth.rstrip("/") + "/account"
    if return_to:
        from urllib.parse import quote

        base += "?return=" + quote(return_to, safe="")
    return base


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