"""
Logging Middleware for Request/Response Tracking
"""
import logging
import time
import uuid
from typing import Callable

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

logger = logging.getLogger(__name__)


class LoggingMiddleware(BaseHTTPMiddleware):
    """
    Middleware to log all HTTP requests with timing and unique request IDs.
    
    Logs:
    - Request ID (UUID4)
    - HTTP method and path
    - Processing time in milliseconds
    - Response status code
    """
    
    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        """Process request and log details"""
        # Generate unique request ID
        request_id = uuid.uuid4()
        start_time = time.perf_counter()
        
        # Add request ID to request state for use in other parts of the app
        request.state.request_id = str(request_id)
        
        try:
            # Process the request
            response = await call_next(request)
            
            # Calculate processing time
            process_time = (time.perf_counter() - start_time) * 1000
            
            # Log successful request
            logger.info(
                f"RequestID={request_id} "
                f"Method={request.method} "
                f"Path={request.url.path} "
                f"CompletedIn={process_time:.2f}ms "
                f"StatusCode={response.status_code}"
            )
            
            return response
            
        except Exception as exc:
            # Calculate processing time for failed requests
            process_time = (time.perf_counter() - start_time) * 1000
            
            # Log failed request
            logger.error(
                f"RequestID={request_id} "
                f"Method={request.method} "
                f"Path={request.url.path} "
                f"CompletedIn={process_time:.2f}ms "
                f"Error={str(exc)}"
            )
            
            # Re-raise the exception to be handled by error handlers
            raise exc


async def logging_middleware_function(request: Request, call_next: Callable) -> Response:
    """
    Functional version of logging src.middleware.
    
    Alternative to class-based middleware for simpler use cases.
    """
    request_id = uuid.uuid4()
    start_time = time.perf_counter()
    
    # Add request ID to request state
    request.state.request_id = str(request_id)
    
    try:
        response = await call_next(request)
        process_time = (time.perf_counter() - start_time) * 1000
        
        logger.info(
            f"RequestID={request_id} "
            f"Method={request.method} "
            f"Path={request.url.path} "
            f"CompletedIn={process_time:.2f}ms "
            f"StatusCode={response.status_code}"
        )
        
        return response
        
    except Exception as exc:
        process_time = (time.perf_counter() - start_time) * 1000
        
        logger.error(
            f"RequestID={request_id} "
            f"Method={request.method} "
            f"Path={request.url.path} "
            f"CompletedIn={process_time:.2f}ms "
            f"Error={str(exc)}"
        )
        
        raise exc
