"""
Modelos Pydantic para requests y responses de la API.
"""
from enum import Enum
from pydantic import BaseModel, Field
from typing import Optional, List


class ProductSyncStatusEnum(str, Enum):
    """Estados de sincronización/migración de productos."""
    PENDING = "pendiente"    # Estado inicial al parsear del XML
    NORMAL = "normal"        # No cambió su estado (ya existía igual)
    NEW = "nuevo"            # Nuevo registro detectado
    DELETED = "eliminado"    # Marcado para eliminar


class ChatRequest(BaseModel):
    """
    Request para el endpoint de chat.
    
    Attributes:
        uuid_conversation: Identificador único del cliente (ej: número de WhatsApp)
        message: Mensaje del usuario
    """
    uuid_conversation: str = Field(
        ..., 
        description="Identificador único del cliente (número de WhatsApp)",
        min_length=1,
        example="573001234567"
    )
    message: str = Field(
        ..., 
        description="Mensaje del usuario",
        min_length=1,
        example="Hola, busco una lavadora Samsung"
    )
    
    class Config:
        json_schema_extra = {
            "example": {
                "uuid_conversation": "573001234567",
                "message": "Hola, busco una lavadora barata"
            }
        }


class ChatResponse(BaseModel):
    """
    Response del endpoint de chat.
    
    Attributes:
        uuid_conversation: Identificador del cliente
        response: Respuesta del agente
        session_active: Indica si la sesión está activa
    """
    uuid_conversation: str = Field(
        ..., 
        description="Identificador del cliente"
    )
    response: str = Field(
        ..., 
        description="Respuesta del agente de ventas"
    )
    session_active: bool = Field(
        default=True, 
        description="Indica si la sesión está activa"
    )
    
    class Config:
        json_schema_extra = {
            "example": {
                "uuid_conversation": "573001234567",
                "response": "¡Hola! Claro, tengo estas lavadoras disponibles...",
                "session_active": True
            }
        }


class ProductSearchRequest(BaseModel):
    """
    Request para búsqueda directa de productos por texto.
    Genera embedding y busca en Neo4j sin pasar por el modelo LLM.
    """
    query: str = Field(
        ...,
        description="Texto de búsqueda para encontrar productos",
        min_length=1,
        example="lavadora Samsung 15kg"
    )
    limit: int = Field(
        default=5,
        description="Cantidad máxima de productos a retornar",
        ge=1,
        le=50
    )

    class Config:
        json_schema_extra = {
            "example": {
                "query": "televisor 55 pulgadas",
                "limit": 5
            }
        }


class ProductItem(BaseModel):
    """Producto individual retornado por la búsqueda."""
    id: Optional[str] = None
    sku_id: Optional[str] = None
    name: Optional[str] = None
    price: Optional[str] = None
    description: Optional[str] = None
    link: Optional[str] = None
    image_link: Optional[str] = None
    category: Optional[str] = None
    brand: Optional[str] = None
    score: Optional[float] = None


class ProductSearchResponse(BaseModel):
    """
    Response de búsqueda directa de productos.
    """
    query: str = Field(..., description="Texto de búsqueda original")
    total: int = Field(..., description="Cantidad de productos encontrados")
    products: List[ProductItem] = Field(default=[], description="Lista de productos encontrados")


class ConversationChatRequest(BaseModel):
    """
    Request para búsqueda de productos con respuesta del LLM.
    Combina búsqueda vectorial + generación de respuesta natural.

    Para paginación ("ver más"), enviar solo uuid_conversation + next_page=true.
    El servidor recupera automáticamente el query anterior y calcula el offset.
    """
    uuid_conversation: str = Field(
        ...,
        description="Identificador único del cliente (número de WhatsApp)",
        min_length=1,
        example="573001234567"
    )
    question: Optional[str] = Field(
        default=None,
        description="Texto de búsqueda. Opcional si next_page=true (se usa el query anterior)",
        example="cocinas de inducción"
    )
    limit: int = Field(
        default=5,
        description="Cantidad máxima de productos a retornar",
        ge=1,
        le=50
    )
    next_page: bool = Field(
        default=False,
        description="Si es true, carga la siguiente página de la búsqueda anterior automáticamente"
    )

    class Config:
        json_schema_extra = {
            "example": {
                "uuid_conversation": "573001234567",
                "question": "cocinas de inducción",
                "limit": 5
            }
        }


class ConversationChatResponse(BaseModel):
    """
    Response combinada: respuesta natural del LLM + lista de productos.
    """
    uuid_conversation: str = Field(..., description="Identificador del cliente")
    answer: str = Field(..., description="Respuesta generada por el modelo LLM")
    intent: Optional[str] = Field(default=None, description="Intención clasificada (PRODUCT, AGENT, PAYMENT, GREETING, OTHER)")
    total: int = Field(..., description="Cantidad de productos encontrados en esta página")
    has_more: bool = Field(default=False, description="Indica si hay más productos disponibles")
    redirect_asesor: bool = Field(default=False, description="Indica si la conversación fue redirigida a un asesor humano")
    products: List[ProductItem] = Field(default=[], description="Lista de productos encontrados")


class HealthResponse(BaseModel):
    """
    Response del endpoint de health check.
    """
    status: str = Field(default="ok", description="Estado del servicio")
    message: str = Field(default="Service is running", description="Mensaje de estado")


class XMLProductItem(BaseModel):
    """Producto parseado desde el XML de Marcimex."""
    product_id: Optional[str] = None
    sku_id: Optional[str] = None
    title: Optional[str] = None
    description: Optional[str] = None
    summary: Optional[str] = None
    category: Optional[str] = None
    global_category: Optional[str] = None
    sub_category: Optional[str] = None
    product_type: Optional[str] = None
    brand: Optional[str] = None
    rpx_code: Optional[str] = None
    link: Optional[str] = None
    image_link: Optional[str] = None
    price: Optional[str] = None
    in_stock: Optional[str] = None
    availability: Optional[str] = None
    status: Optional[str] = None
    color: Optional[str] = None
    specifications: Optional[str] = None
    short_link: Optional[str] = None
    status_product: Optional[ProductSyncStatusEnum] = None


class XMLProductsResponse(BaseModel):
    """Response con la lista de productos del XML."""
    total: int = Field(..., description="Total de productos parseados")
    source_url: str = Field(..., description="URL del XML fuente")
    updated_at: Optional[str] = Field(None, description="Fecha de actualización del XML")
    products: List[XMLProductItem] = Field(default=[], description="Lista de productos")


class SyncProductsResponse(BaseModel):
    """Response de sincronización de productos XML a Neo4j."""
    created: int = Field(..., description="Productos creados/actualizados en Neo4j")
    errors: int = Field(..., description="Errores durante la sincronización")
    total: int = Field(..., description="Total de productos procesados del XML")
    mode: str = Field(..., description="Modo de sincronización: initial_load o incremental_sync")
    previous_count: int = Field(default=0, description="Cantidad de productos previos en BD")
    new: int = Field(default=0, description="Productos nuevos (no existían en BD)")
    updated: int = Field(default=0, description="Productos actualizados (ya existían)")
    deleted: int = Field(default=0, description="Productos eliminados de Neo4j (no están en XML)")
    promotions_updated: int = Field(default=0, description="Productos actualizados a promotion=true")
    message: str = Field(..., description="Mensaje descriptivo del resultado")


class DocumentItem(BaseModel):
    """Documento genérico almacenado en Neo4j (FAQ, políticas, guías, etc.)."""
    id: Optional[str] = None
    doc_type: Optional[str] = None
    title: Optional[str] = None
    content: Optional[str] = None
    source: Optional[str] = None
    score: Optional[float] = None


class FaqSyncResponse(BaseModel):
    """Response de sincronización de FAQ a Neo4j."""
    created: int = Field(..., description="FAQs creadas en Neo4j")
    errors: int = Field(..., description="Errores durante la sincronización")
    total: int = Field(..., description="Total de FAQs procesadas")
    previous_count: int = Field(default=0, description="FAQs previas en BD")
    doc_type: str = Field(default="faq", description="Tipo de documento sincronizado")
    message: str = Field(..., description="Mensaje descriptivo del resultado")


# =============================================
# MODELOS PARA /chat/search (API externa)
# =============================================

class SearchProductInstallment(BaseModel):
    """Información de cuotas de un producto."""
    Value: Optional[float] = None
    InterestRate: Optional[float] = None
    TotalValuePlusInterestRate: Optional[float] = None
    NumberOfInstallments: Optional[int] = None
    Name: Optional[str] = None
    PaymentSystemName: Optional[str] = None


class SearchProductItem(BaseModel):
    """Producto retornado por la API externa de búsqueda."""
    productId: Optional[str] = None
    skuId: Optional[str] = None
    name: Optional[str] = None
    brand: Optional[str] = None
    category: Optional[str] = None
    link: Optional[str] = None
    price: Optional[str] = None
    image: Optional[str] = None
    specs: Optional[dict] = None
    promotion: bool = False
    # Campos extendidos de Neo4j
    description: Optional[str] = None
    summary: Optional[str] = None
    inStock: Optional[bool] = None
    availability: Optional[str] = None
    color: Optional[str] = None
    specifications: Optional[str] = None
    globalCategory: Optional[str] = None
    subCategory: Optional[str] = None
    productType: Optional[str] = None
    syncStatus: Optional[str] = None
    score: Optional[float] = None


class SearchChatRequest(BaseModel):
    """Request para el endpoint /chat/search."""
    uuid_conversation: str = Field(
        ...,
        description="Identificador único del cliente",
        min_length=1,
        example="573001234567"
    )
    question: Optional[str] = Field(
        default=None,
        description="Mensaje del usuario",
        example="cocina"
    )
    count: int = Field(
        default=6,
        description="Cantidad de productos a retornar",
        ge=1,
        le=50
    )
    resumePurchase: Optional[str] = Field(
        default=None,
        description="Nombres de los últimos productos vistos por el usuario (ya formateados). Se recomiendan si la conversación es nueva y el usuario saluda o pide recomendaciones."
    )
    platformId: Optional[str] = Field(
        default=None,
        description="Id de la platforma",
        example="593900000000"
    )
    usuario: Optional[str] = Field(
        default=None,
        description="Nick del usuario",
        example="Anonimus"
    )


class SearchChatResponse(BaseModel):
    """Response del endpoint /chat/search."""
    uuid_conversation: str = Field(..., description="Identificador del cliente")
    answer: str = Field(..., description="Respuesta generada por el agente")
    intent: Optional[str] = Field(default=None, description="Intención clasificada (PRODUCT, AGENT, PAYMENT, BALANCE, GREETING, OTHER)")
    total: int = Field(default=0, description="Cantidad de productos encontrados")
    redirect_asesor: bool = Field(default=False, description="Indica si la conversación fue redirigida a un asesor humano")
    summary_agent: Optional[str] = Field(default=None, description="Resumen de la conversación generado al redirigir a asesor (redirect_to_agent / redirect_to_agent_direct)")
    products: List[SearchProductItem] = Field(default=[], description="Lista de productos")


class ConversationAnalizeRequest(BaseModel):
    """Request del endpoint /chat/conversation-analize."""
    question: str = Field(..., description="Pregunta del usuario a analizar")


class ConversationAnalizeResponse(BaseModel):
    """Response del endpoint /chat/conversation-analize."""
    result: bool = Field(..., description="True si la pregunta es sobre productos o recomendaciones de productos")


class Neo4jSearchResponse(BaseModel):
    """Response del endpoint /products/search."""
    query: str
    total: int
    elapsed_s: float
    products: list
