"""Per-vessel configuration: identification + actuator + PID.

Composes the lower-level configs into one object that lives at the heart
of every ``ProjectConfig``.
"""

from __future__ import annotations

from enum import StrEnum

from pydantic import BaseModel, ConfigDict, Field

from arautopilot.core.actuator_config import ActuatorConfig
from arautopilot.core.ids import VesselId, new_vessel_id
from arautopilot.core.pid_config import PidConfig
from arautopilot.core.sensor_config import DualRudderSensorConfig, RudderSensorConfig, RudderSensorType


class VesselType(StrEnum):
    """Vessel classes targeted by Phase 1 of the product (brief section 3)."""

    YACHT_MOTOR_PLANEO = "yacht_motor_planeo"
    """Planing motor yacht, 30-40 m."""

    YACHT_MOTOR_DESPLAZAMIENTO = "yacht_motor_desplazamiento"
    """Displacement motor yacht, 30-40 m."""

    SAILBOAT_MOTOR = "sailboat_motor"
    """Sailing yacht under motor (no sail trim). Phase 1 only."""

    FISHING_BOAT = "fishing_boat"
    """Fishing vessel, 30 m class."""

    SMALL_FERRY = "small_ferry"
    """Small ferry, 30 m class."""

    PATROL_BOAT = "patrol_boat"
    """Coastal patrol boat, 30 m class."""


class VesselConfig(BaseModel):
    """Identification, geometry, and control configuration of one vessel."""

    model_config = ConfigDict(extra="forbid", validate_assignment=True)

    vessel_id: VesselId = Field(default_factory=new_vessel_id)
    name: str = Field(min_length=1, max_length=120)
    type: VesselType
    length_m: float = Field(gt=0.0, le=200.0, description="Length overall, metres.")
    displacement_t: float = Field(
        default=0.0,
        ge=0.0,
        le=10_000.0,
        description="Loaded displacement, tonnes. 0 means unknown.",
    )
    max_speed_kn: float = Field(
        gt=0.0,
        le=80.0,
        description="Maximum design speed over ground, knots.",
    )

    actuator: ActuatorConfig
    pid: PidConfig
    sensors: DualRudderSensorConfig = Field(
        default_factory=lambda: DualRudderSensorConfig(
            primary=RudderSensorConfig(
                type=RudderSensorType.AS5048A_SPI,
                label="Primary – rudder stock",
                spi_cs_gpio=10,
            )
        ),
        description="Rudder angle sensor(s). Dual config enables cross-validation and failover.",
    )
