from __future__ import annotations

from typing import Any, Literal, Union

from pydantic import BaseModel


class QueuedEvent(BaseModel):
    type: Literal["queued"] = "queued"
    node_id: str


class ExecutingEvent(BaseModel):
    type: Literal["executing"] = "executing"
    node_id: str


class ProgressEvent(BaseModel):
    type: Literal["progress"] = "progress"
    node_id: str
    value: float


class ExecutedEvent(BaseModel):
    type: Literal["executed"] = "executed"
    node_id: str
    outputs: dict[str, Any]


class ErrorEvent(BaseModel):
    type: Literal["error"] = "error"
    node_id: str
    error: str
    retryable: bool = False
    # Optional friendly classification (see execution.error_classifier). `error`
    # always holds the raw provider string for debugging; these enrich the UI.
    category: str | None = None
    friendly: str | None = None


class ValidationErrorDetail(BaseModel):
    node_id: str
    port_id: str
    message: str


class ValidationErrorEvent(BaseModel):
    type: Literal["validation_error"] = "validation_error"
    errors: list[ValidationErrorDetail]


class GraphCompleteEvent(BaseModel):
    type: Literal["graph_complete"] = "graph_complete"
    duration: float
    nodes_executed: int


class StreamDeltaEvent(BaseModel):
    type: Literal["stream_delta"] = "stream_delta"
    node_id: str
    delta: str
    accumulated: str


class StreamPartialImageEvent(BaseModel):
    type: Literal["stream_partial_image"] = "stream_partial_image"
    node_id: str
    partial_index: int
    src: str  # server-relative file path
    is_final: bool = False


class StreamPartialSvgEvent(BaseModel):
    type: Literal["stream_partial_svg"] = "stream_partial_svg"
    node_id: str
    partial_index: int
    svg: str  # raw SVG markup; frontend renders inline as a data URI for progressive preview
    is_final: bool = False


ExecutionEvent = Union[
    QueuedEvent,
    ExecutingEvent,
    ProgressEvent,
    ExecutedEvent,
    ErrorEvent,
    ValidationErrorEvent,
    GraphCompleteEvent,
    StreamDeltaEvent,
    StreamPartialImageEvent,
    StreamPartialSvgEvent,
]
