from pydantic import BaseModel, StringConstraints
from typing import List, Optional, Annotated
from typing import Literal
from datetime import datetime
from pydantic import field_validator

class WaiterBase(BaseModel):
    name: str
    load: float = 0
    role: str = "waiter"

class WaiterCreate(WaiterBase):
    pass

class WaiterOut(WaiterBase):
    id: int
    class Config:
        from_attributes = True

class UserBase(BaseModel):
    username: str
    role: Optional[str] = "user"

class UserCreate(BaseModel):
    username: str
    password: Annotated[str, StringConstraints(max_length=72)]
    role: Literal["user", "admin", "manager", "barra", "sala"] = "user"

    @field_validator("role")
    @classmethod
    def validate_role(cls, v):
        allowed = {"user", "admin", "manager", "barra", "sala"}
        if v not in allowed:
            raise ValueError(f"role must be one of {allowed}")
        return v

class UserOut(UserBase):
    id: int
    class Config:
        from_attributes = True

class ProductBase(BaseModel):
    name: str
    price: float
    cost: float
    group_id: int

class ProductCreate(ProductBase):
    pass

class ProductOut(ProductBase):
    id: int
    class Config:
        from_attributes = True

class GroupBase(BaseModel):
    name: str

class GroupCreate(GroupBase):
    pass

class GroupOut(GroupBase):
    id: int
    class Config:
        from_attributes = True

class TableBase(BaseModel):
    number: int
    name: Optional[str] = None
    abbreviation: Optional[str] = None
    pos_x: Optional[int] = None
    pos_y: Optional[int] = None

class TableCreate(TableBase):
    pass

class TableOut(TableBase):
    id: int
    name: Optional[str] = None
    abbreviation: Optional[str] = None
    pos_x: Optional[int] = None
    pos_y: Optional[int] = None
    class Config:
        from_attributes = True

class OrderProductBase(BaseModel):
    product_id: int
    quantity: int
    waiter_id: int | None = None

class OrderProductCreate(OrderProductBase):
    pass

class OrderProductOut(OrderProductBase):
    id: int
    class Config:
        from_attributes = True

class OrderBase(BaseModel):
    products: List[OrderProductCreate]
    table_id: Optional[int]
    total_price: Optional[float] = 0


class OrderCreate(OrderBase):
    algorithm: Optional[str] = "least-loaded"

class OrderOut(BaseModel):
    id: int
    status: str
    total_price: float
    created_at: datetime
    table: Optional[TableOut] = None
    products: List[OrderProductOut]
    class Config:
        from_attributes = True
    @field_validator("status")
    @classmethod
    def validate_status(cls, v):
        allowed = {"pending", "ready", "delivered"}
        if v not in allowed:
            raise ValueError(f"status must be one of {allowed}")
        return v