from datetime import date, datetime
from decimal import Decimal
from uuid import UUID
from pydantic import BaseModel, ConfigDict, Field, field_validator

STATUSES = {"PENDING", "IN_TRANSIT", "DELIVERED", "CANCELLED"}

class DeliveryCreate(BaseModel):
    branch_id: UUID; customer_id: UUID; sale_id: UUID | None = None
    address: str = Field(min_length=1, max_length=500)
    delivery_fee: Decimal = Field(default=Decimal("0"), ge=0, max_digits=14, decimal_places=2)
    rider_driver_name: str | None = Field(default=None, max_length=200)
    rider_driver_phone: str | None = Field(default=None, max_length=50)
    tracking_reference: str = Field(min_length=1, max_length=150)
    notes: str | None = Field(default=None, max_length=2000)

class DeliveryUpdate(BaseModel):
    address: str | None = Field(default=None, min_length=1, max_length=500)
    delivery_fee: Decimal | None = Field(default=None, ge=0, max_digits=14, decimal_places=2)
    rider_driver_name: str | None = Field(default=None, max_length=200)
    rider_driver_phone: str | None = Field(default=None, max_length=50)
    tracking_reference: str | None = Field(default=None, min_length=1, max_length=150)
    notes: str | None = Field(default=None, max_length=2000)

class DeliveryStatusUpdate(BaseModel):
    status: str; note: str | None = Field(default=None, max_length=2000)
    @field_validator("status")
    @classmethod
    def validate_status(cls, value):
        value = value.upper()
        if value not in STATUSES: raise ValueError("Invalid delivery status.")
        return value

class DeliveryRead(BaseModel):
    id: UUID; business_id: UUID; branch_id: UUID; customer_id: UUID; sale_id: UUID | None; address: str; delivery_fee: Decimal; rider_driver_name: str | None; rider_driver_phone: str | None; tracking_reference: str; status: str; notes: str | None; created_by: UUID; created_at: datetime; updated_at: datetime
    model_config = ConfigDict(from_attributes=True)

class DeliveryHistoryRead(BaseModel):
    id: UUID; delivery_id: UUID; previous_status: str | None; new_status: str; changed_by: UUID; changed_at: datetime; note: str | None
    model_config = ConfigDict(from_attributes=True)
