"""The single event shape every engine runner emits."""

from dataclasses import dataclass, field
from typing import Any, Optional


@dataclass(frozen=True)
class BridgeEvent:
    type: str
    payload: dict[str, Any] = field(default_factory=dict)

    @classmethod
    def text(cls, text: str) -> "BridgeEvent":
        return cls("text", {"text": text})

    @classmethod
    def tool(
        cls,
        name: str,
        *,
        args: Optional[dict[str, Any]] = None,
        result: Optional[Any] = None,
    ) -> "BridgeEvent":
        """L8: an agent's memory must be written from the event stream, never
        its own self-report — args/result are additive so this can honestly
        carry what a tool call did, not just that one ran. Never a new
        top-level `kind`: an unknown kind fails OPEN to write permissions."""
        payload: dict[str, Any] = {"name": name}
        if args is not None:
            payload["args"] = args
        if result is not None:
            payload["result"] = result
        return cls("tool", payload)

    @classmethod
    def error(cls, message: str) -> "BridgeEvent":
        return cls("error", {"message": message})

    @classmethod
    def status(cls, text: str) -> "BridgeEvent":
        """A short progress line for the live activity card."""
        return cls("status", {"text": text})

    @classmethod
    def cancelled(cls) -> "BridgeEvent":
        """The active run was stopped on the user's request."""
        return cls("cancelled")

    @classmethod
    def session(cls, engine_session_id: str) -> "BridgeEvent":
        """The engine-side session id for this run (claude stream-json init
        session_id / codex thread.started thread_id). The frontend round-trips
        it to the backend so the next run in the conversation can resume."""
        return cls("session", {"engine_session_id": engine_session_id})

    @classmethod
    def done(cls) -> "BridgeEvent":
        return cls("done")

    @classmethod
    def usage(cls, input_tokens: int) -> "BridgeEvent":
        return cls("usage", {"input_tokens": int(input_tokens)})

    def to_dict(self) -> dict[str, Any]:
        return {"type": self.type, **self.payload}
