"""Middleware that logs every HTTP request with user context and timing."""
import logging
import time
import uuid

from starlette.middleware.base import BaseHTTPMiddleware
from starlette.requests import Request

logger = logging.getLogger("pedshub.requests")

# Paths to skip logging (noisy or uninteresting)
SKIP_PATHS = {"/api/health", "/favicon.ico", "/robots.txt"}
SKIP_PREFIXES = ("/uploads/",)


class RequestLoggingMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        path = request.url.path

        # Skip noisy paths
        if path in SKIP_PATHS or any(path.startswith(p) for p in SKIP_PREFIXES):
            return await call_next(request)

        request_id = uuid.uuid4().hex[:8]
        request.state.request_id = request_id

        # Extract user from JWT (best-effort, never block)
        user_id = None
        user_email = None
        auth = request.headers.get("authorization", "")
        if auth.startswith("Bearer "):
            try:
                from jose import jwt
                from app.config import settings
                payload = jwt.decode(
                    auth[7:], settings.SECRET_KEY,
                    algorithms=[settings.ALGORITHM],
                    options={"verify_exp": False},
                )
                user_email = payload.get("sub")
            except Exception:
                pass

        start = time.perf_counter()
        response = await call_next(request)
        duration_ms = round((time.perf_counter() - start) * 1000, 1)

        status = response.status_code
        method = request.method
        client_ip = request.client.host if request.client else "-"

        log_data = {
            "request_id": request_id,
            "method": method,
            "path": path,
            "status": status,
            "duration_ms": duration_ms,
            "client_ip": client_ip,
        }
        if user_email:
            log_data["user"] = user_email

        if status >= 500:
            logger.error("%(method)s %(path)s %(status)s %(duration_ms)sms", log_data, extra=log_data)
        elif status >= 400:
            logger.warning("%(method)s %(path)s %(status)s %(duration_ms)sms", log_data, extra=log_data)
        else:
            logger.info("%(method)s %(path)s %(status)s %(duration_ms)sms", log_data, extra=log_data)

        return response
