"""Metrics export layer -- Prometheus text format, health checks, JSON.

Consumes MetricsCollector data and produces export-ready output.
Stdlib-only (ADR-021).
"""

from __future__ import annotations

import enum
import json
import time
from typing import Any


class MetricsExportFormat(enum.Enum):
    """Supported export formats."""

    PROMETHEUS = "prometheus"
    JSON = "json"


class PrometheusExporter:
    """Export MetricsCollector data as Prometheus text format."""

    def __init__(
        self,
        collector: Any,
        namespace: str = "orxaq",
    ) -> None:
        self._collector = collector
        self._ns = namespace

    def _line(
        self,
        name: str,
        value: float,
        help_text: str,
        metric_type: str = "gauge",
        labels: dict[str, str] | None = None,
    ) -> list[str]:
        """Build HELP/TYPE/value lines for one metric."""
        fqn = f"{self._ns}_{name}"
        lines = [
            f"# HELP {fqn} {help_text}",
            f"# TYPE {fqn} {metric_type}",
        ]
        if labels:
            label_str = ",".join(f'{k}="{v}"' for k, v in sorted(labels.items()))
            lines.append(f"{fqn}{{{label_str}}} {value}")
        else:
            lines.append(f"{fqn} {value}")
        return lines

    def export(self) -> str:
        """Render all metrics as Prometheus text exposition."""
        c = self._collector
        snapshot = c.dashboard_snapshot()
        lines: list[str] = []

        # Counters
        lines += self._line(
            "tasks_total",
            snapshot["total_tasks"],
            "Total tasks processed",
            "counter",
        )
        lines += self._line(
            "tasks_completed_total",
            snapshot["completed_tasks"],
            "Total tasks completed successfully",
            "counter",
        )
        lines += self._line(
            "tasks_failed_total",
            snapshot["failed_tasks"],
            "Total tasks failed",
            "counter",
        )

        # Gauges
        lines += self._line(
            "error_rate",
            snapshot["error_rate"],
            "Current error rate",
        )
        lines += self._line(
            "cost_usd_total",
            snapshot["total_cost_usd"],
            "Total cost in USD",
            "counter",
        )
        lines += self._line(
            "tasks_per_minute",
            snapshot["tasks_per_minute"],
            "Current throughput in tasks per minute",
        )
        lines += self._line(
            "uptime_seconds",
            snapshot["uptime_seconds"],
            "Collector uptime in seconds",
        )

        # Per-provider metrics
        for _name, pstats in sorted(snapshot["providers"].items()):
            labels = {"provider": pstats["name"]}
            lines += self._line(
                "provider_latency_avg_ms",
                pstats["avg_latency_ms"],
                "Average provider latency in ms",
                labels=labels,
            )
            lines += self._line(
                "provider_latency_p95_ms",
                pstats["p95_latency_ms"],
                "P95 provider latency in ms",
                labels=labels,
            )
            lines += self._line(
                "provider_success_rate",
                pstats["success_rate"],
                "Provider success rate",
                labels=labels,
            )
            lines += self._line(
                "provider_tasks_total",
                pstats["total_tasks"],
                "Total tasks for provider",
                "counter",
                labels=labels,
            )
            lines += self._line(
                "provider_cost_usd",
                pstats["total_cost_usd"],
                "Total cost for provider in USD",
                "counter",
                labels=labels,
            )

        return "\n".join(lines) + "\n"


class HealthCheck:
    """System health aggregation."""

    def __init__(self, collector: Any) -> None:
        self._collector = collector
        self._start_time = time.time()

    def check(self) -> dict:
        """Return health status dict.

        Keys: status (healthy/degraded/unhealthy),
        checks (subsystem statuses), uptime_seconds.
        """
        c = self._collector
        snapshot = c.dashboard_snapshot()
        error_rate = snapshot["error_rate"]
        total_tasks = snapshot["total_tasks"]
        providers = snapshot["providers"]

        checks: dict[str, str] = {}

        # Metrics collector check
        if total_tasks > 0 or snapshot["uptime_seconds"] < 60:
            checks["metrics_collector"] = "ok"
        else:
            checks["metrics_collector"] = "warning"

        # Error rate check
        if error_rate > 0.5:
            checks["error_rate"] = "critical"
        elif error_rate > 0.1:
            checks["error_rate"] = "warning"
        else:
            checks["error_rate"] = "ok"

        # Provider count check
        if len(providers) > 0:
            checks["provider_count"] = "ok"
        else:
            checks["provider_count"] = "warning"

        # Aggregate status
        if any(v == "critical" for v in checks.values()):
            status = "unhealthy"
        elif any(v == "warning" for v in checks.values()):
            status = "degraded"
        else:
            status = "healthy"

        return {
            "status": status,
            "checks": checks,
            "uptime_seconds": round(time.time() - self._start_time, 1),
            "total_tasks": total_tasks,
            "error_rate": error_rate,
            "provider_count": len(providers),
        }


def export_metrics(
    collector: Any,
    fmt: MetricsExportFormat,
) -> str:
    """Export metrics in the given format."""
    if fmt == MetricsExportFormat.PROMETHEUS:
        return PrometheusExporter(collector).export()
    if fmt == MetricsExportFormat.JSON:
        snapshot = collector.dashboard_snapshot()  # type: ignore[attr-defined]
        return json.dumps(snapshot, indent=2, default=str)
    msg = f"Unsupported format: {fmt}"
    raise ValueError(msg)
