import uuid
from datetime import datetime
from enum import Enum, auto
from typing import List, Optional
from sqlalchemy import UniqueConstraint
from sqlmodel import Field, Relationship, SQLModel


class BaseModel(SQLModel):
    id: Optional[uuid.UUID] = Field(default_factory=uuid.uuid4, primary_key=True)
    created_at: datetime = Field(default=datetime.now())


class DroneModel(int, Enum):
    LIGHTWEIGHT = auto()
    MIDDLEWEIGHT = auto()
    CRUISERWEIGHT = auto()
    HEAVYWEIGHT = auto()


class DroneState(int, Enum):
    IDLE = auto()
    LOADING = auto()
    LOADED = auto()
    DELIVERING = auto()
    DELIVERED = auto()
    RETURNING = auto()


class Drone(BaseModel, table=True):
    __tablename__ = "drones"
    __table_args__ = (UniqueConstraint("serial_number"),)
    serial_number: str = Field(..., max_length=100, index=True)
    model: DroneModel = DroneModel.LIGHTWEIGHT
    weight_limit: float = Field(..., ge=0, le=500)
    battery_capacity: float = Field(..., ge=0, le=100)
    state: DroneState = DroneState.IDLE
    deliveries: List["Delivery"] = Relationship(back_populates="drone")
    auditories: List["Auditory"] = Relationship(back_populates="drone")


class DroneCreate(SQLModel):
    serial_number: str
    model: Optional[DroneModel] = None
    weight_limit: float
    battery_capacity: float
    state: Optional[DroneState] = None


class DroneUpdate(SQLModel):
    serial_number: Optional[str] = None
    model: Optional[DroneModel] = None
    weight_limit: Optional[float] = None
    battery_capacity: Optional[float] = None
    state: Optional[DroneState] = None


class Delivery(BaseModel, table=True):
    __tablename__ = "deliveries"
    drone_id: Optional[uuid.UUID] = Field(default=None, foreign_key="drones.id")
    drone: Optional[Drone] = Relationship(back_populates="deliveries")
    medications: List["Medication"] = Relationship(back_populates="delivery")


class DeliveryCreate(SQLModel):
    drone_id: Optional[uuid.UUID] = None
    medications: Optional[List[uuid.UUID]] = None


class Medication(BaseModel, table=True):
    __tablename__ = "medications"
    __table_args__ = (UniqueConstraint("name"),)
    name: str = Field(..., index=True)
    weight: float = Field(..., gt=0)
    code: str = Field(..., index=True)
    image: str
    delivery_id: Optional[uuid.UUID] = Field(default=None, foreign_key="deliveries.id")
    delivery: Optional[Delivery] = Relationship(back_populates="medications")


class MedicationCreate(SQLModel):
    name: str = None
    weight: float = None
    code: str = None
    image: str = None


class MedicationUpdate(SQLModel):
    name: Optional[str] = None
    weigth: Optional[float] = Field(..., gt=0)
    code: Optional[str] = None
    image: Optional[str]


class Auditory(BaseModel, table=True):
    drone_id: Optional[uuid.UUID] = Field(default=None, foreign_key="drones.id")
    drone: Optional[Drone] = Relationship(back_populates="auditories")
    battery_capacity: float = Field(...)

enum.auto datetime.datetime.now sqlalchemy.UniqueConstraint sqlmodel.Field sqlmodel.Relationship
[((254, 305), 'sqlmodel.Field', 'Field', ([], {'default_factory': 'uuid.uuid4', 'primary_key': '(True)'}), '(default_factory=uuid.uuid4, primary_key=True)\n', (259, 305), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((412, 418), 'enum.auto', 'auto', ([], {}), '()\n', (416, 418), False, 'from enum import Enum, auto\n'), ((438, 444), 'enum.auto', 'auto', ([], {}), '()\n', (442, 444), False, 'from enum import Enum, auto\n'), ((465, 471), 'enum.auto', 'auto', ([], {}), '()\n', (469, 471), False, 'from enum import Enum, auto\n'), ((490, 496), 'enum.auto', 'auto', ([], {}), '()\n', (494, 496), False, 'from enum import Enum, auto\n'), ((539, 545), 'enum.auto', 'auto', ([], {}), '()\n', (543, 545), False, 'from enum import Enum, auto\n'), ((560, 566), 'enum.auto', 'auto', ([], {}), '()\n', (564, 566), False, 'from enum import Enum, auto\n'), ((580, 586), 'enum.auto', 'auto', ([], {}), '()\n', (584, 586), False, 'from enum import Enum, auto\n'), ((604, 610), 'enum.auto', 'auto', ([], {}), '()\n', (608, 610), False, 'from enum import Enum, auto\n'), ((627, 633), 'enum.auto', 'auto', ([], {}), '()\n', (631, 633), False, 'from enum import Enum, auto\n'), ((650, 656), 'enum.auto', 'auto', ([], {}), '()\n', (654, 656), False, 'from enum import Enum, auto\n'), ((807, 845), 'sqlmodel.Field', 'Field', (['...'], {'max_length': '(100)', 'index': '(True)'}), '(..., max_length=100, index=True)\n', (812, 845), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((919, 943), 'sqlmodel.Field', 'Field', (['...'], {'ge': '(0)', 'le': '(500)'}), '(..., ge=0, le=500)\n', (924, 943), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((974, 998), 'sqlmodel.Field', 'Field', (['...'], {'ge': '(0)', 'le': '(100)'}), '(..., ge=0, le=100)\n', (979, 998), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((1074, 1110), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""drone"""'}), "(back_populates='drone')\n", (1086, 1110), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((1146, 1182), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""drone"""'}), "(back_populates='drone')\n", (1158, 1182), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((1712, 1756), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'foreign_key': '"""drones.id"""'}), "(default=None, foreign_key='drones.id')\n", (1717, 1756), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((1786, 1827), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""deliveries"""'}), "(back_populates='deliveries')\n", (1798, 1827), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((1866, 1905), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""delivery"""'}), "(back_populates='delivery')\n", (1878, 1905), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((2173, 2195), 'sqlmodel.Field', 'Field', (['...'], {'index': '(True)'}), '(..., index=True)\n', (2178, 2195), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((2216, 2232), 'sqlmodel.Field', 'Field', (['...'], {'gt': '(0)'}), '(..., gt=0)\n', (2221, 2232), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((2249, 2271), 'sqlmodel.Field', 'Field', (['...'], {'index': '(True)'}), '(..., index=True)\n', (2254, 2271), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((2326, 2374), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'foreign_key': '"""deliveries.id"""'}), "(default=None, foreign_key='deliveries.id')\n", (2331, 2374), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((2410, 2452), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""medications"""'}), "(back_populates='medications')\n", (2422, 2452), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((2675, 2691), 'sqlmodel.Field', 'Field', (['...'], {'gt': '(0)'}), '(..., gt=0)\n', (2680, 2691), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((2825, 2869), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'foreign_key': '"""drones.id"""'}), "(default=None, foreign_key='drones.id')\n", (2830, 2869), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((2899, 2940), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""auditories"""'}), "(back_populates='auditories')\n", (2911, 2940), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((2971, 2981), 'sqlmodel.Field', 'Field', (['...'], {}), '(...)\n', (2976, 2981), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((746, 779), 'sqlalchemy.UniqueConstraint', 'UniqueConstraint', (['"""serial_number"""'], {}), "('serial_number')\n", (762, 779), False, 'from sqlalchemy import UniqueConstraint\n'), ((2130, 2154), 'sqlalchemy.UniqueConstraint', 'UniqueConstraint', (['"""name"""'], {}), "('name')\n", (2146, 2154), False, 'from sqlalchemy import UniqueConstraint\n'), ((347, 361), 'datetime.datetime.now', 'datetime.now', ([], {}), '()\n', (359, 361), False, 'from datetime import datetime\n')]