from __future__ import annotations

from typing import Dict, List, Tuple

try:
    from prometheus_client import Counter as _PromCounter
    from prometheus_client import generate_latest as _prom_generate_latest
    from prometheus_client import CONTENT_TYPE_LATEST as _PROM_CONTENT_TYPE
    _PROM_OK = True
except Exception:
    _PROM_OK = False


if _PROM_OK:
    # Total send requests, labeled by routed node_id
    SOFIIA_SEND_REQUESTS_TOTAL = _PromCounter(
        "sofiia_send_requests_total",
        "Total number of send requests processed by sofiia-console",
        ["node_id"],
    )

    # Total idempotency replays (same response served again)
    SOFIIA_IDEMPOTENCY_REPLAYS_TOTAL = _PromCounter(
        "sofiia_idempotency_replays_total",
        "Total number of idempotency replays served from cache",
    )

    # Total cursor pagination requests
    SOFIIA_CURSOR_REQUESTS_TOTAL = _PromCounter(
        "sofiia_cursor_requests_total",
        "Total number of cursor pagination requests",
        ["resource"],
    )

    def render_metrics() -> Tuple[bytes, str]:
        return _prom_generate_latest(), _PROM_CONTENT_TYPE

else:
    class _FallbackCounterChild:
        def __init__(self, parent: "_FallbackCounter", key: Tuple[str, ...]):
            self._parent = parent
            self._key = key

        def inc(self, amount: float = 1.0) -> None:
            self._parent._values[self._key] = self._parent._values.get(self._key, 0.0) + float(amount)

    class _FallbackCounter:
        def __init__(self, name: str, doc: str, labelnames: List[str] | Tuple[str, ...] | None = None):
            self.name = name
            self.doc = doc
            self.labelnames = tuple(labelnames or [])
            self._values: Dict[Tuple[str, ...], float] = {}

        def labels(self, **kwargs: str) -> _FallbackCounterChild:
            key = tuple(str(kwargs.get(lbl, "")) for lbl in self.labelnames)
            if key not in self._values:
                self._values[key] = 0.0
            return _FallbackCounterChild(self, key)

        def inc(self, amount: float = 1.0) -> None:
            key = tuple()
            self._values[key] = self._values.get(key, 0.0) + float(amount)

        def _render(self) -> List[str]:
            out = [f"# HELP {self.name} {self.doc}", f"# TYPE {self.name} counter"]
            if not self._values:
                if self.labelnames:
                    out.append(f"{self.name}{{}} 0.0")
                else:
                    out.append(f"{self.name} 0.0")
                return out
            for key, value in self._values.items():
                if self.labelnames:
                    labels = ",".join(
                        f'{lname}="{lval}"' for lname, lval in zip(self.labelnames, key)
                    )
                    out.append(f"{self.name}{{{labels}}} {value}")
                else:
                    out.append(f"{self.name} {value}")
            return out

    SOFIIA_SEND_REQUESTS_TOTAL = _FallbackCounter(
        "sofiia_send_requests_total",
        "Total number of send requests processed by sofiia-console",
        ["node_id"],
    )
    SOFIIA_IDEMPOTENCY_REPLAYS_TOTAL = _FallbackCounter(
        "sofiia_idempotency_replays_total",
        "Total number of idempotency replays served from cache",
    )
    SOFIIA_CURSOR_REQUESTS_TOTAL = _FallbackCounter(
        "sofiia_cursor_requests_total",
        "Total number of cursor pagination requests",
        ["resource"],
    )

    _ALL = [
        SOFIIA_SEND_REQUESTS_TOTAL,
        SOFIIA_IDEMPOTENCY_REPLAYS_TOTAL,
        SOFIIA_CURSOR_REQUESTS_TOTAL,
    ]

    def render_metrics() -> Tuple[bytes, str]:
        lines: List[str] = []
        for c in _ALL:
            lines.extend(c._render())
        text = "\n".join(lines) + "\n"
        return text.encode("utf-8"), "text/plain; version=0.0.4; charset=utf-8"

