"""SSE Event model for the oedix agent framework.

Defines the 16+ event types that are yielded through the pipeline and
optionally persisted to ``action_event`` in history.db.
"""

from __future__ import annotations

import uuid
from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum
from typing import Any, Optional


class EventType(str, Enum):
    """All SSE event types emitted by the oedix pipeline."""

    # Action(thinking)
    THINKING = "thinking"
    DECISION = "decision"
    APPROACH_UPDATE = "approach_update"
    TEXT = "text"

    # Action(tool)
    TOOL_USE = "tool_use"
    TOOL_RESULT = "tool_result"

    # Canvas (real-time visualisation)
    CANVAS = "canvas"
    CANVAS_UPDATE = "canvas_update"

    # Action(planner)
    PLAN = "plan"
    PLAN_UPDATE = "plan_update"

    # Action(organizer)
    CONTEXT_SUMMARY = "context_summary"
    INSTRUCTION_SEARCH = "instruction_search"
    INSTRUCTION_UPDATE = "instruction_update"

    # Action(response)
    RESPONSE = "response"

    # Individual action lifecycle (within ActionSet)
    ACTION_PLAN = "action_plan"
    ACTION_START = "action_start"
    ACTION_COMPLETE = "action_complete"

    # ActionSet lifecycle
    ACTION_SET_START = "action_set_start"
    ACTION_SET_COMPLETE = "action_set_complete"

    # AgentQueue lifecycle
    DONE = "done"
    ERROR = "error"
    HISTORY = "history"


@dataclass
class Event:
    """A single SSE event flowing through the pipeline.

    Attributes:
        type: Event category.
        data: Arbitrary event payload.
        queue_id: Owning AgentQueue ID.
        set_id: Owning ActionSet ID (``None`` for queue-level events).
        action_id: Owning Action ID (``None`` for set/queue-level events).
        timestamp: ISO-8601 timestamp.
        id: Unique event identifier.
    """

    type: EventType
    data: dict[str, Any] = field(default_factory=dict)
    queue_id: Optional[str] = None
    set_id: Optional[str] = None
    action_id: Optional[str] = None
    timestamp: str = field(
        default_factory=lambda: datetime.now(timezone.utc).isoformat()
    )
    id: str = field(default_factory=lambda: uuid.uuid4().hex)

    # ------------------------------------------------------------------
    # Serialisation
    # ------------------------------------------------------------------

    def to_dict(self) -> dict[str, Any]:
        return {
            "id": self.id,
            "type": self.type.value,
            "data": self.data,
            "queue_id": self.queue_id,
            "set_id": self.set_id,
            "action_id": self.action_id,
            "timestamp": self.timestamp,
        }

    def to_sse(self) -> str:
        """Format as a Server-Sent Events data line."""
        import json

        payload = json.dumps(self.to_dict(), ensure_ascii=False)
        return f"data: {payload}\n\n"

    @classmethod
    def from_dict(cls, data: dict) -> Event:
        return cls(
            id=data.get("id", uuid.uuid4().hex),
            type=EventType(data["type"]),
            data=data.get("data", {}),
            queue_id=data.get("queue_id"),
            set_id=data.get("set_id"),
            action_id=data.get("action_id"),
            timestamp=data.get(
                "timestamp", datetime.now(timezone.utc).isoformat()
            ),
        )
