"""HTTP API 的 Pydantic 契约。"""
from __future__ import annotations

from typing import Any, Dict, List, Literal, Optional

from pydantic import BaseModel, Field


class PreflightBody(BaseModel):
    dut_id: Optional[str] = None
    host_id: Optional[str] = None
    firmware_id: Optional[str] = None
    discovered_serial: Optional[str] = None


class CreateRunBody(BaseModel):
    name: str = "固件 A/B 无人值守回归"
    workflow_id: Optional[str] = None
    dut_id: Optional[str] = None
    host_id: Optional[str] = None
    firmware_a_id: Optional[str] = None
    firmware_b_id: Optional[str] = None
    loops: int = Field(default=8, ge=1, le=500)
    inject_failure: bool = True
    execution_mode: Literal["simulated", "agent_dry_run"] = "simulated"
    created_by: str = "console-demo"


class HumanActionBody(BaseModel):
    actor: str = "console-user"
    reason: str = "人工操作"


class AgentRegisterBody(BaseModel):
    host_id: Optional[str] = None
    host_name: Optional[str] = None
    agent_version: str = Field(min_length=1, max_length=32)
    os_family: str = Field(default="linux", min_length=1, max_length=32)
    os_version: Optional[str] = Field(default=None, max_length=128)
    kernel: Optional[str] = Field(default=None, max_length=128)
    cpu: Optional[str] = Field(default=None, max_length=128)
    motherboard: Optional[str] = Field(default=None, max_length=128)
    bios_version: Optional[str] = Field(default=None, max_length=64)
    ip_address: Optional[str] = Field(default=None, max_length=64)
    toolchain: Dict[str, Any] = Field(default_factory=dict)
    labels: Dict[str, Any] = Field(default_factory=dict)


class AgentHeartbeatBody(BaseModel):
    healthy: bool = True
    agent_version: Optional[str] = Field(default=None, max_length=32)
    ip_address: Optional[str] = Field(default=None, max_length=64)
    toolchain: Dict[str, Any] = Field(default_factory=dict)
    device_probe: Dict[str, Any] = Field(default_factory=dict)


class AgentLeaseBody(BaseModel):
    wait_timeout_s: float = Field(default=0.0, ge=0.0, le=20.0)


class AgentStepAttemptBody(BaseModel):
    attempt: int = Field(ge=1)


class AgentStepEvent(BaseModel):
    message: str = Field(min_length=1, max_length=2000)
    severity: Literal["DEBUG", "INFO", "WARNING", "ERROR"] = "INFO"
    payload: Dict[str, Any] = Field(default_factory=dict)


class AgentStepEventsBody(AgentStepAttemptBody):
    events: List[AgentStepEvent] = Field(min_length=1, max_length=100)


class AgentStepCompleteBody(AgentStepAttemptBody):
    status: Literal["SUCCEEDED", "FAILED"]
    exit_code: Optional[int] = None
    error_class: Optional[str] = Field(default=None, max_length=32)
    result: Dict[str, Any] = Field(default_factory=dict)
    log_uri: Optional[str] = Field(default=None, max_length=512)
