"""HTTP server for exposing metrics endpoints."""

from __future__ import annotations

import json
import logging
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
from typing import Any

from oclawma.metrics.collector import MetricsCollector
from oclawma.metrics.formatter import format_prometheus_metrics

logger = logging.getLogger(__name__)


class MetricsHandler(BaseHTTPRequestHandler):
    """HTTP request handler for metrics endpoints."""

    # Class attribute set by MetricsServer
    collector: MetricsCollector | None = None

    def log_message(self, format: str, *args: Any) -> None:
        """Override to use our logger."""
        logger.debug(f"{self.address_string()} - {format % args}")

    def _send_json_response(self, data: dict[str, Any], status: int = 200) -> None:
        """Send a JSON response."""
        self.send_response(status)
        self.send_header("Content-Type", "application/json")
        self.end_headers()
        self.wfile.write(json.dumps(data).encode("utf-8"))

    def _send_text_response(self, text: str, status: int = 200) -> None:
        """Send a plain text response."""
        self.send_response(status)
        self.send_header("Content-Type", "text/plain; charset=utf-8")
        self.end_headers()
        self.wfile.write(text.encode("utf-8"))

    def do_GET(self) -> None:  # noqa: N802
        """Handle GET requests."""
        if self.collector is None:
            self._send_json_response({"error": "Collector not initialized"}, 500)
            return

        path = self.path

        if path == "/metrics":
            # Prometheus format endpoint
            metrics_text = format_prometheus_metrics(self.collector)
            self._send_text_response(metrics_text)

        elif path == "/metrics/json":
            # JSON format endpoint
            snapshot = self.collector.get_metrics_snapshot()
            self._send_json_response(snapshot)

        elif path == "/health":
            # Health check endpoint
            self._send_json_response(
                {
                    "status": "healthy",
                    "collector_ready": self.collector is not None,
                }
            )

        else:
            # 404 for unknown paths
            self._send_json_response({"error": f"Not found: {path}"}, 404)


class MetricsServer:
    """HTTP server for exposing Prometheus-compatible metrics.

    Provides endpoints:
    - /metrics - Prometheus text format
    - /metrics/json - JSON format
    - /health - Health check

    Example:
        >>> from oclawma.metrics import MetricsCollector, MetricsServer
        >>> collector = MetricsCollector()
        >>> server = MetricsServer(collector, host="0.0.0.0", port=9090)
        >>> server.start()
        >>> # Server is now running in background thread
        >>> server.stop()
    """

    def __init__(
        self,
        collector: MetricsCollector,
        host: str = "0.0.0.0",
        port: int = 9090,
    ) -> None:
        """Initialize metrics server.

        Args:
            collector: Metrics collector to expose
            host: Host address to bind to (default: 0.0.0.0)
            port: Port to listen on (default: 9090)
        """
        self.collector = collector
        self.host = host
        self.port = port
        self._server: HTTPServer | None = None
        self._thread: threading.Thread | None = None
        self._lock = threading.Lock()

        # Set collector on handler class
        MetricsHandler.collector = collector

    def start(self) -> None:
        """Start the metrics server in a background thread."""
        with self._lock:
            if self._server is not None:
                logger.warning("Server already running")
                return

            # Create server with port 0 to let OS assign an available port
            # We'll read the actual port afterward
            self._server = HTTPServer((self.host, self.port), MetricsHandler)

            # If port was 0, get the assigned port
            if self.port == 0:
                self.port = self._server.server_address[1]

            self._thread = threading.Thread(target=self._server.serve_forever, daemon=True)
            self._thread.start()

            logger.info(f"Metrics server started on {self.host}:{self.port}")

    def stop(self) -> None:
        """Stop the metrics server."""
        with self._lock:
            if self._server is None:
                return

            logger.info("Stopping metrics server...")
            self._server.shutdown()
            self._server.server_close()
            self._server = None

            if self._thread:
                self._thread.join(timeout=5.0)
                self._thread = None

            logger.info("Metrics server stopped")

    @property
    def is_running(self) -> bool:
        """Check if server is currently running."""
        with self._lock:
            return self._server is not None
