"""Schlanke In-Memory-Metriken (Counter + Timer) fuer einen Prozess.

Bewusst ohne externe Dependency. Fuer mehrere Instanzen/Prozesse spaeter durch
einen gemeinsamen Backend (z. B. Prometheus-Exporter) ersetzbar.
"""

import threading
import time
from collections import defaultdict


class Metrics:
    def __init__(self):
        self._lock = threading.Lock()
        self._counters: dict[str, float] = defaultdict(float)
        self._timers: dict[str, list] = defaultdict(lambda: [0.0, 0])  # [sum, count]

    @staticmethod
    def _key(name: str, labels: dict | None) -> str:
        if not labels:
            return name
        rendered = ",".join(f'{k}="{v}"' for k, v in sorted(labels.items()))
        return f"{name}{{{rendered}}}"

    def inc(self, name: str, labels: dict | None = None, value: float = 1.0) -> None:
        with self._lock:
            self._counters[self._key(name, labels)] += value

    def observe(self, name: str, seconds: float, labels: dict | None = None) -> None:
        with self._lock:
            agg = self._timers[self._key(name, labels)]
            agg[0] += seconds
            agg[1] += 1

    def snapshot(self) -> dict:
        with self._lock:
            counters = dict(self._counters)
            timers = {
                key: {
                    "sum": agg[0],
                    "count": agg[1],
                    "avg": (agg[0] / agg[1] if agg[1] else 0.0),
                }
                for key, agg in self._timers.items()
            }
        return {"counters": counters, "timers": timers}

    def prometheus(self) -> str:
        snap = self.snapshot()
        lines = []
        for key, value in sorted(snap["counters"].items()):
            lines.append(f"{key} {value}")
        for key, agg in sorted(snap["timers"].items()):
            base, _, labels = key.partition("{")
            suffix = ("{" + labels) if labels else ""
            lines.append(f"{base}_sum{suffix} {agg['sum']}")
            lines.append(f"{base}_count{suffix} {agg['count']}")
        return "\n".join(lines) + "\n"

    def reset(self) -> None:
        with self._lock:
            self._counters.clear()
            self._timers.clear()


metrics = Metrics()


class timer:
    """Context-Manager: misst die Dauer und schreibt sie als Timer-Beobachtung."""

    def __init__(self, name: str, labels: dict | None = None):
        self.name = name
        self.labels = labels

    def __enter__(self):
        self._start = time.perf_counter()
        return self

    def __exit__(self, *exc):
        metrics.observe(self.name, time.perf_counter() - self._start, self.labels)
        return False
