""" Catering service models """
import uuid
from typing import List, Optional, Dict, Any
from enum import Enum
from pydantic import validator

from sqlmodel import Field, Relationship, Column, JSON
from .base import SQLModel


class TipoEntrega(str, Enum):
    """Tipos de entrega disponibles para catering"""
    ESTABLECIMIENTO = "establecimiento"
    ENTREGA = "entrega"
    SERVICIO_DOMICILIO = "servicio_domicilio"


class Alergenos(str, Enum):
    """Tipos de alergenos disponibles"""
    GLUTEN = "gluten"
    CRUSTACEOS = "crustaceos"
    PESCADO = "pescado"
    HUEVOS = "huevos"
    CACAHUETES = "cacahuetes"
    SOJA = "soja"
    LACTEOS = "lacteos"
    FRUTOS_DE_CASCARA = "frutos_de_cascara"
    APIO = "apio"
    MOSTAZA = "mostaza"
    SESAMO = "sesamo"
    DI_AZUFRE = "di_azufre"
    ALTRAMUCES = "altramuces"
    MOLUSCOS = "moluscos"


class TipoMenu(str, Enum):
    """Tipos de menús disponibles"""
    TAPAS = "tapas"  # Menú de tapas
    PIZZA = "pizza"  # Menú de pizza
    MEDITERRANEO = "mediterraneo"  # Menú mediterráneo
    ASIATICO = "asiatico"  # Menú asiático
    MEXICANO = "mexicano"  # Menú mexicano
    ITALIANO = "italiano"  # Menú italiano
    VEGETARIANO = "vegetariano"  # Menú vegetariano
    VEGANO = "vegano"  # Menú vegano
    SIN_GLUTEN = "sin_gluten"  # Menú sin gluten
    INFANTIL = "infantil"  # Menú infantil
    GOURMET = "gourmet"  # Menú gourmet
    FUSION = "fusion"  # Menú fusión
    MARISCO = "marisco"  # Menú de marisco
    CARNES = "carnes"  # Menú de carnes
    POSTRES = "postres"  # Menú de postres
    BODEGAS = "bodegas"  # Menú de bodegas
    BRUNCH = "brunch"  # Menú brunch
    COFFEE_BREAK = "coffee_break"  # Menú coffee break
    PICNIC = "picnic"  # Menú picnic
    BARBACOA = "barbacoa"  # Menú barbacoa
    PAELLA = "paella"  # Menú paella
    SUSHI = "sushi"  # Menú sushi
    VARIADO = "variado"  # Menú variado
    OTRO = "otro"  # Menú otro


class TipoArticulo(str, Enum):
    """Tipos de artículos disponibles para catering"""
    # Bebidas
    AGUA = "agua"  # Agua mineral
    REFRESCOS = "refrescos"  # Refrescos varios
    ZUMOS = "zumos"  # Zumos naturales
    CERVEZA = "cerveza"  # Cerveza
    VINO = "vino"  # Vino
    CAVA = "cava"  # Cava
    CHAMPAGNE = "champagne"  # Champagne
    COCTELES = "cocteles"  # Cócteles
    CAFE = "cafe"  # Café
    TE = "te"  # Té
    INFUSIONES = "infusiones"  # Infusione
    # Aperitivos
    ACEITUNAS = "aceitunas"  # Aceitunas
    FRUTOS_SECOS = "frutos_secos"  # Frutos secos
    PATATAS = "patatas"  # Patatas fritas/snacks
    TAPAS = "tapas"  # Tapas variadas
    CANAPES = "canapes"  # Canapés
    QUESOS = "quesos"  # Tabla de quesos
    EMBUTIDOS = "embutidos"  # Tabla de embutidos
    # Postres
    TARTAS = "tartas"  # Tartas
    PASTELES = "pasteles"  # Pasteles
    HELADOS = "helados"  # Helados
    FRUTA = "fruta"  # Fruta fresca
    CHOCOLATES = "chocolates"  # Chocolates
    GALLETAS = "galletas"  # Galletas
    DULCES = "dulces"  # Dulces varios
    # Otros
    VARIADO = "variado"  # Artículos variados
    OTRO = "otro"  # Otro tipo de artículo


class TipoCatering(str, Enum):
    """Tipos de servicio de catering según la forma de servir"""
    # Servicios en mesa
    MESA_SERVIDO = "mesa_servido"  # Servicio en mesa con camareros (emplatado o a la inglesa)
    MESA_COMPARTIDO = "mesa_compartido"  # Servicio en mesa donde los comensales se sirven (family style o a la francesa)
    MESA_REDONDA = "mesa_redonda"  # Mesas redondas de 8-12 personas con servicio en mesa
    BANQUETE_IMPERIAL = "banquete_imperial"  # Mesas largas y alargadas, servicio en mesa
    GUERIDON = "gueridon"  # Platos terminados o montados en carro junto a la mesa
    # Servicios de buffet
    BUFFET = "buffet"  # Buffet (con o sin mesas)
    ESTACIONES = "estaciones"  # Islas de comida específica (pasta, carne, sushi, etc.)
    # Servicios de cóctel y aperitivos
    COCTEL = "coctel"  # Aperitivos y canapés servidos por camareros con bandejas
    FINGER_FOOD = "finger_food"  # Mini porciones para comer con la mano
    # Servicios mixtos
    MIXTO_COCTEL_MESA = "mixto_coctel_mesa"  # Aperitivos de pie + comida en mesa
    MIXTO_COCTEL_BUFFET = "mixto_coctel_buffet"  # Aperitivos de pie + buffet
    # Servicios especiales
    SHOW_COOKING = "show_cooking"  # Cocina en vivo frente a los invitados
    FOOD_TRUCK = "food_truck"  # Servicio desde food truck


class Menu(SQLModel):
    """Modelo para menús de catering"""
    type_menu: TipoMenu = Field(description="Tipo de menú")
    nombre: str = Field(description="Nombre del menú")
    descripcion: str = Field(description="Descripción del menú")
    platos: List[str] = Field(sa_column=Column(JSON), description="Lista de platos incluidos en el menú")
    opciones_especiales: List[str] = Field(default_factory=list, sa_column=Column(JSON), description="Opciones especiales disponibles (ej: sin gluten, sin lactosa)")


class Articulo(SQLModel):
    """Modelo para artículos individuales de catering"""
    type_articulo: TipoArticulo = Field(description="Tipo de artículo")
    nombre: str = Field(description="Nombre del artículo")
    descripcion: str = Field(description="Descripción del artículo")
    opciones_especiales: List[str] = Field(default_factory=list, sa_column=Column(JSON), description="Opciones especiales disponibles")


class CateringBase(SQLModel):
    """Modelo base para servicios de catering"""
    tipo_entrega: TipoEntrega = Field(description="Tipo de entrega del servicio")
    tipo_catering: Optional[TipoCatering] = Field(default=None, description="Tipo de servicio de catering")
    min_comensales: int = Field(description="Número mínimo de comensales")
    max_comensales: int = Field(description="Número máximo de comensales")
    duracion: float = Field(description="Duración del servicio en horas")
    alergenos: List[Alergenos] = Field(default_factory=list, sa_column=Column(JSON), description="Alergenos presentes en el servicio")
    caracteristicas: List[str] = Field(default_factory=list, sa_column=Column(JSON), description="Características del servicio")

    @validator('max_comensales')
    def validate_max_comensales(cls, v, values):
        """Valida que max_comensales sea mayor o igual que min_comensales"""
        if 'min_comensales' in values and v < values['min_comensales']:
            raise ValueError('max_comensales debe ser mayor o igual que min_comensales')
        return v

    @validator('tipo_catering', pre=True, always=True)
    def empty_string_to_none(cls, v):
        if v == "":
            return None
        return v



# Database model
class Catering(CateringBase, table=True):
    """Modelo de base de datos para servicios de catering"""
    id: uuid.UUID = Field(default=None, primary_key=True, foreign_key="service.id", description="ID único del servicio de catering")
    service: "Service" = Relationship(back_populates="catering")
    menu: Optional[Menu] = Field(default=None, sa_column=Column(JSON), description="Menú disponible")
    articulo: Optional[Articulo] = Field(default=None, sa_column=Column(JSON), description="Artículo individual disponible")

    @validator('menu', 'articulo', check_fields=False)
    def validate_menu_or_articulo(cls, v, values):
        """Valida que al menos uno de los campos menu o articulo esté definido"""
        if v is None and 'articulo' in values and values['articulo'] is None:
            raise ValueError('Al menos uno de los campos menu o articulo debe estar definido')
        return v
# Out models
class CateringOut(CateringBase):
    """Modelo de salida para servicios de catering"""
    id: uuid.UUID


class CateringsOut(SQLModel):
    """Modelo de salida para listas de servicios de catering"""
    data: List[CateringOut] = Field(description="Lista de servicios de catering")
    count: int = Field(description="Número total de servicios")

class CateringServiceOut(CateringBase):
    """Modelo de salida para servicios de catering"""
    id: uuid.UUID
    menu: Optional[Menu] = Field(default=None, sa_column=Column(JSON), description="Menú disponible")
    articulo: Optional[Articulo] = Field(default=None, sa_column=Column(JSON), description="Artículo individual disponible")


class CateringsServiceOut(SQLModel):
    """Modelo de salida para listas de servicios de catering"""
    data: List[CateringServiceOut] = Field(description="Lista de servicios de catering")
    count: int = Field(description="Número total de servicios")



# Create/Update models
class CateringCreate(CateringBase):
    """Modelo para crear servicios de catering"""
    pass


class CateringUpdate(SQLModel):
    """Modelo para actualizar servicios de catering"""
    tipo_entrega: Optional[TipoEntrega] = Field(default=None, description="Tipo de entrega del servicio")
    tipo_catering: Optional[TipoCatering] = Field(default=None, description="Tipo de servicio de catering")
    menu: Optional[Menu] = Field(default=None, sa_column=Column(JSON), description="Menú disponible")
    articulo: Optional[Articulo] = Field(default=None, sa_column=Column(JSON), description="Artículo individual disponible")
    min_comensales: Optional[int] = Field(default=None, description="Número mínimo de comensales")
    max_comensales: Optional[int] = Field(default=None, description="Número máximo de comensales")
    duracion: Optional[float] = Field(default=None, description="Duración del servicio en horas")
    alergenos: Optional[List[Alergenos]] = Field(default=None, sa_column=Column(JSON), description="Alergenos presentes en el servicio")
    caracteristicas: Optional[List[str]] = Field(default=None, sa_column=Column(JSON), description="Características del servicio")

    @validator('max_comensales')
    def validate_max_comensales(cls, v, values):
        """Valida que max_comensales sea mayor o igual que min_comensales"""
        if 'min_comensales' in values and v is not None and values['min_comensales'] is not None and v < values['min_comensales']:
            raise ValueError('max_comensales debe ser mayor o igual que min_comensales')
        return v
    

class CateringServiceCreate(CateringBase):
    """Modelo para crear servicios de catering"""
    menu: Optional[Menu] = Field(default=None, sa_column=Column(JSON), description="Menú disponible")
    articulo: Optional[Articulo] = Field(default=None, sa_column=Column(JSON), description="Artículo individual disponible")


class CateringServiceUpdate(SQLModel):
    """Modelo para actualizar servicios de catering"""
    tipo_entrega: Optional[TipoEntrega] = Field(default=None, description="Tipo de entrega del servicio")
    tipo_catering: Optional[TipoCatering] = Field(default=None, description="Tipo de servicio de catering")
    menu: Optional[Menu] = Field(default=None, sa_column=Column(JSON), description="Menú disponible")
    articulo: Optional[Articulo] = Field(default=None, sa_column=Column(JSON), description="Artículo individual disponible")
    min_comensales: Optional[int] = Field(default=None, description="Número mínimo de comensales")
    max_comensales: Optional[int] = Field(default=None, description="Número máximo de comensales")
    duracion: Optional[float] = Field(default=None, description="Duración del servicio en horas")
    alergenos: Optional[List[Alergenos]] = Field(default=None, sa_column=Column(JSON), description="Alergenos presentes en el servicio")
    caracteristicas: Optional[List[str]] = Field(default=None, sa_column=Column(JSON), description="Características del servicio")

    @validator('max_comensales')
    def validate_max_comensales(cls, v, values):
        """Valida que max_comensales sea mayor o igual que min_comensales"""
        if 'min_comensales' in values and v is not None and values['min_comensales'] is not None and v < values['min_comensales']:
            raise ValueError('max_comensales debe ser mayor o igual que min_comensales')
        return v    
    
    
    