"""
HTTP request/response metrics middleware

Per v1.1.2 Phase 1 and developer Q&A IQ2:
- Times all HTTP requests
- Generates request IDs for tracking (IQ2)
- Records status codes, methods, routes
- Tracks request and response sizes
- Adds X-Request-ID header to all responses (not just debug mode)

Example usage:
    >>> from starpunk.monitoring.http import setup_http_metrics
    >>> app = Flask(__name__)
    >>> setup_http_metrics(app)
"""

import time
import uuid
from flask import g, request, Flask
from typing import Any

from starpunk.monitoring.metrics import record_metric


def setup_http_metrics(app: Flask) -> None:
    """
    Setup HTTP metrics collection for Flask app

    Per IQ2: Generates request IDs and adds X-Request-ID header in all modes

    Args:
        app: Flask application instance
    """

    @app.before_request
    def start_request_metrics():
        """
        Initialize request metrics tracking

        Per IQ2: Generate UUID request ID and store in g
        """
        # Generate request ID (IQ2: in all modes, not just debug)
        g.request_id = str(uuid.uuid4())

        # Store request start time and metadata
        g.request_start_time = time.perf_counter()
        g.request_metadata = {
            'method': request.method,
            'endpoint': request.endpoint or 'unknown',
            'path': request.path,
            'content_length': request.content_length or 0,
        }

    @app.after_request
    def record_response_metrics(response):
        """
        Record HTTP response metrics

        Args:
            response: Flask response object

        Returns:
            Modified response with X-Request-ID header
        """
        # Skip if metrics not initialized (shouldn't happen in normal flow)
        if not hasattr(g, 'request_start_time'):
            return response

        # Calculate request duration
        duration_sec = time.perf_counter() - g.request_start_time
        duration_ms = duration_sec * 1000

        # Get response size
        response_size = 0
        if response.data:
            response_size = len(response.data)
        elif hasattr(response, 'content_length') and response.content_length:
            response_size = response.content_length

        # Build metadata
        metadata = {
            **g.request_metadata,
            'status_code': response.status_code,
            'response_size': response_size,
        }

        # Record metric
        operation_name = f"{g.request_metadata['method']} {g.request_metadata['endpoint']}"
        record_metric(
            'http',
            operation_name,
            duration_ms,
            metadata
        )

        # Add request ID header (IQ2: in all modes)
        response.headers['X-Request-ID'] = g.request_id

        return response

    @app.teardown_request
    def record_error_metrics(error=None):
        """
        Record metrics for requests that result in errors

        Args:
            error: Exception if request failed
        """
        if error and hasattr(g, 'request_start_time'):
            duration_ms = (time.perf_counter() - g.request_start_time) * 1000

            metadata = {
                **g.request_metadata,
                'error': str(error),
                'error_type': type(error).__name__,
            }

            operation_name = f"{g.request_metadata['method']} {g.request_metadata['endpoint']} ERROR"
            record_metric(
                'http',
                operation_name,
                duration_ms,
                metadata,
                force=True  # Always record errors
            )
