"""Structured errors: one shape the frontend can act on.

Every failure carries a stable machine-readable `error_code` plus a human
message. The frontend switches on the code, never on the prose. Entity IDs are
safe to log; tokens, cookies and secrets never are (coding.md).
"""

from __future__ import annotations

from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse

# --- codes -----------------------------------------------------------------
# Auth / admission
AUTH_NOT_CONFIGURED = "AUTH_NOT_CONFIGURED"
AUTH_SESSION_MISSING = "AUTH_SESSION_MISSING"
AUTH_NOT_INVITED = "AUTH_NOT_INVITED"
AUTH_FORBIDDEN = "AUTH_FORBIDDEN"
# Generic
VALIDATION_FAILED = "VALIDATION_FAILED"
NOT_FOUND = "NOT_FOUND"
INTERNAL_ERROR = "INTERNAL_ERROR"


def error_response(code: str, message: str, status: int) -> JSONResponse:
    return JSONResponse(
        status_code=status, content={"error_code": code, "message": message}
    )


def install_handlers(app: FastAPI) -> None:
    @app.exception_handler(RequestValidationError)
    async def _validation(_request: Request, exc: RequestValidationError):
        return JSONResponse(
            status_code=422,
            content={
                "error_code": VALIDATION_FAILED,
                "message": "request validation failed",
                "details": exc.errors(),
            },
        )
