"""
Pydantic models for Lovense API requests and responses.
"""

from typing import Any

from pydantic import BaseModel, Field

__all__ = [
    "ToyInfo",
    "GetToysResponse",
    "GetToyNameResponse",
    "CommandResponse",
    "FunctionPayload",
    "PatternPayload",
    "PatternV2Action",
    "PatternV2SetupPayload",
    "PatternV2PlayPayload",
    "PatternV2InitPlayPayload",
    "PatternV2StopPayload",
    "PresetPayload",
    "PositionPayload",
]


class ToyInfo(BaseModel):
    """Single toy info from GetToys response."""

    id: str
    name: str
    status: str | None = None
    version: str | None = None
    battery: int | None = None
    nickName: str | None = None
    shortFunctionNames: list[str] | None = None
    fullFunctionNames: list[str] | None = None

    model_config = {"extra": "allow"}


class GetToysResponse(BaseModel):
    """Response from GetToys command."""

    code: int = 200
    type: str = "OK"
    data: dict[str, Any] | None = None


class GetToyNameResponse(BaseModel):
    """Response from GetToyName command."""

    code: int = 200
    type: str = "OK"
    data: list[str] | None = None


class CommandResponse(BaseModel):
    """Generic command response."""

    code: int = 200
    type: str = "OK"
    data: dict[str, Any] | None = None


# --- Request payloads (for building commands) ---


class FunctionPayload(BaseModel):
    """Payload for Function command."""

    command: str = "Function"
    action: str
    timeSec: float = 0
    apiVer: int = 1
    toy: str | list[str] | None = None
    loopRunningSec: float | None = None
    loopPauseSec: float | None = None
    stopPrevious: int | None = None


class PatternPayload(BaseModel):
    """Payload for Pattern command."""

    command: str = "Pattern"
    rule: str
    strength: str
    timeSec: float = 0
    apiVer: int = 2
    toy: str | list[str] | None = None


class PatternV2Action(BaseModel):
    """Single action for PatternV2 (ts, pos)."""

    ts: int  # timestamp in ms
    pos: int = Field(..., ge=0, le=100)  # position 0-100


class PatternV2SetupPayload(BaseModel):
    """Payload for PatternV2 Setup."""

    command: str = "PatternV2"
    type: str = "Setup"
    actions: list[PatternV2Action]
    apiVer: int = 1


class PatternV2PlayPayload(BaseModel):
    """Payload for PatternV2 Play."""

    command: str = "PatternV2"
    type: str = "Play"
    apiVer: int = 1
    toy: str | list[str] | None = None
    startTime: int | None = None
    offsetTime: int | None = None
    timeMs: float | None = None


class PatternV2InitPlayPayload(BaseModel):
    """Payload for PatternV2 InitPlay (setup + play in one)."""

    command: str = "PatternV2"
    type: str = "InitPlay"
    actions: list[PatternV2Action]
    apiVer: int = 1
    toy: str | list[str] | None = None
    startTime: int | None = None
    offsetTime: int | None = None
    stopPrevious: int = 0


class PatternV2StopPayload(BaseModel):
    """Payload for PatternV2 Stop."""

    command: str = "PatternV2"
    type: str = "Stop"
    apiVer: int = 1
    toy: str | list[str] | None = None


class PresetPayload(BaseModel):
    """Payload for Preset command."""

    command: str = "Preset"
    name: str
    timeSec: float = 0
    apiVer: int = 1
    toy: str | list[str] | None = None


class PositionPayload(BaseModel):
    """Payload for Position command (Solace Pro). Value 0-100 as string."""

    command: str = "Position"
    value: str  # "0" to "100"
    apiVer: int = 1
    toy: str | list[str] | None = None
