"""
GraphRAG Retriever para consultas sobre productos retail y políticas de tienda.
"""

from typing import List, Dict, Any, Optional
from .neo4j_client import neo4j_client
from .embeddings_service import embeddings_service
from config.settings import settings
import logging
logger = logging.getLogger(__name__)



class GraphRAGRetriever:
    """Retriever GraphRAG para Retail."""
    
    def __init__(self):
        self.neo4j = neo4j_client
        self.embeddings = embeddings_service
        self.max_results = settings.GRAPHRAG_MAX_RESULTS
        
    def _determine_query_type(self, query: str) -> str:
        """
        Determina el tipo de consulta: producto, política, o general.
        """
        query_lower = query.lower()
        
        policy_keywords = [
            "garantía", "garantia", "devolución", "cambio", "reembolso", "política",
            "envío", "costo de envío", "servicio técnico", "instalación", "manual",
            "horario", "tienda", "ubicación", "crédito", "intereses"
        ]
        
        product_keywords = [
            "precio", "cuesta", "vale", "características", "especificaciones",
            "pulgadas", "litros", "marca", "modelo", "color", "tamaño",
            "diferencia", "comparar", "mejor", "barato", "oferta"
        ]
        
        policy_score = sum(1 for kw in policy_keywords if kw in query_lower)
        product_score = sum(1 for kw in product_keywords if kw in query_lower)
        
        if policy_score > 0:
            return 'store_policy'
        elif product_score > 0:
            return 'product_info'
        else:
            return 'general' # Probablemente búsqueda de producto por nombre simple
    
    def retrieve(
        self,
        query: str,
        filters: Optional[Dict[str, Any]] = None,
        top_k: Optional[int] = None
    ) -> List[Dict[str, Any]]:
        """
        Recupera información relevante del grafo Neo4j.
        """
        try:
            if not self.neo4j.connect():
                logger.error("❌ No se pudo conectar a Neo4j")
                return []
            
            filters = filters or {}
            limit = top_k or self.max_results
            query_type = self._determine_query_type(query)
            logger.info(f"🎯 Tipo de query RAG: {query_type}")
            
            results = []
            
            if query_type == 'store_policy':
                # Búsqueda vectorial o de palabras clave en nodos de Política
                # Simularemos búsqueda fulltext por ahora
                results = self.neo4j.search_policies(query, limit)
            
            elif query_type == 'product_info' or query_type == 'general':
                # Búsqueda híbrida de productos
                results = self.neo4j.fulltext_search_products(query, limit)
                
                # Si tenemos un producto específico en contexto (por filtros), buscar sus detalles
                product_id = filters.get('product_id')
                if product_id:
                     context = self.neo4j.get_product_context(product_id)
                     if context: results.insert(0, context)
            
            logger.info(f"✅ Recuperados {len(results)} resultados de Neo4j")
            return results
            
        except Exception as e:
            logger.error(f"❌ Error en retrieve: {e}")
            return []
    
    def format_context(self, results: List[Dict[str, Any]], query_type: str = 'general') -> str:
        """
        Formatea resultados del grafo para el LLM.
        """
        if not results:
            return "No se encontró información relevante en el catálogo."
        
        context_parts = []
        
        for idx, result in enumerate(results, 1):
            if 'p' in result: # Nodo producto
                context_parts.append(self._format_product_context(result))
            elif 'policy' in result:
                 context_parts.append(f"📜 POLÍTICA: {result['policy'].get('text', '')}")
            elif 'name' in result: # Resultado simple
                 context_parts.append(self._format_product_basic(result))
            else:
                context_parts.append(str(result))
        
        return "\n---\n".join(context_parts)
    
    def _format_product_context(self, context: Dict[str, Any]) -> str:
        p = context.get('p', {})
        c = context.get('c', {})
        b = context.get('b', {})
        
        parts = [
            f"📦 **{p.get('name', 'Producto')}**",
            f"💰 Precio: ${p.get('price', 'N/A')}",
            f"🏷️ Categoría: {c.get('name', 'General')}",
            f"🏭 Marca: {b.get('name', 'Genérica')}",
            f"📝 Descripción: {p.get('description', '')}"
        ]
        
        features = context.get('features', [])
        if features:
            parts.append("\n**Características:**")
            for f in features:
                if f and 'name' in f: parts.append(f"- {f['name']}: {f.get('value', 'Sí')}")
                
        return "\n".join(parts)

    def _format_product_basic(self, p: Dict[str, Any]) -> str:
        return f"📦 {p.get('name')} - ${p.get('price')} - {p.get('description', '')[:100]}..."

    def query(self, query: str, filters: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        query_type = self._determine_query_type(query)
        results = self.retrieve(query=query, filters=filters)
        context = self.format_context(results, query_type)
        return {
            "query": query,
            "results": results,
            "context": context,
            "query_type": query_type
        }

graph_rag_retriever = GraphRAGRetriever()
