import httpx
from typing import List, Optional, Dict, Any, Union
from dataclasses import dataclass
from .config import get_settings

# Modelos simples usando dataclasses (evita dependencias extra)
@dataclass
class Cliente:
    codigo: str
    nombre: str
    email: Optional[str] = None
    telefono: Optional[str] = None

@dataclass
class Proveedor:
    codigo: str
    nombre: str
    email: Optional[str] = None
    telefono: Optional[str] = None

@dataclass
class Documento:
    id: str
    tipo: str
    numero: str
    fecha: str
    importe: float
    estado: str

class ERPClientError(Exception):
    """Excepción personalizada para errores del ERP"""
    pass

class ERPClient:
    """Cliente para interactuar con la API del ERP utilizando la librería httpx (async)"""
    
    def __init__(self):
        self.settings = get_settings()
        self.base_url = self.settings.base_url
        self.headers = self.settings.headers
        self.timeout = self.settings.erp_timeout
        self.verify_ssl = self.settings.erp_ssl_verify
    
    async def _request(
        self, 
        method: str, 
        endpoint: str, 
        params: Optional[Dict] = None,
        json_data: Optional[Dict] = None
    ) -> Dict[str, Any]:
        """
        Método base para peticiones HTTP asíncronas usando httpx
        """
        url = f"{self.base_url.rstrip('/')}/{endpoint.lstrip('/')}"
        
        async with httpx.AsyncClient(verify=self.verify_ssl, timeout=self.timeout) as client:
            try:
                response = await client.request(
                    method=method,
                    url=url,
                    json=json_data,
                    params=params,
                    headers=self.headers
                )
                
                # Para depuración similar al print original
                # print(response.text, url)
                
                response.raise_for_status()
                return response.json()
                
            except httpx.HTTPStatusError as e:
                error_msg = f"Error HTTP {e.response.status_code}"
                try:
                    error_detail = e.response.json()
                    error_msg += f": {error_detail}"
                except:
                    error_msg += f": {e.response.text}"
                raise ERPClientError(error_msg)
                
            except httpx.RequestError as e:
                raise ERPClientError(f"Error de conexión o petición: {str(e)}")
    
    # === MÉTODOS ESPECÍFICOS DEL ERP ===
    
    async def buscar_clientes(self, nombre: str) -> List[Cliente]:
        """
        Busca clientes por nombre
        """
        try:
            result = await self._request(
                "POST", 
                "clientes/search",
                json_data={"nombre": nombre, "limite": 20}
            )
            clientes = []
            datos = result.get("data", result.get("clientes", []))
            
            for item in datos:
                cliente = Cliente(
                    codigo=item.get("codigo", item.get("id", "")),
                    nombre=item.get("nombre", item.get("razonSocial", "")),
                    email=item.get("email"),
                    telefono=item.get("telefono")
                )
                clientes.append(cliente)
            
            return clientes
            
        except ERPClientError as e:
            # En producción usaríamos logger, aquí mantenemos consistencia con el código original
            print(f"Error en buscar_clientes: {e}")
            return []
    
    async def buscar_proveedores(self, nombre: str) -> List[Proveedor]:
        """
        Busca proveedores por nombre
        """
        try:
            result = await self._request(
                "POST", 
                "proveedores/search",
                json_data={"nombre": nombre, "limite": 20}
            )
            
            proveedores = []
            datos = result.get("data", result.get("proveedores", []))
            
            for item in datos:
                proveedor = Proveedor(
                    codigo=item.get("codigo", item.get("id", "")),
                    nombre=item.get("nombre", item.get("razonSocial", "")),
                    email=item.get("email"),
                    telefono=item.get("telefono")
                )
                proveedores.append(proveedor)
            
            return proveedores
            
        except ERPClientError as e:
            print(f"Error en buscar_proveedores: {e}")
            return []
    
    async def obtener_documentos_cliente(self, codigo_cliente: str) -> List[Documento]:
        """
        Obtiene documentos de un cliente por su código
        """
        try:
            result = await self._request(
                "POST", 
                "clientes/documentos",
                json_data={"codigo": codigo_cliente, "limite": 20}
            )
            
            documentos = []
            datos = result.get("data", result.get("documentos", []))
            
            for item in datos:
                doc = Documento(
                    id=item.get("codigo", ""),
                    tipo=item.get("tipo", item.get("tipoDocumento", "")),
                    numero=item.get("numero", item.get("numeroDocumento", "")),
                    fecha=item.get("fecha", item.get("fechaEmision", "")),
                    importe=float(item.get("importe", item.get("total", 0))),
                    estado=item.get("estado", "")
                )
                documentos.append(doc)
            
            return documentos
            
        except ERPClientError as e:
            print(f"Error en obtener_documentos_cliente: {e}")
            return []
    
    async def obtener_documentos_proveedor(self, codigo_proveedor: str) -> List[Documento]:
        """
        Obtiene documentos de un proveedor por su código
        """
        try:
            result = await self._request(
                "POST", 
                "proveedores/documentos",
                json_data={"codigo": codigo_proveedor, "limite": 20}
            )
            
            documentos = []
            datos = result.get("data", result.get("documentos", []))
            
            for item in datos:
                doc = Documento(
                    id=item.get("codigo", ""),
                    tipo=item.get("tipo", item.get("tipoDocumento", "")),
                    numero=item.get("numero", item.get("numeroDocumento", "")),
                    fecha=item.get("fecha", item.get("fechaEmision", "")),
                    importe=float(item.get("importe", item.get("total", 0))),
                    estado=item.get("estado", "")
                )
                documentos.append(doc)
            
            return documentos
            
        except ERPClientError as e:
            print(f"Error en obtener_documentos_proveedor: {e}")
            return []
