"""
metrics_exporter.py — Prometheus metrics for llm-guard-kit.

Optional dependency: prometheus-client >= 0.14
Install: pip install llm-guard-kit[prometheus]

If prometheus_client is not installed, all functions become no-ops.
PROMETHEUS_AVAILABLE is False so callers can branch if needed.
Purpose:    Optional dependency (prometheus-client) that exports 6 guard metrics as Prometheus gauges and counters. All functions become no-ops if prometheus-client is not installed.
Exports:    MetricsExporter, PROMETHEUS_AVAILABLE
Added:      v0.29.0
Status:     Stable
"""
from __future__ import annotations

from typing import Optional

try:
    import prometheus_client as _prom
    from prometheus_client import (
        Counter,
        Gauge,
        Histogram,
        generate_latest as _gen_latest,
        CONTENT_TYPE_LATEST,
        CollectorRegistry,
    )

    # Use a dedicated registry so we don't pollute the default one in tests
    _REGISTRY = CollectorRegistry(auto_describe=True)

    _chains_scored = Counter(
        "llmguard_chains_scored_total",
        "Total chains scored, by alert tier",
        ["tier"],
        registry=_REGISTRY,
    )
    _risk_histogram = Histogram(
        "llmguard_risk_score",
        "Distribution of risk scores",
        buckets=[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
        registry=_REGISTRY,
    )
    _alert_threshold_gauge = Gauge(
        "llmguard_alert_threshold",
        "Current alert threshold",
        registry=_REGISTRY,
    )
    _judge_calls = Counter(
        "llmguard_judge_calls_total",
        "Total judge API calls by model",
        ["model"],
        registry=_REGISTRY,
    )
    _feedback_received = Counter(
        "llmguard_feedback_received_total",
        "Human feedback labels received",
        ["label"],
        registry=_REGISTRY,
    )
    _score_latency = Histogram(
        "llmguard_score_latency_seconds",
        "Wall-clock time for score_chain() calls",
        buckets=[0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.0, 5.0],
        registry=_REGISTRY,
    )

    PROMETHEUS_AVAILABLE = True

except (ImportError, TypeError):
    PROMETHEUS_AVAILABLE = False
    _REGISTRY = None
    CONTENT_TYPE_LATEST = "text/plain"


# ── Public API ──────────────────────────────────────────────────────────────────


def record_chain_score(
    risk: float,
    tier: str,
    latency: float,
    judge_model: Optional[str] = None,
    alert_threshold: Optional[float] = None,
) -> None:
    """
    Record metrics for a completed score_chain() call.

    Parameters
    ----------
    risk : float        Final risk score (0–1).
    tier : str          "ALERT", "REVIEW", or "PASS".
    latency : float     Wall-clock seconds for the call.
    judge_model : str   Model used for judge call, if any.
    alert_threshold : float   Current alert threshold (updates gauge if provided).
    """
    if not PROMETHEUS_AVAILABLE:
        return
    _chains_scored.labels(tier=tier).inc()
    _risk_histogram.observe(risk)
    _score_latency.observe(latency)
    if judge_model:
        _judge_calls.labels(model=judge_model).inc()
    if alert_threshold is not None:
        _alert_threshold_gauge.set(alert_threshold)


def record_feedback(label: int) -> None:
    """
    Record a human feedback label.

    Parameters
    ----------
    label : int   0 = correct chain, 1 = incorrect chain.
    """
    if not PROMETHEUS_AVAILABLE:
        return
    _feedback_received.labels(label="incorrect" if label == 1 else "correct").inc()


def generate_latest() -> bytes:
    """
    Return current metrics in Prometheus text format.

    Returns empty bytes if prometheus_client is not installed.
    """
    if not PROMETHEUS_AVAILABLE:
        return b""
    return _gen_latest(_REGISTRY)
