"""Lightweight conversion tracer for template generation diagnostics.

Borrowed from svg2ooxml's ConversionTracer pattern:
- Records stage events during processing
- Zero overhead when tracer is None (callers check `if tracer:`)
- Produces structured ConversionReport for debugging
"""

from __future__ import annotations

import time
from collections import defaultdict
from dataclasses import dataclass, field


@dataclass(frozen=True, slots=True)
class StageEvent:
    """A single recorded event during conversion."""

    stage: str
    action: str
    elapsed_ms: float
    metadata: dict[str, object] = field(default_factory=dict)


@dataclass
class ConversionReport:
    """Aggregated report of all conversion events."""

    events: list[StageEvent] = field(default_factory=list)
    total_ms: float = 0.0

    def to_dict(self) -> dict[str, object]:
        """Serialize to a plain dict for JSON export."""
        stages: dict[str, list[dict[str, object]]] = defaultdict(list)
        for e in self.events:
            entry: dict[str, object] = {
                "action": e.action,
                "elapsed_ms": round(e.elapsed_ms, 2),
            }
            if e.metadata:
                entry["metadata"] = e.metadata
            stages[e.stage].append(entry)
        return {
            "total_ms": round(self.total_ms, 2),
            "stages": dict(stages),
        }


class ConversionTracer:
    """Record conversion events for diagnostic reporting.

    Usage:
        tracer = ConversionTracer()
        with tracer.stage("ir_build"):
            tracer.record("ir_build", "resolve_tokens", {"count": 42})
            ...
        report = tracer.report()

    When not needed, pass None and callers skip tracing:
        if tracer:
            tracer.record(...)
    """

    def __init__(self) -> None:
        self._events: list[StageEvent] = []
        self._start_time = time.monotonic()
        self._stage_start: float | None = None
        self._current_stage: str | None = None

    def record(
        self,
        stage: str,
        action: str,
        metadata: dict[str, object] | None = None,
    ) -> None:
        """Record a single event.

        Args:
            stage: Pipeline stage (e.g. 'ir_build', 'emitter', 'packaging')
            action: Specific action (e.g. 'resolve_tokens', 'customize_theme')
            metadata: Optional key-value data for diagnostics
        """
        elapsed = (time.monotonic() - self._start_time) * 1000
        self._events.append(
            StageEvent(
                stage=stage,
                action=action,
                elapsed_ms=elapsed,
                metadata=metadata or {},
            )
        )

    def stage(self, name: str) -> _StageContext:
        """Context manager that records stage start/end timing.

        Usage:
            with tracer.stage("packaging"):
                ...
        """
        return _StageContext(self, name)

    def report(self) -> ConversionReport:
        """Build the final conversion report."""
        total = (time.monotonic() - self._start_time) * 1000
        return ConversionReport(events=list(self._events), total_ms=total)


class _StageContext:
    """Context manager for stage timing."""

    def __init__(self, tracer: ConversionTracer, name: str) -> None:
        self._tracer = tracer
        self._name = name
        self._start: float = 0.0

    def __enter__(self) -> _StageContext:
        self._start = time.monotonic()
        return self

    def __exit__(self, *_exc: object) -> None:
        elapsed = (time.monotonic() - self._start) * 1000
        self._tracer.record(self._name, "completed", {"duration_ms": round(elapsed, 2)})
