"""
Event type definitions for KivotClient.

Numeric event types match the protobuf EventType enum in
core/proto/events/v1/events.proto and the Go constants in
core/e2e/framework/event_types.go.
"""

from dataclasses import dataclass, field
from enum import IntEnum
from typing import Any, Dict


class EventType(IntEnum):
    """Numeric event types matching the protobuf EventType enum."""

    # Run lifecycle (1-99)
    RUN_CREATED = 1
    RUN_STARTED = 2
    RUN_COMPLETED = 3
    RUN_FAILED = 4
    RUN_CANCELLED = 5

    # Step lifecycle (100-199)
    STEP_STARTED = 100
    STEP_COMPLETED = 101
    STEP_FAILED = 102

    # Model/LLM events (200-299)
    MODEL_START = 200
    MODEL_DELTA = 201
    MODEL_REASONING = 202
    MODEL_END = 203
    MODEL_FAILED = 204

    # Tool events (300-399)
    TOOL_CALL_START = 300
    TOOL_CALL_DELTA = 301
    TOOL_RESULT = 302
    TOOL_FAILED = 303

    # Message/Output events (400-499)
    MESSAGE_CREATED = 400
    OUTPUT_FINAL = 401

    # Artifact events (900-999)
    ARTIFACT_CREATED = 900


TERMINAL_EVENT_TYPES = frozenset(
    {
        EventType.RUN_COMPLETED,
        EventType.RUN_FAILED,
        EventType.RUN_CANCELLED,
    }
)

# Demo sequence types matching Go DemoSequenceTypes.
DEMO_SEQUENCE_TYPES = [
    EventType.RUN_CREATED,
    EventType.RUN_STARTED,
    EventType.MODEL_DELTA,
    EventType.MODEL_DELTA,
    EventType.MODEL_DELTA,
    EventType.MODEL_DELTA,
    EventType.MODEL_DELTA,
    EventType.MESSAGE_CREATED,
    EventType.RUN_COMPLETED,
]


@dataclass
class StreamEvent:
    """A single event from the WebSocket stream."""

    cursor: int
    run_id: str
    event_id: str
    seq: int
    type: int
    type_name: str
    payload: Dict[str, Any]
    timestamp: str
    step_id: str = ""
    author: str = ""
    trace_id: str = ""
    agent_id: str = ""
    raw: Dict[str, Any] = field(default_factory=dict)

    @property
    def is_terminal(self) -> bool:
        """True if this event ends the run (completed, failed, or cancelled)."""
        return self.type in TERMINAL_EVENT_TYPES

    @property
    def is_model_delta(self) -> bool:
        """True if this is a streaming model delta event."""
        return self.type == EventType.MODEL_DELTA

    @property
    def content(self) -> str:
        """Extract text content from payload (for MODEL_DELTA, MESSAGE_CREATED)."""
        return self.payload.get("content", "")
