"""Optional FastAPI-compat error rendering.

DRF renders a validation error as HTTP **400** with a `{field: [msgs]}` body; FastAPI/pydantic
renders it as HTTP **422** with `{"detail": [{"loc", "msg", "type"}]}`. A service migrating FROM
FastAPI that must preserve that wire shape byte-for-byte can opt in with `ANDREA_FASTAPI_COMPAT_422=1`
(a settings flag). OFF by default → DRF's standard 400 (the right default; most internal services do
not care, and no client should key on 422 — see #186). A useful option to HAVE, not a default.

Wired as the DRF EXCEPTION_HANDLER by andrea_svc_web.settings; when the flag is off this is a
transparent pass-through to DRF's default handler.
"""
from django.conf import settings
from rest_framework.exceptions import ValidationError
from rest_framework.views import exception_handler as _drf_default_handler


def _flatten(detail, loc):
    """DRF ValidationError.detail (nested dict/list of messages) → FastAPI's flat
    [{"loc": [...], "msg": ..., "type": ...}] list."""
    out = []
    if isinstance(detail, dict):
        for key, value in detail.items():
            out.extend(_flatten(value, loc + [str(key)]))
    elif isinstance(detail, (list, tuple)):
        # a flat list of messages for this loc, OR a list of nested structures
        if detail and all(not isinstance(i, (dict, list, tuple)) for i in detail):
            for msg in detail:
                out.append({"loc": loc, "msg": str(msg), "type": getattr(msg, "code", "") or "value_error"})
        else:
            for idx, item in enumerate(detail):
                out.extend(_flatten(item, loc + [idx]))
    else:
        out.append({"loc": loc, "msg": str(detail), "type": getattr(detail, "code", "") or "value_error"})
    return out


def fastapi_compat_exception_handler(exc, context):
    """DRF EXCEPTION_HANDLER. Identical to DRF's default UNLESS settings.ANDREA_FASTAPI_COMPAT_422 is
    true, in which case a ValidationError is re-rendered as HTTP 422 in FastAPI's `detail` shape."""
    response = _drf_default_handler(exc, context)
    if (response is not None
            and getattr(settings, "ANDREA_FASTAPI_COMPAT_422", False)
            and isinstance(exc, ValidationError)):
        response.data = {"detail": _flatten(exc.detail, ["body"])}
        response.status_code = 422
    return response
