"""Pydantic schemas for the Modbus device CRUD + readings + metrics API (M5-T05)."""

from __future__ import annotations

from datetime import datetime
from typing import Any

from pydantic import BaseModel, Field


# ---------------------------------------------------------------------------
# Device schemas
# ---------------------------------------------------------------------------


class ModbusDeviceCreate(BaseModel):
    """Request body for POST /api/modbus/devices."""

    friendly_name: str = Field(..., min_length=1, max_length=255)
    transport: str = Field(default="tcp", max_length=16)
    host: str = Field(..., min_length=1, max_length=255)
    port: int = Field(default=502, ge=1, le=65535)
    unit_id: int = Field(default=1, ge=0, le=247)
    profile: str = Field(..., min_length=1, max_length=64)
    poll_interval_s: int = Field(default=5, ge=1, le=3600)
    enabled: bool = Field(default=True)


class ModbusDeviceUpdate(BaseModel):
    """Request body for PATCH /api/modbus/devices/{uuid} — all fields optional."""

    friendly_name: str | None = Field(default=None, min_length=1, max_length=255)
    transport: str | None = Field(default=None, max_length=16)
    host: str | None = Field(default=None, min_length=1, max_length=255)
    port: int | None = Field(default=None, ge=1, le=65535)
    unit_id: int | None = Field(default=None, ge=0, le=247)
    profile: str | None = Field(default=None, min_length=1, max_length=64)
    poll_interval_s: int | None = Field(default=None, ge=1, le=3600)
    enabled: bool | None = None


class ModbusDeviceResponse(BaseModel):
    """Response schema for a single Modbus device."""

    uuid: str
    friendly_name: str
    transport: str
    host: str
    port: int
    unit_id: int
    profile: str
    poll_interval_s: int
    enabled: bool
    last_poll_at: datetime | None
    last_poll_ok: bool | None
    created_at: datetime
    updated_at: datetime

    model_config = {"from_attributes": True}


class ModbusDeviceListResponse(BaseModel):
    """Response schema for listing Modbus devices."""

    items: list[ModbusDeviceResponse]
    total: int


# ---------------------------------------------------------------------------
# Reading schemas
# ---------------------------------------------------------------------------


class ModbusReadingResponse(BaseModel):
    """A single reading row: timestamp + decoded payload."""

    recorded_at: datetime
    payload: dict[str, Any]

    model_config = {"from_attributes": True}


class ModbusReadingsResponse(BaseModel):
    """Response schema for the readings time-range endpoint."""

    items: list[ModbusReadingResponse]


class ModbusLatestResponse(BaseModel):
    """Response for the /latest endpoint.

    ``found`` is False and ``recorded_at``/``payload`` are None when the device
    has no readings yet.  Callers should check ``found`` before using the values.
    """

    found: bool
    recorded_at: datetime | None
    payload: dict[str, Any] | None


# ---------------------------------------------------------------------------
# Metrics / profile schemas
# ---------------------------------------------------------------------------


class MetricInfo(BaseModel):
    """Metadata for a single measurable quantity in a device's profile."""

    key: str
    label: str
    unit: str
    device_class: str


class ModbusMetricsResponse(BaseModel):
    """Response schema for GET /api/modbus/devices/{uuid}/metrics."""

    profile: str
    metrics: list[MetricInfo]


# ---------------------------------------------------------------------------
# Profile list schema
# ---------------------------------------------------------------------------


class ProfileSummary(BaseModel):
    """One entry in the GET /api/modbus/profiles response."""

    name: str
    description: str


class ModbusProfilesResponse(BaseModel):
    """Response schema for GET /api/modbus/profiles."""

    profiles: list[ProfileSummary]


# ---------------------------------------------------------------------------
# Test-read schema
# ---------------------------------------------------------------------------


class ModbusTestReadResponse(BaseModel):
    """Response for POST /api/modbus/devices/{uuid}/test.

    On success ``ok=True`` and ``payload`` contains the decoded values.
    On failure ``ok=False`` and ``error`` describes the problem.
    """

    ok: bool
    payload: dict[str, Any] | None = None
    error: str | None = None


# ---------------------------------------------------------------------------
# Cascade-delete schema
# ---------------------------------------------------------------------------


class ModbusDeleteResponse(BaseModel):
    """Response for DELETE /api/modbus/devices/{uuid}?cascade=true.

    Returned only when cascade deletion succeeds (HTTP 200).  Non-cascade
    successful deletes continue to return HTTP 204 (no body).
    """

    deleted: bool
    readings_deleted: int
    toggles_deleted: int
