"""Run recorder - persists events to storage."""

from __future__ import annotations

import logging
import time
from typing import Any

logger = logging.getLogger(__name__)


def _utc_ms() -> int:
    return int(time.time() * 1000)


class RunRecorder:
    """Subscribe to events and persist them to a StudioStore-like backend."""

    def __init__(self, *, store: Any):
        self._store = store
        self._seq_by_run: dict[str, int] = {}

    def on_event(self, event: Any) -> None:
        """Event handler (sync) safe to attach via events.on_all."""
        try:
            from persistence import RunStatus

            run_id = str(
                getattr(event, "execution_id", None) or getattr(event, "turn_id", None) or ""
            ).strip()
            if not run_id:
                return

            ts_ms = _utc_ms()
            seq = self._seq_by_run.get(run_id, 0) + 1
            self._seq_by_run[run_id] = seq

            if seq == 1:
                self._upsert_summary(run_id=run_id, status=RunStatus.RUNNING, started_at_ms=ts_ms)

            ev_type = str(
                getattr(getattr(event, "type", None), "value", None)
                or getattr(event, "type", "")
                or ""
            )
            node_id = getattr(event, "node_id", None)
            payload = event.model_dump(mode="json") if hasattr(event, "model_dump") else {"event": str(event)}
            payload_dict = payload if isinstance(payload, dict) else {"event": payload}

            self._append_event(
                run_id=run_id,
                seq=seq,
                ts_ms=ts_ms,
                type_=ev_type or "event",
                node_id=str(node_id) if node_id else None,
                payload=payload_dict,
            )

            if ev_type in ("turn_completed", "turn_failed"):
                from persistence import RunStatus

                status = RunStatus.COMPLETED if ev_type == "turn_completed" else RunStatus.FAILED
                err = getattr(event, "error", None) if status == RunStatus.FAILED else None
                self._upsert_summary(
                    run_id=run_id,
                    status=status,
                    finished_at_ms=ts_ms,
                    error=str(err) if err else None,
                )
        except Exception:
            logger.debug("RunRecorder dropped event (non-fatal)", exc_info=True)

    def _upsert_summary(
        self,
        *,
        run_id: str,
        status: Any,
        started_at_ms: int | None = None,
        finished_at_ms: int | None = None,
        error: str | None = None,
    ) -> None:
        try:
            from persistence import StudioRunSummary

            upsert_fn = getattr(self._store, "upsert_run_summary", None)
            if callable(upsert_fn):
                upsert_fn(
                    summary=StudioRunSummary(
                        run_id=run_id,
                        workspace_id=None,
                        doc_id=None,
                        status=status,
                        started_at_ms=started_at_ms,
                        finished_at_ms=finished_at_ms,
                        error=error,
                    )
                )
        except Exception:
            logger.debug("Failed to upsert run", exc_info=True)

    def _append_event(
        self,
        *,
        run_id: str,
        seq: int,
        ts_ms: int,
        type_: str,
        node_id: str | None,
        payload: dict[str, Any],
    ) -> None:
        try:
            from persistence import StudioRunEvent

            append_fn = getattr(self._store, "append_run_event", None)
            if callable(append_fn):
                append_fn(
                    event=StudioRunEvent(
                        run_id=run_id,
                        seq=int(seq),
                        ts_ms=int(ts_ms),
                        type=str(type_),
                        node_id=node_id,
                        payload=dict(payload),
                    )
                )
        except Exception:
            logger.debug("Failed to append run event", exc_info=True)


__all__ = [
    "RunRecorder",
]
