import uuid
from datetime import datetime
from typing import Literal

from pydantic import AliasChoices, BaseModel, ConfigDict, Field, computed_field


ExecutionState = Literal["manual", "queued", "scheduled", "launching", "paused", "completed", "cancelled"]
LaunchMode = Literal["manual", "queued", "scheduled", "immediate"]
ConcurrencyMode = Literal["sequential", "parallel"]
LaunchRequestStatus = Literal["requested", "accepted", "completed", "cancelled"]


class ExecutionIntentUpdate(BaseModel):
    execution_state: ExecutionState | None = None
    launch_mode: LaunchMode | None = None
    concurrency_mode: ConcurrencyMode | None = None
    queue_rank: int | None = None
    execution_group: str | None = None
    scheduled_for: datetime | None = None


class ExecutionIntentRead(BaseModel):
    workplan_id: uuid.UUID

    @computed_field  # type: ignore[prop-decorator]
    @property
    def workstream_id(self) -> uuid.UUID:
        return self.workplan_id
    execution_state: ExecutionState
    launch_mode: LaunchMode
    concurrency_mode: ConcurrencyMode
    queue_rank: int | None = None
    execution_group: str | None = None
    scheduled_for: datetime | None = None


class WorkplanQueueItem(BaseModel):
    workplan_id: uuid.UUID
    slug: str
    title: str
    status: str
    repo_id: uuid.UUID | None = None
    planning_priority: str | None = None
    planning_order: int | None = None
    execution_state: ExecutionState
    launch_mode: LaunchMode
    concurrency_mode: ConcurrencyMode
    queue_rank: int | None = None
    execution_group: str | None = None
    scheduled_for: datetime | None = None
    eligible: bool
    blocked_by_workplan_ids: list[uuid.UUID] = Field(default_factory=list)

    @computed_field  # type: ignore[prop-decorator]
    @property
    def blocked_by_workstream_ids(self) -> list[uuid.UUID]:
        return self.blocked_by_workplan_ids
    blocked_by_task_ids: list[uuid.UUID] = Field(default_factory=list)
    sort_key: list[str | int] = Field(default_factory=list)


class LaunchRequestCreate(BaseModel):
    workplan_id: uuid.UUID = Field(validation_alias=AliasChoices("workplan_id", "workstream_id"))
    requested_by: str = "dashboard"
    requested_actor: str | None = None
    launch_mode: LaunchMode = "queued"
    concurrency_mode: ConcurrencyMode = "sequential"
    priority: str | None = None
    repo_id: uuid.UUID | None = None
    branch_preference: str | None = None
    immediate_pickup: bool = False
    notes: str | None = None
    request_metadata: dict = Field(default_factory=dict)


class LaunchRequestRead(BaseModel):
    model_config = ConfigDict(from_attributes=True)
    id: uuid.UUID
    workplan_id: uuid.UUID
    requested_by: str
    requested_actor: str | None = None
    launch_mode: LaunchMode

    @computed_field  # type: ignore[prop-decorator]
    @property
    def workstream_id(self) -> uuid.UUID:
        return self.workplan_id
    concurrency_mode: ConcurrencyMode
    priority: str | None = None
    repo_id: uuid.UUID | None = None
    branch_preference: str | None = None
    immediate_pickup: bool
    status: LaunchRequestStatus
    notes: str | None = None
    request_metadata: dict = Field(default_factory=dict)
    created_at: datetime
    updated_at: datetime


class ExecutionSemantics(BaseModel):
    execution_states: dict[str, str]
    launch_modes: dict[str, str]
    concurrency_modes: dict[str, str]
    state_hub_responsibility: list[str]
    activity_core_responsibility: list[str]
