# backend/app/observability/metrics.py — 경량 Prometheus 메트릭 (의존성 없음)
import threading
from collections import defaultdict


class _Registry:
    def __init__(self):
        self._lock = threading.Lock()
        self.counters: dict[tuple[str, tuple], float] = defaultdict(float)
        self.gauges: dict[tuple[str, tuple], float] = {}
        self.hist_sum: dict[tuple[str, tuple], float] = defaultdict(float)
        self.hist_count: dict[tuple[str, tuple], int] = defaultdict(int)
        self._help: dict[str, str] = {}

    def _key(self, name, labels):
        return (name, tuple(sorted((labels or {}).items())))

    def inc(self, name, amount=1.0, **labels):
        with self._lock:
            self.counters[self._key(name, labels)] += amount

    def set_gauge(self, name, value, **labels):
        with self._lock:
            self.gauges[self._key(name, labels)] = value

    def observe(self, name, value, **labels):
        with self._lock:
            k = self._key(name, labels)
            self.hist_sum[k] += value
            self.hist_count[k] += 1

    def help(self, name, text):
        self._help[name] = text

    def _fmt_labels(self, labels: tuple) -> str:
        if not labels:
            return ""
        inner = ",".join(f'{k}="{v}"' for k, v in labels)
        return "{" + inner + "}"

    def render(self) -> str:
        lines: list[str] = []
        with self._lock:
            for (name, labels), v in sorted(self.counters.items()):
                lines.append(f"{name}_total{self._fmt_labels(labels)} {v}")
            for (name, labels), v in sorted(self.gauges.items()):
                lines.append(f"{name}{self._fmt_labels(labels)} {v}")
            for (name, labels), s in sorted(self.hist_sum.items()):
                lines.append(f"{name}_sum{self._fmt_labels(labels)} {s}")
                lines.append(
                    f"{name}_count{self._fmt_labels(labels)} {self.hist_count[(name, labels)]}"
                )
        return "\n".join(lines) + "\n"


registry = _Registry()


# 핵심 메트릭 헬퍼(운영 런북 §15.2)
def http_request(method: str, path: str, status: int, dur_s: float) -> None:
    registry.inc("ari_http_requests", method=method, status=str(status))
    registry.observe("ari_http_latency_seconds", dur_s, method=method)


def llm_call(outcome: str) -> None:
    registry.inc("ari_llm_calls", outcome=outcome)


def worker_job(job: str, outcome: str) -> None:
    registry.inc("ari_worker_jobs", job=job, outcome=outcome)


def approval(risk: str, status: str) -> None:
    registry.inc("ari_approvals", risk=risk, status=status)


def add_saved_minutes(m: float) -> None:
    registry.inc("ari_saved_minutes", m)


def render() -> str:
    return registry.render()
