"""MAVLink I/O schemas (Component — Phase 4)."""

from typing import Optional

from pydantic import BaseModel


class GPSInputMessage(BaseModel):
    """Full field set for MAVLink GPS_INPUT (#233).

    All numeric fields follow MAVLink units convention:
      lat/lon in degE7, alt in metres MSL, velocity in m/s.
    """
    time_usec: int          # µs since Unix epoch
    gps_id: int = 0
    ignore_flags: int = 0   # GPS_INPUT_IGNORE_FLAGS bitmask (0 = use all)
    time_week_ms: int        # GPS ms-of-week
    time_week: int           # GPS week number
    fix_type: int            # 0=no fix, 2=2D, 3=3D
    lat: int                 # degE7
    lon: int                 # degE7
    alt: float               # metres MSL
    hdop: float
    vdop: float
    vn: float                # m/s North
    ve: float                # m/s East
    vd: float                # m/s Down
    speed_accuracy: float    # m/s
    horiz_accuracy: float    # m
    vert_accuracy: float     # m
    satellites_visible: int = 10  # synthetic — prevents ArduPilot satellite-count failsafes


class IMUMessage(BaseModel):
    """IMU data decoded from MAVLink ATTITUDE / RAW_IMU."""
    accel_x: float   # m/s² body-frame X
    accel_y: float   # m/s² body-frame Y
    accel_z: float   # m/s² body-frame Z
    gyro_x: float    # rad/s body-frame X
    gyro_y: float    # rad/s body-frame Y
    gyro_z: float    # rad/s body-frame Z
    timestamp_us: int  # µs


class TelemetryMessage(BaseModel):
    """1-Hz telemetry payload sent as NAMED_VALUE_FLOAT messages."""
    confidence_score: float   # 0.0–1.0
    drift_estimate_m: float   # estimated position drift in metres
    fix_type: int             # current fix_type being sent
    frames_since_sat: int     # frames since last satellite correction


class RelocalizationRequest(BaseModel):
    """Sent when 3 consecutive frames have no position estimate (MAV-04)."""
    last_lat: Optional[float] = None    # last known WGS84 lat
    last_lon: Optional[float] = None    # last known WGS84 lon
    uncertainty_m: float = 500.0        # position uncertainty radius
    consecutive_failures: int = 3
