"""HTTP middleware: bind a correlation id and log each request."""

import time
import uuid

from starlette.types import ASGIApp, Message, Receive, Scope, Send

from app.core.logging import correlation_id, get_logger

log = get_logger("http")

_HEADER = "x-correlation-id"


class CorrelationIdMiddleware:
    """Pure-ASGI middleware: reuse inbound ``X-Correlation-Id`` or mint one,
    bind it for downstream logs, echo it back, and log request completion."""

    def __init__(self, app: ASGIApp) -> None:
        self.app = app

    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
        if scope["type"] != "http":
            await self.app(scope, receive, send)
            return

        headers = dict(scope["headers"])
        inbound = headers.get(_HEADER.encode())
        cid = inbound.decode() if inbound else uuid.uuid4().hex
        token = correlation_id.set(cid)
        started = time.perf_counter()
        status_code = 0

        async def send_wrapper(message: Message) -> None:
            nonlocal status_code
            if message["type"] == "http.response.start":
                status_code = message["status"]
                message.setdefault("headers", [])
                message["headers"].append((_HEADER.encode(), cid.encode()))
            await send(message)

        try:
            await self.app(scope, receive, send_wrapper)
        finally:
            log.info(
                "request",
                method=scope["method"],
                path=scope["path"],
                status=status_code,
                duration_ms=round((time.perf_counter() - started) * 1000, 1),
            )
            correlation_id.reset(token)
