from __future__ import annotations

import time
from typing import Callable

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

from monitoring.metrics import observe_request
from services.metrics import get_metrics_service


class MetricsMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next: Callable[[Request], Response]) -> Response:
        start_time = time.time()
        response = await call_next(request)
        process_time = time.time() - start_time

        observe_request(
            method=request.method,
            endpoint=request.url.path,
            status=response.status_code,
            seconds=process_time,
        )

        # Store in database asynchronously
        background_tasks = getattr(request.state, "background_tasks", None)
        if background_tasks:
            background_tasks.add_task(
                store_request_metric,
                method=request.method,
                endpoint=request.url.path,
                status_code=response.status_code,
                duration_seconds=process_time,
            )

        return response


async def store_request_metric(
    method: str, endpoint: str, status_code: int, duration_seconds: float
) -> None:
    """Store request metric in database."""
    try:
        service = get_metrics_service()
        service.store_metric(
            metric_name="http_request",
            value=duration_seconds,
            labels={"method": method, "endpoint": endpoint,
                    "status": status_code},
            endpoint=endpoint,
            method=method,
            status_code=status_code,
            duration_seconds=duration_seconds,
        )
    except Exception:
        # Log error but don't fail the request
        pass
