"""Global error handling middleware.

Catches unhandled exceptions in API routes, logs them to both
Python logging and the persistent ErrorLogger, and returns
consistent JSON error responses.
"""

from __future__ import annotations

import logging
import time

from fastapi import Request, Response
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware

log = logging.getLogger(__name__)


class ErrorMiddleware(BaseHTTPMiddleware):
    """Catches unhandled exceptions and logs them persistently."""

    async def dispatch(self, request: Request, call_next) -> Response:
        start = time.time()
        try:
            response = await call_next(request)
        except Exception as exc:
            duration_ms = int((time.time() - start) * 1000)
            path = request.url.path
            method = request.method

            # Log to Python logger (→ console + file)
            log.error(
                "Unhandled %s %s → %s: %s",
                method, path, type(exc).__name__, exc,
                exc_info=True,
                extra={
                    "method": method,
                    "path": path,
                    "status_code": 500,
                    "duration_ms": duration_ms,
                },
            )

            # Log to persistent SQLite error log
            error_logger = getattr(request.app.state, "error_logger", None)
            if error_logger:
                try:
                    await error_logger.log_exception(
                        exc,
                        source=f"api:{path}",
                        request_method=method,
                        request_path=path,
                        status_code=500,
                    )
                except Exception:
                    log.debug("Failed to persist error log", exc_info=True)

            return JSONResponse(
                status_code=500,
                content={"detail": "Internal server error"},
            )

        # Log slow requests (>5s) as warnings
        duration_ms = int((time.time() - start) * 1000)
        if duration_ms > 5000 and request.url.path.startswith("/api/"):
            log.warning(
                "Slow request: %s %s took %dms (status %d)",
                request.method, request.url.path, duration_ms,
                response.status_code,
                extra={
                    "method": request.method,
                    "path": request.url.path,
                    "status_code": response.status_code,
                    "duration_ms": duration_ms,
                },
            )

        # Log 5xx responses that didn't throw (e.g., HTTPException(500))
        if response.status_code >= 500:
            error_logger = getattr(request.app.state, "error_logger", None)
            if error_logger:
                try:
                    await error_logger.log_error(
                        message=f"HTTP {response.status_code} on {request.method} {request.url.path}",
                        source=f"api:{request.url.path}",
                        request_method=request.method,
                        request_path=request.url.path,
                        status_code=response.status_code,
                    )
                except Exception:
                    pass

        return response
