"""Backend-neutral worker models."""

from __future__ import annotations

from collections.abc import Callable
from dataclasses import dataclass, field
from typing import Literal

WorkerStatus = Literal["starting", "ready", "idle", "failed"]
WorkerReadyPhase = Literal["cold_start", "waiting", "ready", "failed"]


@dataclass(frozen=True, slots=True)
class WorkerSpec:
    """Stable worker request resolved from worker-routing semantics."""

    worker_key: str
    private_agent_names: frozenset[str] | None = None


@dataclass(frozen=True, slots=True)
class WorkerHandle:
    """Generic worker handle used by the execution layer."""

    worker_id: str
    worker_key: str
    endpoint: str
    auth_token: str | None
    status: WorkerStatus
    backend_name: str
    last_used_at: float
    created_at: float
    last_started_at: float | None = None
    expires_at: float | None = None
    startup_count: int = 0
    failure_count: int = 0
    failure_reason: str | None = None
    debug_metadata: dict[str, str] = field(default_factory=dict)


@dataclass(frozen=True, slots=True)
class WorkerMaintenanceResult:
    """Workers changed by one backend maintenance pass."""

    cleaned: tuple[WorkerHandle, ...]
    reconciled: tuple[WorkerHandle, ...]


@dataclass(frozen=True, slots=True)
class WorkerReadyProgress:
    """Progress event emitted while a worker is warming up."""

    phase: WorkerReadyPhase
    worker_key: str
    backend_name: str
    elapsed_seconds: float
    error: str | None = None


ProgressSink = Callable[[WorkerReadyProgress], None]


def worker_api_endpoint(
    handle: WorkerHandle,
    operation: Literal["execute", "leases", "workers", "cleanup", "save-attachment"],
) -> str:
    """Return the API endpoint for one worker operation."""
    api_root = handle.debug_metadata.get("api_root")
    if api_root is None:
        api_root = handle.endpoint.removesuffix("/execute").rstrip("/")

    if operation == "execute":
        return handle.endpoint
    if operation == "cleanup":
        return f"{api_root}/workers/cleanup"
    return f"{api_root}/{operation}"
