"""
Kuramoto Metrics Logger — Synchronization validation for mesh cognition.

Copyright (c) 2026 SYM.BOT Ltd. Apache 2.0 License.
"""

import json
import time
from dataclasses import dataclass, asdict
from pathlib import Path
from typing import Optional

from .coupler import CouplingDecision


@dataclass
class MetricEntry:
    timestamp: float
    peer_count: int
    h1_l2_distance: float
    h2_l2_distance: float
    order_parameter: float
    effective_alpha: float
    decisions: list[dict]


class KuramotoMetricsLogger:
    """Logs per-inference Kuramoto metrics for offline analysis."""

    def __init__(self, max_entries: int = 10_000):
        self._entries: list[MetricEntry] = []
        self._max_entries = max_entries

    def log(
        self,
        peer_count: int,
        l2_distances: Optional[tuple[float, float]],
        order_parameter: Optional[float],
        effective_alpha: float,
        decisions: dict[str, CouplingDecision],
    ):
        entry = MetricEntry(
            timestamp=time.time(),
            peer_count=peer_count,
            h1_l2_distance=l2_distances[0] if l2_distances else 0.0,
            h2_l2_distance=l2_distances[1] if l2_distances else 0.0,
            order_parameter=order_parameter or 0.0,
            effective_alpha=effective_alpha,
            decisions=[
                {
                    "agent_id": d.agent_id[:8],
                    "drift": round(d.drift, 4),
                    "decision": d.decision.value,
                    "alpha": round(d.alpha, 3),
                    "weight": round(d.weight, 4),
                }
                for d in decisions.values()
            ],
        )
        self._entries.append(entry)
        if len(self._entries) > self._max_entries:
            self._entries = self._entries[-self._max_entries:]

    def export(self, path: str = "kuramoto_metrics.jsonl") -> Path:
        """Export metrics to JSONL file."""
        filepath = Path(path)
        with open(filepath, "w") as f:
            for entry in self._entries:
                f.write(json.dumps(asdict(entry)) + "\n")
        return filepath

    @property
    def entry_count(self) -> int:
        return len(self._entries)

    @property
    def latest(self) -> Optional[MetricEntry]:
        return self._entries[-1] if self._entries else None

    def clear(self):
        self._entries.clear()
