""" Service models """
import uuid
from typing import List, Optional, Dict, Any
from enum import Enum
from .relationship_event_service import EventService
from sqlmodel import Field, Relationship, Column, JSON
from .base import SQLModel


class ServiceType(str, Enum):
    """Tipos de servicios disponibles"""
    ESPAI = "espai"
    CATERING = "catering"
    MOBILIARI_DECORACIO = "mobiliari-decoracio"
    MUSICA = "musica"
    FOTOGRAFIA = "fotografia"

class Address(SQLModel):
    """Modelo de salida para direcciones"""
    direccion: str = Field(max_length=255, description="Dirección postal completa")
    ciudad: str = Field(max_length=100, description="Ciudad")
    codigo_postal: str = Field(max_length=10, description="Código postal")
    provincia: str = Field(max_length=100, description="Provincia")

class ServiceBase(SQLModel):
    """Modelo base para servicios"""
    type: ServiceType = Field(description="Tipo de servicio")
    name: str = Field(index=True, description="Nombre del servicio")
    images: List[str] = Field(default_factory=list, sa_column=Column(JSON))
    description: str = Field(default=None, description="Descripción del servicio")
    service_include: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    address: Address = Field(default=None, sa_column=Column(JSON), description="Dirección del servicio")


# Database model
class Service(ServiceBase, table=True):
    """Modelo de base de datos para servicios"""
    id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
    account_id: uuid.UUID = Field(foreign_key="account.id")
    account: "Account" = Relationship(back_populates="services")
    events: List["Event"] = Relationship(back_populates="services", link_model=EventService)
    availability_rules: List["AvailabilityRule"] = Relationship(back_populates="service")

    # Relaciones con los servicios específicos
    espai_id: Optional[uuid.UUID] = None
    catering_id: Optional[uuid.UUID] = None
    mobiliari_decoracio_id: Optional[uuid.UUID] = None
    musica_id: Optional[uuid.UUID] = None
    fotografia_id: Optional[uuid.UUID] = None
    espai: Optional["Espai"] = Relationship(back_populates="service")
    catering: Optional["Catering"] = Relationship(back_populates="service")
    mobiliari_decoracio: Optional["MobiliariDecoracio"] = Relationship(back_populates="service")
    musica: Optional["Musica"] = Relationship(back_populates="service")
    fotografia: Optional["Fotografia"] = Relationship(back_populates="service")


# -- Out Services model --
class ServiceOut(SQLModel):
    """Modelo de salida para servicios"""
    id: uuid.UUID
    type: ServiceType
    name: str
    description: Optional[str] = None
    images: List[str] = Field(default_factory=list)
    service_include: Optional[Dict[str, Any]] = None
    address: Optional[Address] = None
    availability_rules: List[Dict[str, Any]] = Field(default_factory=list)
    account_id: uuid.UUID
    
    # Campos específicos de cada tipo de servicio
    espai_id: Optional[uuid.UUID] = None
    espai: Optional[Dict[str, Any]] = None
    catering_id: Optional[uuid.UUID] = None
    catering: Optional[Dict[str, Any]] = None
    mobiliari_decoracio_id: Optional[uuid.UUID] = None
    mobiliari_decoracio: Optional[Dict[str, Any]] = None
    musica_id: Optional[uuid.UUID] = None
    musica: Optional[Dict[str, Any]] = None
    fotografia_id: Optional[uuid.UUID] = None
    fotografia: Optional[Dict[str, Any]] = None

    class Config:
        from_attributes = True
        exclude_none = True
        exclude_unset = True

class ServicesOut(SQLModel):
    """Modelo de salida para listas de servicios"""
    data: List[Dict[str, Any]] = Field(description="Lista de servicios")
    count: int = Field(description="Número total de servicios")


# -- Out Services específicos --
class ServiceFotografiaOut(ServiceBase):
    """Modelo de salida para servicios de fotografía con su raider"""
    id: uuid.UUID
    availability_rules: List[Dict[str, Any]]
    account_id: uuid.UUID
    fotografia_id: uuid.UUID
    fotografia: Dict[str, Any]

class ServiceFotografiasOut(SQLModel):
    data: List[ServiceFotografiaOut] = Field(description="Lista de servicios de fotografía")
    count: int = Field(description="Número total de servicios de fotografía")

class ServiceCateringOut(ServiceBase):
    """Modelo de salida para servicios de catering"""
    id: uuid.UUID
    availability_rules: List[Dict[str, Any]]
    account_id: uuid.UUID
    catering_id: uuid.UUID
    catering: Dict[str, Any]

class ServiceCateringsOut(SQLModel):
    data: List[ServiceCateringOut] = Field(description="Lista de servicios de catering")
    count: int = Field(description="Número total de servicios de catering")

class ServiceMobiliariDecoracioOut(ServiceBase):
    """Modelo de salida para servicios de mobiliario y decoración"""
    id: uuid.UUID
    availability_rules: List[Dict[str, Any]]
    account_id: uuid.UUID
    mobiliari_decoracio_id: uuid.UUID
    mobiliari_decoracio: Dict[str, Any]

class ServiceMobiliariDecoraciosOut(SQLModel):
    data: List[ServiceMobiliariDecoracioOut] = Field(description="Lista de servicios de mobiliario y decoración")
    count: int = Field(description="Número total de servicios de mobiliario y decoración")

class ServiceMusicaOut(ServiceBase):
    """Modelo de salida para servicios de música"""
    id: uuid.UUID
    availability_rules: List[Dict[str, Any]]
    account_id: uuid.UUID
    musica_id: uuid.UUID
    musica: Dict[str, Any]

class ServiceMusicasOut(SQLModel):
    data: List[ServiceMusicaOut] = Field(description="Lista de servicios de música")
    count: int = Field(description="Número total de servicios de música")

class ServiceEspaiOut(ServiceBase):
    """Modelo de salida para servicios de espacio"""
    id: uuid.UUID
    availability_rules: List[Dict[str, Any]]
    account_id: uuid.UUID
    espai_id: uuid.UUID
    espai: Dict[str, Any]

class ServiceEspaisOut(SQLModel):
    data: List[ServiceEspaiOut] = Field(description="Lista de servicios de espacio")
    count: int = Field(description="Número total de servicios de espacio")


# -- Create/Update models --
class ServiceCreate(ServiceBase):
    """Modelo para crear servicios"""
    availability_rules: List[Dict[str, Any]]
    pass

class ServiceUpdate(SQLModel):
    """Modelo para actualizar servicios genéricos"""
    name: Optional[str] = Field(default=None, description="Nombre del servicio")
    type: Optional[ServiceType] = Field(default=None, description="Tipo de servicio")
    images: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    description: Optional[str] = Field(default=None, description="Descripción del servicio")
    service_include: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    availability_rules: Optional[List[Dict[str, Any]]] = Field(default=None, sa_column=Column(JSON))
    address: Optional[Address] = Field(default=None, sa_column=Column(JSON), description="Dirección del servicio")

# -- Create/Update models específicos --
class ServiceCreateFotografia(ServiceBase):
    """Modelo para crear servicios de fotografía"""
    availability_rules: List[Dict[str, Any]]
    fotografia: Dict[str, Any]

class ServiceUpdateFotografia(SQLModel):
    """Modelo para actualizar servicios de fotografía"""
    name: Optional[str] = Field(default=None, description="Nombre del servicio")
    images: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    description: Optional[str] = Field(default=None, description="Descripción del servicio")
    service_include: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    availability_rules: Optional[List[Dict[str, Any]]] = Field(default=None, sa_column=Column(JSON))
    address: Optional[Address] = Field(default=None, sa_column=Column(JSON), description="Dirección del servicio")
    fotografia: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))

class ServiceCreateCatering(ServiceBase):
    """Modelo para crear servicios de catering"""
    availability_rules: List[Dict[str, Any]]
    catering: Dict[str, Any]

class ServiceUpdateCatering(SQLModel):
    """Modelo para actualizar servicios de catering"""
    name: Optional[str] = Field(default=None, description="Nombre del servicio")
    images: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    description: Optional[str] = Field(default=None, description="Descripción del servicio")
    service_include: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    availability_rules: Optional[List[Dict[str, Any]]] = Field(default=None, sa_column=Column(JSON))
    address: Optional[Address] = Field(default=None, sa_column=Column(JSON), description="Dirección del servicio")
    catering: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))

class ServiceCreateMobiliariDecoracio(ServiceBase):
    """Modelo para crear servicios de mobiliario y decoración"""
    availability_rules: List[Dict[str, Any]]
    mobiliari_decoracio: Dict[str, Any]

class ServiceUpdateMobiliariDecoracio(SQLModel):
    """Modelo para actualizar servicios de mobiliario y decoración"""
    name: Optional[str] = Field(default=None, description="Nombre del servicio")
    images: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    description: Optional[str] = Field(default=None, description="Descripción del servicio")
    service_include: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    availability_rules: Optional[List[Dict[str, Any]]] = Field(default=None, sa_column=Column(JSON))
    address: Optional[Address] = Field(default=None, sa_column=Column(JSON), description="Dirección del servicio")
    mobiliari_decoracio: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))

class ServiceCreateEspai(ServiceBase):
    """Modelo para crear servicios de espacio"""
    availability_rules: List[Dict[str, Any]]
    espai: Dict[str, Any]

class ServiceUpdateEspai(SQLModel):
    """Modelo para actualizar servicios de espacio"""
    name: Optional[str] = Field(default=None, description="Nombre del servicio")
    images: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    description: Optional[str] = Field(default=None, description="Descripción del servicio")
    service_include: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    availability_rules: Optional[List[Dict[str, Any]]] = Field(default=None, sa_column=Column(JSON))
    address: Optional[Address] = Field(default=None, sa_column=Column(JSON), description="Dirección del servicio")
    espai: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))

class ServiceCreateMusica(ServiceBase):
    """Modelo para crear servicios de música"""
    availability_rules: List[Dict[str, Any]]
    musica: Dict[str, Any]

class ServiceUpdateMusica(SQLModel):
    """Modelo para actualizar servicios de música"""
    name: Optional[str] = Field(default=None, description="Nombre del servicio")
    images: Optional[List[str]] = Field(default=None, sa_column=Column(JSON))
    description: Optional[str] = Field(default=None, description="Descripción del servicio")    
    service_include: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    availability_rules: Optional[List[Dict[str, Any]]] = Field(default=None, sa_column=Column(JSON))
    address: Optional[Address] = Field(default=None, sa_column=Column(JSON), description="Dirección del servicio")
    musica: Optional[Dict[str, Any]] = Field(default=None, sa_column=Column(JSON))
    












