from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum
from typing import Any, Generic, TypeVar

from .policies import RetryPolicy, RunPolicies

StateT = TypeVar("StateT")

INTERNAL_START_EVENT = "__start__"


def utc_now() -> datetime:
    return datetime.now(timezone.utc)


class RunStatus(str, Enum):
    COMPLETED = "completed"
    STOPPED = "stopped"
    FAILED = "failed"
    LIMIT_REACHED = "limit_reached"
    TIMEOUT = "timeout"


@dataclass(frozen=True)
class RouteSpec:
    event: str
    task: str


@dataclass(frozen=True)
class Event:
    event_id: str
    name: str
    payload: Any = None
    source_task: str | None = None
    source_event_id: str | None = None
    created_at: datetime = field(default_factory=utc_now)
    metadata: dict[str, Any] = field(default_factory=dict)


@dataclass(frozen=True)
class TaskSpec:
    name: str
    method_name: str
    subscriptions: tuple[str, ...]
    retry: RetryPolicy = field(default_factory=RetryPolicy)
    timeout: float | None = None
    failure_event: str | None = None
    input_type: type[Any] | None = None
    metadata: dict[str, Any] = field(default_factory=dict)


@dataclass(frozen=True)
class HistoryRecord:
    record_type: str
    run_id: str
    workflow_name: str
    timestamp: datetime = field(default_factory=utc_now)
    task_name: str | None = None
    event_id: str | None = None
    event_name: str | None = None
    attempt: int | None = None
    details: dict[str, Any] = field(default_factory=dict)


@dataclass(frozen=True)
class WorkflowDescription:
    name: str
    tasks: list[TaskSpec]
    routes: list[RouteSpec]
    run_policies: RunPolicies


@dataclass(frozen=True)
class RunResult(Generic[StateT]):
    run_id: str
    status: RunStatus
    result: Any
    state: StateT
    history: list[HistoryRecord]
    termination_reason: str | None = None
