from pydantic import BaseModel, validator
from datetime import datetime
from fastapi import UploadFile

from typing import Any, Dict, Union, Optional,List

class CuentaRequest(BaseModel):
    id_cuenta: Union[str, int]
    
class LoginRequest(BaseModel):
    email: str
    password: str

class CuentaServicioRequest(BaseModel):
    id_cuenta: Union[str, int]
    dato: str
    valor: str
    
class AssistantsEmpresaRequest(BaseModel):
    id_empresa: Union[str, int]
    
class obtenerPqrsfPorEncargadoRequest(BaseModel):
    id_encargado: Union[str, int]

class obtenerPqrsfVencidasPorEncargadoRequest(BaseModel):
    id_encargado: Union[str, int]

class obtenerPqrsfProximasAVencerPorEncargadoRequest(BaseModel):
    id_encargado: Union[str, int]

class obtenerTodasPqrsfPorEncargadoRequest(BaseModel):
    id_encargado: Union[str, int]

class obtenerPqrsfResueltasPorEncargadoRequest(BaseModel):
    id_encargado: Union[str, int]

class obtenerPqrsfPendientesPorEncargadoRequest(BaseModel):
    id_encargado: Union[str, int]
    
class obtenerPqrsfEnProcesoPorEncargadoRequest(BaseModel):
    id_encargado: Union[str, int]

class obtenerPqrsfPorMedioDeLlegadaRequest(BaseModel):
   medio_llegada: str
   
class ActualizarGeneralInformationRequest(BaseModel):
    nombre: str
    tipo_doc: str
    documento: Union[str, int]
    correo: str
    telefono: str
    direccion: str
class AssistantsAsistentesRequest(BaseModel):
    idEmpresa: Union[str, int]

class codigoTemporalRequest(BaseModel):
    email: str
    
class NuevoEmpleadoRequest(BaseModel):
    nombres: str
    apellidos: str
    tipo_doc: str
    documento: str
    id_area: int
    id_cargo: int
    correo_corporativo: str
    correo_alterno: str
    telefono: str
    direccion: str
    status: int
    idperfil: int
    
    
class adjuntoFidelizacion(BaseModel):
    id_contacto_union: int
    id_agente_creador: int
    asunto: str
    descripcion: str
    fecha_hora: str
    id_agente_asignado: int
    
    
    
class NuevoPerfilRequest(BaseModel):
    perfiles: str  
    descripcion: str    
    status: int
    
class NuevoLogPqrsfRequest(BaseModel):
    id_pqrsf: int          
    evento: str            
    descripcion: str      
    id_usuario: int 
    
class NuevoAreaRequest(BaseModel):
    area: str        
    descripcion: str  
    
class NuevoCargoRequest(BaseModel):
    cargo: str        
    descripcion: str  
    idArea: int    
class NuevoPermisoRequest(BaseModel):
    id_perfil: int       
    id_modulo: int       
    id_vista: int          
    id_elemento: Optional[Union[int, str]] = None     
    permiso: str    
    
class NuevoTipoPqrsfRequest(BaseModel):
    categoria_id: int            
    tipo_pqrsf: str                
    area_encargada_id: Optional[int]         
    usuario_encargado_id: int  
    respuesta_ia: Optional[str]   
    tiempo_respuesta: int         
    archivo_adjunto: str  
    tipo_archivo: str      
    status: int       

class NuevoApiInventarioRequest(BaseModel):
    endpoint: str                
    url: str 
    token: str                  
    usuario: str
    contrasena: str 
    status: int         
    
class obtenerTipoPqrsfConFuentesRequest(BaseModel):
    id_pqrsf_tipo: int
    
class insertarTipoPqrsfFuenteRequest(BaseModel):
    id_pqrsf_tipo: int
    id_fuente_datos: int

class insertarFuenteDatosRequest(BaseModel):
    nombre: str
    tipo: str
    ubicacion: str
    descripcion: str
    
class EnviarWhatsappRequest(BaseModel):
    campana_id: int       
    numero_enviar: str  
    variables: Dict[str, Any]  
    
class obtenerAdjuntosMesaAyudaRequest(BaseModel):
    id_mesa_ayuda: int

class obtenerPqrsfResueltasPorMesRequest(BaseModel):
    mes: str

class obtenerPqrsfPendientesPorMesRequest(BaseModel):
    mes: str

class MarcarLeidaRequest(BaseModel):
    notificationId: int  
    user_id: int        

class MarcarTodasLeidasRequest(BaseModel):  
    user_id: int        
    
class NuevoCuentaServicioRequest(BaseModel):
    tipo_cuenta: str   
    status: int  

class EnviarCorreoEmpleadoRequest(BaseModel):
    user: str         
    email: str   
    codigo: Union[str, int] 
    
class EnviarCorreoPQRRequest(BaseModel):
    ciudadano: str             
    correos: str          
    categoria: str            
    tipo_pqrsf: str           
    estado: str                
    fecha_respuesta: Optional[Union[str, int]]
    num_radicado: str
    
class EnviarCorreoSoporteRequest(BaseModel):
    asunto: str
    observacion: str
    nombre: str
    modulo_name: str 
    vista_name: str       
    
class SendWhatsappPqrsfRequest(BaseModel):
    telefono: str        
    ciudadano: str       
    num_radicado: str    
    estado: str    
    
class CrearRespuestaSinRegistroRequest(BaseModel):
    asistente: int  
    respuesta: str 
    
class SoporteDataRequest(BaseModel):
    prioridad: str
    modulo: int
    vista: int
    asunto: str
    id_empleado: int
    observacion: str   
    
###########################################CLASES PARA SOLICITUDES PUT####################################################
class ActualizarUsuarioRequest(BaseModel):
    nombres: str            
    apellidos: str             
    tipo_doc: str             
    documento: str            
    id_cargo: int              
    correo_corporativo: str  
    correo_alterno: str 
    telefono: str  
    direccion: str             
    status: str
    nomstatus: str
    
class ActualizarPerfilRequest(BaseModel):
    nombres: str              
    apellidos: str         
    tipo_doc: str             
    documento: str            
    correo_corporativo: str  
    correo_alterno: str
    telefono: str
    direccion: str
    id_cargo: Optional[int] = None
    id_area: Optional[int] = None            
    status: Union[str, int]
    
    
class ActualizarNoticiaRequest(BaseModel):
    id: int                # ID de la noticia (obligatorio)
    principal: int         # Indicador de si es principal (1 o 0)
    fecha_noticia: str    # Fecha de la noticia (tipo `date`)
    titulo: str            # Título de la noticia
    texto_corto: str       # Resumen de la noticia (texto corto)
    texto_largo: str       # Descripción larga de la noticia
    link: str              # Enlace asociado con la noticia
    adjunto: Optional[UploadFile] = None
    
    

class ActualizarEmpleadoRequest(BaseModel):
    nombres: str              
    apellidos: str         
    tipo_doc: str             
    documento: str            
    correo_corporativo: str  
    correo_alterno: str
    telefono: str
    direccion: str
    id_cargo: int
    id_area: int               
    idperfil: int               
    status: Union[str, int]
    nomstatus: str
    id: int

class ActualizarEmpleadoPerfilRequest(BaseModel):
    perfiles: str              
    descripcion: str         
    status: Union[str, int]          

class ActualizarRespuestaRequest(BaseModel):
    respuesta: str              

class ActualizarAreaRequest(BaseModel):
    area: str
    descripcion: str              

class ActualizarCargoRequest(BaseModel):
    cargo: str
    descripcion: str      
    idArea:int        
    
class ActualizarContraseñaRequest(BaseModel):
    newPassword: str 
    
class ActualizarPermisoRequest(BaseModel):
    id_perfil: int              
    id_modulo: int         
    id_vista: int             
    id_elemento: Optional[int] = None            
    permiso: str  
class ActualizarDatosAsistente(BaseModel):
    idempresa: Union[str, int] 
    nombre: Union[str, int] 
    descripcion: Union[str, int] 
    imgurl: Union[str, int] 
    id: Union[str, int] 
    empresa: Union[str, int]
class ActualizarEstadoAsistente(BaseModel):
    status: int

class ActualizarMesaAyudaRequest(BaseModel):
    id_reporte: int          
    respuesta: str           
    id_empleado: int         
    status: int              
    fecha_respuesta: str  
    
class ActualizarTipoPqrsfRequest(BaseModel):
    id: int                    
    categoria_id: int          
    tipo_pqrsf: str            
    area_encargada_id: Optional[int]   
    usuario_encargado_id: int  
    respuesta_ia: Optional[str]
    tiempo_respuesta: Union[str, int]
    archivo_adjunto: str 
    tipo_archivo: str     
    status: Union[str, int]  
    
class ActualizarApiInventarioRequest(BaseModel):
    id: int                 
    endpoint: str      
    url: str
    token: str
    usuario: str
    contrasena: str 
    status: Union[str, int]          
    

class actualizarTipoPqrsfFuenteRequest(BaseModel):
    id: int                 
    id_fuente_datos: Union[str, int]     

class actualizarStatusCampanaRequest(BaseModel):
    id: int                 
    campana_status: Union[str, int]     
    
class ActualizarStatusPqrsfRequest(BaseModel):
    id_pqrsf: int           
    status: str            
    respuesta: str         
    fecha_respuesta: str
    id_encargado: int
    
class ActualizarPqrsfRequest(BaseModel):
    id: int           
    id_tipo_pqrs: int            
    id_encargado: int  
    status: int      
    
class actualizarRutaAssetLandingRequest(BaseModel):
    id: int           
    ruta: str   
    
class actualizarCuentaServicioRequest(BaseModel):
    id: int           
    tipo_cuenta: str            
    status: Union[str, int]     
    
class actualizarCuentadeServicioRequest(BaseModel):
    id: int           
    dato: str            
    valor: str    
    
class updateRespuestaSinRegistroRequest(BaseModel):
    asistente: int           
    respuesta: str  
# Subclase para la actualización de parámetros
class ParamsUpdateData(BaseModel):
    modelo_predeterminado: str
    modelo_actual: Union[str, int] 
    archivos: Union[str, int] 
    codigo: Union[str, int] 
    instruccion_saludo_despedida: str
    instruccion_personalidad: str
    instrucciones: str
    restricciones: str
    uupdateType: str = "params"

class FeatureUpdateData(BaseModel):
    modelo_actual: Union[str, int] 
    cambiar_modelo: Union[str, int] 
    openai: Union[str, int] 
    anthropic: Union[str, int] 
    google: Union[str, int] 
    llama: Union[str, int] 
    cic: Union[str, int] 
    escuchar: Union[str, int] 
    hablar: Union[str, int] 
    uupdateType: str = "features"

class VoiceUpdateData(BaseModel):
    id_modelo_voz: Union[str, int]
    similarity_boost: str
    stability: str
    style: str
    use_speaker_boost: Union[str, int] 
    optimize_streaming_latency: Union[str, int]
    uupdateType: str = "voice" 
class NotifyNewData(BaseModel):
  type: Union[str, int]
  message: Union[str, int]
  data: Union[Dict[str, Any], List[Any]]

class Funcion(BaseModel):
    name: str
    description: str
    strict: bool
    parameters: Dict[str, Any]

class FuncionOpenIARequest(BaseModel):
  id_asistente: int
  funcion: Funcion


""" class ActualizarPerfilRequest(BaseModel):
    nombres: str
    apellidos: str
    tipo_doc: str
    documento: str
    correo_corporativo: str
    correo_alterno: str
    telefono: str
    direccion: str
    id_area: int
    id_cargo: int
    status: str """
    

class Prospecto(BaseModel):
    # Campos básicos
    id: int
    fecha_registro: Optional[str] = None
    
    # 🔧 USAR NOMBRES REALES DE LA BASE DE DATOS
    nombre_embajador: Optional[str] = None
    nombres: Optional[str] = None
    apellidos: Optional[str] = None
    tipo_documento: Optional[str] = None
    documento: Optional[str] = None
    correos: Optional[str] = None
    telefono: Optional[str] = None
    pais: Optional[str] = None
    departamento: Optional[str] = None
    ciudad: Optional[str] = None
    localidad: Optional[str] = None
    barrio: Optional[str] = None
    direccion: Optional[str] = None
    fecha_cumpleanos: Optional[str] = None
    genero: Optional[str] = None
    tipo_sangre: Optional[str] = None
    nombre_recomendador: Optional[str] = None
    grupo_wp: Optional[str] = None
    grupo_wp1: Optional[str] = None
    como_ayudar: Optional[str] = None
    pasion: Optional[str] = None
    intereses: Optional[str] = None
    autorizacion: Optional[str] = None
    estado_etapa: Optional[int] = None
    id_notificacion_contacto: Optional[int] = None
    id_origen_datos: Optional[int] = None
    origen_datos: Optional[str] = None
    fecha_registro_contacto: Optional[str] = None
    recomendado: Optional[str] = None
    
    # Campos adicionales que pueden no estar en BD pero el frontend los espera
    contacto_exitoso: Optional[str] = None
    duracion_llamada: Optional[str] = None
    desea_participar_capacitacion: Optional[str] = None
    tiene_grupo_ciudadanos: Optional[str] = None
    compromiso_firmas: Optional[str] = None
    desea_conocer_sede: Optional[str] = None
    requiere_material_apoyo: Optional[str] = None
    desea_recibir_credencial: Optional[str] = None
    desea_invitar_otras_personas: Optional[str] = None
    nivel_satisfaccion_llamada: Optional[int] = None
    observaciones_adicionales: Optional[str] = None
    mensaje_whatsapp_enviado: Optional[str] = None
    razon_no_respondio: Optional[str] = None



# Para los parámetros de solicitud
class ListProspectosRequest(BaseModel):
    page: Optional[int] = 1
    pageSize: Optional[int] = 5

# Para la respuesta
class ListProspectosResponse(BaseModel):
    success: bool
    message: str
    data: List[Prospecto]
    totalRecords: int
    totalPages: int
    currentPage: int
    pageSize: int
    hasNextPage: bool
    hasPrevPage: bool

class Encuestado(BaseModel):
    id: int
    tipo_documento: Optional[str]
    documento: Optional[str]
    nombres: Optional[str]
    apellidos: Optional[str]
    correos: Optional[str]
    telefono: Optional[str]
    pais: Optional[str]
    departamento: Optional[str]
    ciudad: Optional[str]
    direccion: Optional[str]
    genero: Optional[str]
    recomendado: Optional[str]
    nombre_recomendador: Optional[str]
    grupo_wp: Optional[str]
    grupo_wp1: Optional[str]
    como_ayudar: Optional[str]
    pasion: Optional[str]
    fecha_registro: Optional[datetime]

class ListEncuestadosResponse(BaseModel):
    success: bool
    message: str
    data: List[Encuestado] 
    totalRecords: int
    totalPages: int
    currentPage: int

class ListEncuestadosRequest(BaseModel):
    fecha: Optional[str] = None  # Formato YYYY-MM-DD
    page: Optional[int] = 1
    pageSize: Optional[int] = 5


class TablaSeleccionadaRequest(BaseModel):
    tablaSeleccionada: str
    page: Optional[int] = 1
    pageSize: Optional[int] = 5

class TablaSeleccionadaResponse(BaseModel):
    success: bool
    message: str
    data: List[dict]
    totalRecords: int
    totalPages: int
    currentPage: int    
    
    
class VoluntarioUpdateRequest(BaseModel):
    tipo_documento: Optional[str] = None  
    documento: Optional[str] = None 
    nombres: Optional[str] = None 
    apellidos: Optional[str] = None 
    correos: Optional[str] = None 
    telefono: Optional[str] = None 
    pais: Optional[str] = None 
    departamento: Optional[str] = None 
    ciudad: Optional[str] = None 
    direccion: Optional[str] = None 
    genero: Optional[str] = None 
    recomendado: Optional[str] = None 
    nombre_recomendador: Optional[str] = None 
    grupo_wp: Optional[str] = None 
    grupo_wp1: Optional[str] = None 
    como_ayudar: Optional[str] = None 
    pasion: Optional[str] = None 
    nombres_completos:  Optional[str] = None, 
    intereses: Optional[str] = None, 
    autorizacion: Optional[str] = None, 
    barrio: Optional[str] = None, 
    fecha_cumpleanos: Optional[str] = None, 
    tipo_sangre: Optional[str] = None, 
    fecha_registro: Optional[str] = None 
    localidad: Optional[str] = None 

    
    nombre_tabla: Optional[str]

class CreateNotesRequest(BaseModel):
    id_empleado: int
    id_contacto_union: int
    id_contacto_origen: Optional[int] = None
    origen_datos: Optional[str] = None
    id_estado_etapa: Optional[int] = None
    nota: str
    
    @validator('id_estado_etapa', pre=True)
    def empty_str_to_none(cls, v):
        if v in ("", "undefined", "null"):
            return None
        return v

class CreateNotesResponse(BaseModel):
    success: int
    message: str

class PrimerContactoRequest(BaseModel):
    nombre_embajador: Optional[str] = None
    nombre_completo_referido: Optional[str] = None
    numero_cedula: Optional[str] = None
    numero_contacto_whatsapp: Optional[str] = None
    participa_grupos: Optional[str] = None
    aporta_recoleccion_firmas: Optional[str] = None
    participa_capacitacion_virtual: Optional[str] = None
    horario_capacitacion: Optional[str] = None
    requiere_material_apoyo: Optional[str] = None
    ciudad_principal: Optional[str] = None
    localidad_barrio: Optional[str] = None
    representa_grupo_ciudadanos: Optional[str] = None
    observaciones_adicionales: Optional[str] = None
    credencial: Optional[str] = None
    nivel_simpatia_satisfaccion: Optional[Union[int, str]] = None
    duracion_llamada_minutos: Optional[Union[int, str]] = None
    temporizador_proceso: Optional[str] = None
    id_union_contactos_personas: Optional[int] = None

class EnviarCorreoRequest(BaseModel):
    nombre_completo_referido: str
    correo_referido: str
    nombre_embajador: Optional[str] = "Equipo Imparables"

class NuevoContactoRequest(BaseModel):
    id: int
    fecha_registro: Optional[str] = None
    id_embajador: int
    nombre_embajador: str
    nombres_completos: Optional[str] = None
    nombres: str
    apellidos: str
    tipo_documento: Optional[str] = None
    documento: Optional[str] = None
    correos: str
    telefono: str
    pais: Optional[str] = None
    departamento: Optional[str] = None
    ciudad: Optional[str] = None
    localidad: Optional[str] = None
    barrio: Optional[str] = None
    direccion: Optional[str] = None
    fecha_cumpleanos: Optional[str] = None
    genero: Optional[str] = None
    tipo_sangre: Optional[str] = None
    recomendado: Optional[str] = None
    nombre_recomendador: Optional[str] = None
    grupo_wp: Optional[str] = None
    grupo_wp1: Optional[str] = None
    como_ayudar: Optional[str] = None
    pasion: Optional[str] = None
    intereses: Optional[str] = None
    autorizacion: Optional[str] = None
    estado_etapa: Optional[int] = None
    nombreTabla: str
    fecha_registro_contacto: str
    tiempo_primer_contacto: str
    noQuisoParticipar: Optional[bool] = None


class TareaSchema(BaseModel):
    id: int
    tarea: str
    descripcion: str

    class Config:
        orm_mode = True
        
class updateContacto(BaseModel):
    fecha_registro: Optional[str] = None
    nombre_embajador: Optional[str] = None
    nombre_recomendador: Optional[str] = None
    nombres: Optional[str] = None
    apellidos: Optional[str] = None
    tipo_documento: Optional[str] = None
    documento: Optional[str] = None
    correos: Optional[str] = None
    telefono: Optional[str] = None
    pais: Optional[str] = None
    departamento: Optional[str] = None
    ciudad: Optional[str] = None
    localidad: Optional[str] = None
    barrio: Optional[str] = None
    direccion: Optional[str] = None
    fecha_cumpleanos: Optional[str] = None
    genero: Optional[str] = None
    tipo_sangre: Optional[str] = None
    recomendado: Optional[str] = None
    nombre_recomendador: Optional[str] = None
    grupo_wp: Optional[str] = None
    grupo_wp1: Optional[str] = None
    como_ayudar: Optional[str] = None
    pasion: Optional[str] = None
    intereses: Optional[str] = None
    autorizacion: Optional[str] = None
    estado_etapa: Optional[int] = None
    origen_datos: Optional[str] = None
    fecha_registro_contacto: Optional[str] = None
    tiempo_primer_contacto: Optional[str] = None


class verificacionContactadoRequest(BaseModel):
    documento: str
    correos: str
    telefono: str
    idOrigenDato: int
    nombreTabla: str



class actualizarEstadoEtapaRequest(BaseModel):
    id: int
    origen_datos: str
    estado_etapa: int



class agregarNuevoProspectoRequest(BaseModel):
    nombreTabla: str
    nombres: str
    apellidos: str
    documento: str
    correos: str
    telefono: str
    tipo_documento: Optional[str] = None
    departamento: Optional[str] = None
    ciudad: Optional[str] = None
    estado_etapa: Optional[int] = None
    genero: Optional[str] = None
    fecha_registro: Optional[str] = None
    intereses: Optional[str] = None
    autorizacion: Optional[str] = None
    pais: Optional[str] = None
    direccion: Optional[str] = None
    recomendado: Optional[str] = None
    nombre_recomendador: Optional[str] = None
    grupo_wp: Optional[str] = None
    grupo_wp1: Optional[str] = None
    como_ayudar: Optional[str] = None
    pasion: Optional[str] = None
    localidad: Optional[str] = None
    barrio: Optional[str] = None
    fecha_cumpleanos: Optional[str] = None
    tipo_sangre: Optional[str] = None


class ObtenerRecordatoriosRequest(BaseModel):
    id_contacto_union: int



# ---------- MODELOS PARA /ask/obtenerUrlFirmada ----------
class ObtenerUrlFirmadaRequest(BaseModel):
    s3_key: str

class ObtenerUrlFirmadaResponse(BaseModel):
    success: bool
    url_firmada: str

class ObtenerUrlFirmadaError(BaseModel):
    success: bool
    message: str


# ---------- MODELOS PARA /ask/obtenerPropuestasCrm ----------
class ObtenerPropuestasCrmRequest(BaseModel):
    page: int = 1
    pageSize: int = 10

class PropuestaCrm(BaseModel):
    id: int
    nombre_completo: str
    correo: str
    tipo_documento: str
    documento: str
    telefono: str
    ciudad: str
    titulo: str
    ambito: str
    descripcion: str
    fecha_hora: Optional[str] = None
    archivos_adjuntos: List[dict] = []

class ObtenerPropuestasCrmResponse(BaseModel):
    success: bool
    message: str
    data: List[PropuestaCrm]
    totalRecords: int
    totalPages: int
    currentPage: int

class ObtenerPropuestasCrmError(BaseModel):
    success: bool
    message: str


class ProcesamientoResponse(BaseModel):
    success: bool
    message: str
    data: Optional[Any] = None

class ProcesamientoError(BaseModel):
    detail: str



class TablaSeleccionadaMarketingRequest(BaseModel):
    tipo_contacto: str
    tablaSeleccionada: str
    page: Optional[int] = 1
    pageSize: Optional[int] = 5


class BusquedaPorCamposDinamicosRequest(BaseModel):
    tipo_contacto: str
    tablaSeleccionada: str
    page: Optional[int] = 1
    pageSize: Optional[int] = 5
    campos: dict


class ActualizarEstadoEtapa(BaseModel):
    estado_etapa: int



class NuevaPreguntaRequest(BaseModel):
    id_enc : int
    pregunta : str
    tipo_pregunta : int
    obligatorio : int


class NuevaEncuestaRequest(BaseModel):
    nombre_encuesta : str
    categoria : int
    fecha_vencimiento : str
    status : int
    usuario : int
    
class ObtenerExcelRequest(BaseModel):
    rows: List[Dict[str, Any]]
