"""Audit logging middleware.

Logs every API request with method, path, status code, response time,
and the authenticated user identity (extracted from the JWT when present).
Log lines are structured so they can be ingested by ELK / Loki.
"""

from __future__ import annotations

import time

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


class AuditMiddleware(BaseHTTPMiddleware):
    """Log all API calls. Skips health/docs paths to reduce noise."""

    # Paths that produce no audit log entry.
    _SKIP_PREFIXES = ("/health", "/docs", "/redoc", "/openapi.json")

    async def dispatch(self, request: Request, call_next) -> Response:
        """Intercept the request, call the handler, and log the outcome."""
        path = request.url.path
        if path == "/" or any(path == p or path.startswith(p + "/") for p in self._SKIP_PREFIXES):
            return await call_next(request)

        start = time.perf_counter()
        response = await call_next(request)
        elapsed_ms = int((time.perf_counter() - start) * 1000)

        # Extract user identity from JWT header for structured audit records.
        # The token is not re-validated here — auth dependencies do that upstream.
        user_id = "anonymous"
        username = "anonymous"
        auth_header = request.headers.get("authorization", "")
        if auth_header.startswith("Bearer "):
            try:
                from app.shared.bootstrap import get_jwt_handler
                claims = get_jwt_handler().decode_token(auth_header[7:])
                user_id = claims.user_id
                username = claims.username
            except Exception:
                pass

        logger.info(
            "AUDIT method={} path={} status={} elapsed_ms={} user_id={} username={}",
            request.method,
            path,
            response.status_code,
            elapsed_ms,
            user_id,
            username,
        )
        return response
