"""Schemas for Flight API requests and responses."""

from __future__ import annotations

from datetime import datetime

from pydantic import BaseModel, Field

from gps_denied.schemas import CameraParameters, Geofences, GPSPoint

# ---------------------------------------------------------------------------
# Waypoint
# ---------------------------------------------------------------------------

class Waypoint(BaseModel):
    """Single waypoint with optional refinement flag."""

    id: str
    lat: float = Field(..., ge=-90, le=90)
    lon: float = Field(..., ge=-180, le=180)
    altitude: float | None = None
    confidence: float = Field(..., ge=0, le=1)
    timestamp: datetime
    refined: bool = False


# ---------------------------------------------------------------------------
# Flight — Requests
# ---------------------------------------------------------------------------

class FlightCreateRequest(BaseModel):
    """POST /flights body."""

    name: str = Field(..., min_length=1, max_length=255)
    description: str = ""
    start_gps: GPSPoint
    rough_waypoints: list[GPSPoint] = Field(default_factory=list)
    geofences: Geofences = Field(default_factory=Geofences)
    camera_params: CameraParameters
    altitude: float = Field(..., gt=0)


class UserFixRequest(BaseModel):
    """POST /flights/{flightId}/user-fix body."""

    frame_id: int = Field(..., ge=0)
    uav_pixel: tuple[float, float]
    satellite_gps: GPSPoint


class ObjectToGPSRequest(BaseModel):
    """POST /flights/{flightId}/frames/{frameId}/object-to-gps body."""

    pixel_x: float = Field(..., ge=0)
    pixel_y: float = Field(..., ge=0)


# ---------------------------------------------------------------------------
# Flight — Responses
# ---------------------------------------------------------------------------

class FlightResponse(BaseModel):
    """Response after flight creation."""

    flight_id: str
    status: str
    message: str | None = None
    created_at: datetime


class FlightDetailResponse(BaseModel):
    """GET /flights/{flightId} response."""

    flight_id: str
    name: str
    description: str
    start_gps: GPSPoint
    waypoints: list[Waypoint] = Field(default_factory=list)
    geofences: Geofences
    camera_params: CameraParameters
    altitude: float
    status: str
    frames_processed: int = 0
    frames_total: int = 0
    created_at: datetime
    updated_at: datetime


class FlightStatusResponse(BaseModel):
    """GET /flights/{flightId}/status response."""

    status: str
    frames_processed: int = 0
    frames_total: int = 0
    current_frame: int | None = None
    current_heading: float | None = None
    blocked: bool = False
    search_grid_size: int | None = None
    message: str | None = None
    created_at: datetime
    updated_at: datetime


class DeleteResponse(BaseModel):
    deleted: bool
    flight_id: str


class UpdateResponse(BaseModel):
    updated: bool
    waypoint_id: str


class BatchUpdateResponse(BaseModel):
    success: bool
    updated_count: int
    failed_ids: list[str] = Field(default_factory=list)
    errors: dict[str, str] | None = None


# ---------------------------------------------------------------------------
# Image Batch
# ---------------------------------------------------------------------------

class BatchMetadata(BaseModel):
    """Metadata accompanying an image batch upload."""

    start_sequence: int = Field(..., ge=0)
    end_sequence: int = Field(..., ge=0)
    batch_number: int = Field(..., ge=0)


class BatchResponse(BaseModel):
    """Response after batch upload."""

    accepted: bool
    sequences: list[int] = Field(default_factory=list)
    next_expected: int = 0
    message: str | None = None


# ---------------------------------------------------------------------------
# User Fix
# ---------------------------------------------------------------------------

class UserFixResponse(BaseModel):
    accepted: bool
    processing_resumed: bool = False
    message: str | None = None


# ---------------------------------------------------------------------------
# Object → GPS
# ---------------------------------------------------------------------------

class ObjectGPSResponse(BaseModel):
    gps: GPSPoint
    accuracy_meters: float
    frame_id: int
    pixel: tuple[float, float]
