"""Helpdesk observability — metrics, tracing, and structured logging helpers.

Design
------
This module provides lightweight instrumentation for the helpdesk module
without introducing external dependencies. When OpenTelemetry or Prometheus
is wired at the platform level these decorators can be swapped for real
metrics exporters with no change to the calling code.

Usage::

    from simorgh.apps.helpdesk.metrics import instrument

    @instrument("ticket_create")
    def create_ticket(...):
        ...
"""

from __future__ import annotations

import functools
import time
from typing import Any, Callable, TypeVar

import structlog

_log = structlog.get_logger("simorgh.helpdesk.metrics")

F = TypeVar("F", bound=Callable[..., Any])

# ---------------------------------------------------------------------------
# In-process counters (placeholder for Prometheus / OTel future wiring)
# ---------------------------------------------------------------------------

_counters: dict[str, int] = {}


def _inc(name: str, delta: int = 1) -> None:
    _counters[name] = _counters.get(name, 0) + delta


def get_counter(name: str) -> int:
    """Return the current value of a named counter (for tests/debug)."""
    return _counters.get(name, 0)


def reset_counters() -> None:
    """Clear all in-process counters (for test isolation)."""
    _counters.clear()


# ---------------------------------------------------------------------------
# Instrumentation decorator
# ---------------------------------------------------------------------------


def instrument(
    operation: str,
    *,
    track_duration: bool = True,
    track_count: bool = True,
) -> Callable[[F], F]:
    """Decorate a service method with metrics and structured logging.

    Parameters
    ----------
    operation:
        Short label for the operation (e.g. "ticket_create", "transition").
        Used as the counter name and log event suffix.
    track_duration:
        When True, log the wall-clock duration of the call.
    track_count:
        When True, increment an in-process counter.
    """

    def decorator(fn: F) -> F:
        @functools.wraps(fn)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            if track_count:
                _inc(f"helpdesk.{operation}.count")

            if not track_duration:
                return fn(*args, **kwargs)

            started_at = time.monotonic()
            try:
                result = fn(*args, **kwargs)
                elapsed_ms = (time.monotonic() - started_at) * 1000
                _log.debug(
                    f"helpdesk.{operation}.duration",
                    operation=operation,
                    elapsed_ms=round(elapsed_ms, 3),
                    success=True,
                )
                return result
            except Exception:
                elapsed_ms = (time.monotonic() - started_at) * 1000
                _inc(f"helpdesk.{operation}.error")
                _log.warning(
                    f"helpdesk.{operation}.duration",
                    operation=operation,
                    elapsed_ms=round(elapsed_ms, 3),
                    success=False,
                )
                raise

        return wrapper  # type: ignore[return-value]

    return decorator


# ---------------------------------------------------------------------------
# Helpers for structured log enrichment
# ---------------------------------------------------------------------------


def log_ticket_event(
    event: str,
    *,
    ticket_id: int | None = None,
    tenant_id: int | None = None,
    extra: dict | None = None,
) -> None:
    """Emit a structured log event with ticket context."""
    payload: dict[str, Any] = {"event": event}
    if ticket_id is not None:
        payload["ticket_id"] = ticket_id
    if tenant_id is not None:
        payload["tenant_id"] = tenant_id
    if extra:
        payload.update(extra)
    _log.info(f"helpdesk.{event}", **payload)

