"""Canonical job envelope for cross-node inference offload."""
from typing import Any, Dict, List, Literal, Optional
from pydantic import BaseModel, Field
import time
import uuid


def _ulid() -> str:
    return str(uuid.uuid4())


class JobRequest(BaseModel):
    job_id: str = Field(default_factory=_ulid)
    trace_id: str = ""
    actor_agent_id: str = ""
    target_agent_id: str = ""
    required_type: Literal["llm", "vision", "stt", "tts", "image", "ocr"] = "llm"
    deadline_ts: int = 0
    idempotency_key: str = ""
    payload: Dict[str, Any] = Field(default_factory=dict)
    hints: Dict[str, Any] = Field(default_factory=dict)

    def remaining_ms(self) -> int:
        if self.deadline_ts <= 0:
            return 30_000
        return max(0, self.deadline_ts - int(time.time() * 1000))

    def effective_idem_key(self) -> str:
        return self.idempotency_key or self.job_id


class JobError(BaseModel):
    code: str = "UNKNOWN"
    message: str = ""


class JobResponse(BaseModel):
    job_id: str = ""
    trace_id: str = ""
    node_id: str = ""
    status: Literal["ok", "busy", "timeout", "error"] = "ok"
    provider: str = ""
    model: str = ""
    latency_ms: int = 0
    result: Optional[Dict[str, Any]] = None
    error: Optional[JobError] = None
    cached: bool = False
