"""
cortex/api/middleware.py — Request logging middleware for the Cortex HTTP API (#182).
"""
from __future__ import annotations

import logging
import time
from typing import Any, Callable, List, Optional, Tuple

logger = logging.getLogger(__name__)

_PATH_MAP: List[Tuple[str, Optional[str]]] = [
    ("/api/v1/health", None),
    ("/api/v1/requests", None),
    ("/api/v1/retrieve/explain", "retrieve"),
    ("/api/v1/retrieve", "retrieve"),
    ("/api/v1/remember", "add"),
    ("/api/v1/memories/search", "search"),
    ("/api/v1/memories", "forget"),
    ("/api/v1/cornerstones", "cornerstones"),
    ("/api/v1/brain-graph", "brain_graph"),
    ("/api/v1/session", "session"),
    ("/api/v1/dream", "dream"),
    ("/api/v1/entities", "entities"),
    ("/api/v1/feedback", "feedback"),
    ("/api/v1/stats", "stats"),
    ("/api/v1/admin", "admin"),
]


def _resolve_request_type(path: str) -> Optional[str]:
    """Return the request_type for *path*, or None to skip logging."""
    for prefix, rtype in _PATH_MAP:
        if path == prefix or path.startswith(prefix + "/") or path.startswith(prefix + "?"):
            return rtype
    return "other"


try:
    from starlette.middleware.base import BaseHTTPMiddleware
    from starlette.requests import Request
    from starlette.responses import Response

    class RequestLogMiddleware(BaseHTTPMiddleware):
        """Log every non-skipped HTTP request to the request_log table."""

        def __init__(self, app: Any, *, storage: Any, owner_id: str = "default") -> None:
            super().__init__(app)
            self._storage = storage
            self._owner_id = owner_id

        async def dispatch(self, request: Request, call_next: Callable) -> Response:
            path = request.url.path
            request_type = _resolve_request_type(path)

            if request_type is None:
                return await call_next(request)

            t0 = time.monotonic()
            response: Response = await call_next(request)
            latency_ms = int((time.monotonic() - t0) * 1000)

            status_str = "success" if response.status_code < 400 else "error"

            try:
                storage = self._storage
                if storage is not None and hasattr(storage, "log_request"):
                    await storage.log_request(
                        owner_id=self._owner_id,
                        request_type=request_type,
                        latency_ms=latency_ms,
                        status=status_str,
                        response_summary=str(response.status_code),
                    )
            except Exception as exc:
                logger.warning("RequestLogMiddleware: log_request failed: %s", exc)

            return response

except ImportError:
    class RequestLogMiddleware:  # type: ignore[no-redef]
        def __init__(self, app: Any, **kwargs: Any) -> None:
            self.app = app
        async def __call__(self, scope: Any, receive: Any, send: Any) -> None:
            await self.app(scope, receive, send)
