"""View As — render Scout as another user.

The drop-in enforces the guards (server-side authorization, rank, nesting,
per-request re-verification); Scout's policy lives in `services/view_as.py`.
The middleware blocks every mutation while impersonating read-only, so these
routes plus `/api/me`'s fields are the entire integration surface.
"""

from fastapi import APIRouter, Depends, HTTPException, Request, status

from app.models.account import Account
from app.models.schemas import ViewAsStart, ViewAsTarget
from app.services import view_as as service
from app.services.authz import current_account, real_username

router = APIRouter(prefix="/api/view-as", tags=["view-as"])


def _real(request: Request) -> str:
    username = real_username(request)
    if not username:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail={"error_code": "NOT_AUTHENTICATED", "summary": "Sign in to continue."},
        )
    return username


@router.get("/targets", response_model=list[ViewAsTarget])
def targets(request: Request, _account: Account = Depends(current_account)) -> list[ViewAsTarget]:
    """Who the REAL caller may view as. Empty for anyone the policy refuses —
    the picker simply has nothing to offer, and start() re-checks regardless."""
    real = _real(request)
    if not service.can_view_as(real, ""):
        return []
    return [ViewAsTarget(**t) for t in service.viewable_targets(real)]


@router.post("/start", status_code=status.HTTP_204_NO_CONTENT)
def start(payload: ViewAsStart, request: Request, _account: Account = Depends(current_account)) -> None:
    _real(request)
    try:
        service.start(request, payload.target.strip().lower(), mode=payload.mode)
    except service.ViewAsError as exc:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail={"error_code": exc.code, "summary": str(exc)},
        ) from exc


@router.post("/stop", status_code=status.HTTP_204_NO_CONTENT)
def stop(request: Request) -> None:
    """Always allowed (and exempt from the read-only write block): ending an
    impersonation must never be refusable."""
    if not real_username(request):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail={"error_code": "NOT_AUTHENTICATED", "summary": "Sign in to continue."},
        )
    service.stop(request)
