"""Auth guards for ``/internal/*``.

Active layer: Bearer token, presented by the operator's CLI and
matched against the value in the secrets dir. Token rotation =
update the file, restart the container.

:func:`require_localhost` is preserved but unused by default — it
fights the Docker bridge network model (the container sees the
gateway IP, not 127.0.0.1, regardless of where traffic originated).
Re-enable it only if the API runs in ``network_mode: host``.
"""

from __future__ import annotations

import hmac
from typing import Optional

from fastapi import HTTPException, Request, status

from app.config import get_settings


def require_localhost(request: Request) -> None:
    """Reject the request unless the connecting peer is loopback.

    ``request.client.host`` reflects the actual TCP peer (the nginx
    upstream connecting from 127.0.0.1) when ``proxy_set_header`` is
    used appropriately. We deliberately do NOT trust
    ``X-Forwarded-For`` here — we want the raw peer.
    """
    peer = request.client.host if request.client else None
    if peer not in {"127.0.0.1", "::1"}:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Not found",
        )


def require_bearer_token(request: Request) -> None:
    """Verify ``Authorization: Bearer <admin_token>``.

    Uses constant-time comparison so timing leaks don't reveal token
    prefixes. The 401 deliberately doesn't echo the supplied token or
    leak whether a token is configured at all — clients should treat
    "no token configured" the same as "wrong token".
    """
    settings = get_settings()
    expected: Optional[str] = settings.resolve_admin_token()
    if not expected:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Server not configured for internal access.",
        )
    auth = request.headers.get("Authorization", "")
    if not auth.startswith("Bearer "):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Bearer token required.",
        )
    presented = auth.removeprefix("Bearer ").strip()
    if not hmac.compare_digest(presented, expected):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid token.",
        )
