# #region TraceContextMiddlewareModule [C:3] [TYPE Module] [SEMANTICS fastapi, middleware, trace, context, request]
# @BRIEF FastAPI/Starlette middleware that seeds a trace_id for every incoming HTTP request.
#           Optionally extracts X-Trace-ID header for cross-service trace propagation.
# @LAYER Core
# @RELATION DEPENDS_ON -> [CotLoggerModule]
# @RELATION CALLED_BY -> [AppModule]
# @INVARIANT X-Trace-ID header is validated as UUID4 format to prevent log injection / trace poisoning.
# @PRE  FastAPI app instance with Starlette middleware support.
# @POST  Every request gets a trace_id via seed_trace_id(). Existing X-Trace-ID header is
#        preserved and used as the trace_id when present and valid.
# @SIDE_EFFECT  Sets ContextVar _trace_id for the duration of the request.

import uuid

from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request
from starlette.responses import Response
from starlette.types import ASGIApp

from ..cot_logger import seed_trace_id, set_trace_id


# #region TraceContextMiddleware [C:2] [TYPE Class] [SEMANTICS middleware, trace, context, dispatch]
# @BRIEF Starlette BaseHTTPMiddleware that seeds a trace_id per request.
class TraceContextMiddleware(BaseHTTPMiddleware):
    """FastAPI/Starlette middleware that seeds a trace_id for every request.

    If the incoming request carries an ``X-Trace-ID`` header, that value is
    validated as UUID4 and used as the trace_id (enabling cross-service trace
    chaining). Invalid or non-UUID values are ignored and a new UUID4 is
    generated instead.

    Usage::

        from backend.src.core.middleware.trace import TraceContextMiddleware
        app.add_middleware(TraceContextMiddleware)
    """

    # #region TraceContextMiddleware.__init__ [TYPE Function]
    # @BRIEF Standard BaseHTTPMiddleware initialiser.
    def __init__(self, app: ASGIApp) -> None:
        super().__init__(app)

    # #endregion TraceContextMiddleware.__init__

    # #region TraceContextMiddleware.dispatch [C:2] [TYPE Function] [SEMANTICS dispatch, trace, seed, header, call_next]
    # @BRIEF Dispatch handler that seeds trace_id before passing to the next middleware.
    async def dispatch(
        self, request: Request, call_next
    ) -> Response:
        """Intercept every request, seed the trace_id, and forward.

        If the client sent an ``X-Trace-ID`` header with a valid UUID4 value,
        use it; otherwise ``seed_trace_id()`` generates a new UUID4.
        Invalid X-Trace-ID values are silently ignored to prevent log
        injection / trace poisoning (see [SEC:H-5]).

        Args:
            request: The incoming Starlette Request.
            call_next: The next middleware or route handler.

        Returns:
            Response from the downstream handler.
        """
        incoming_trace_id = request.headers.get("X-Trace-ID")
        if incoming_trace_id:
            try:
                uuid.UUID(hex=incoming_trace_id, version=4)
                set_trace_id(incoming_trace_id)
            except (ValueError, AttributeError):
                seed_trace_id()
        else:
            seed_trace_id()

        response = await call_next(request)
        return response

    # #endregion TraceContextMiddleware.dispatch


# #endregion TraceContextMiddleware
# #endregion TraceContextMiddlewareModule
