"""
RAG服务层 - 提供可复用的业务逻辑（增强版）
用于CLI和MCP服务共享
支持后处理器、元数据过滤、批量查询和增量索引管理
"""
from typing import Optional, Dict, Any, List
from loguru import logger

from llama_index.core import Document

from src.core import RAGSystem
from src.config import get_config_manager, ConfigManager


class RAGService:
    """RAG服务 - 封装所有RAG相关的业务逻辑"""
    
    def __init__(self, config: Optional[ConfigManager] = None):
        """
        初始化RAG服务
        
        Args:
            config: 配置实例，如果为None则使用全局配置
        """
        self.config = config or get_config_manager()
        self.rag_system: Optional[RAGSystem] = None
    
    def _get_rag_system(self) -> RAGSystem:
        """
        获取RAGSystem实例（懒加载）
        
        Returns:
            RAGSystem实例
        """
        if self.rag_system is None:
            self.rag_system = RAGSystem(config=self.config)
        return self.rag_system
    
    def build_index(
        self, 
        data_dir: str, 
        force_rebuild: bool = False
    ) -> Dict[str, Any]:
        """
        构建知识库索引
        
        Args:
            data_dir: 文档目录路径
            force_rebuild: 是否强制重建索引
        
        Returns:
            包含构建结果的字典
        """
        try:
            logger.info(f"开始构建索引: data_dir={data_dir}, force_rebuild={force_rebuild}")
            
            rag = self._get_rag_system()
            success = rag.build_index(data_dir, force_rebuild)
            
            return {
                "success": success,
                "message": "索引构建成功" if success else "索引构建失败",
                "data_dir": data_dir,
                "force_rebuild": force_rebuild
            }
        
        except Exception as e:
            logger.error(f"构建索引失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc(),
                "data_dir": data_dir,
                "force_rebuild": force_rebuild
            }
    
    def query(
        self, 
        question: str, 
        mode: Optional[str] = None, 
        top_k: Optional[int] = None
    ) -> Dict[str, Any]:
        """
        查询知识库（使用LLM生成答案）
        
        Args:
            question: 用户问题
            mode: 检索模式 (vector/bm25/hybrid)
            top_k: 检索的文档数量
        
        Returns:
            包含查询结果的字典
        """
        try:
            logger.info(f"查询知识库: question={question}, mode={mode}, top_k={top_k}")
            
            rag = self._get_rag_system()
            result = rag.query(question=question, mode=mode, top_k=top_k)
            
            return result
        
        except Exception as e:
            logger.error(f"查询失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc(),
                "answer": None,
                "sources": [],
                "mode": mode or self.config.retrieval.mode
            }
    
    def retrieve(
        self,
        question: str,
        mode: Optional[str] = None,
        top_k: Optional[int] = None,
        similarity_cutoff: Optional[float] = None,
        use_reranker: Optional[bool] = None,
        metadata_filters: Optional[Dict] = None
    ) -> Dict[str, Any]:
        """
        检索相关文档（增强版，支持后处理器和元数据过滤）
        
        Args:
            question: 检索内容
            mode: 检索模式 (vector/bm25/hybrid)
            top_k: 检索的文档数量
            similarity_cutoff: 相似度阈值过滤
            use_reranker: 是否使用重排序
            metadata_filters: 元数据过滤条件
        
        Returns:
            包含检索结果的字典
        """
        try:
            logger.info(f"检索文档: question={question}, mode={mode}, top_k={top_k}")
            
            rag = self._get_rag_system()
            result = rag.retrieve(
                question=question,
                mode=mode,
                top_k=top_k,
                similarity_cutoff=similarity_cutoff,
                use_reranker=use_reranker,
                metadata_filters=metadata_filters
            )
            
            return result
        
        except Exception as e:
            logger.error(f"检索失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc(),
                "results": [],
                "mode": mode or "hybrid"
            }
    
    def get_status(self, verbose: bool = False) -> Dict[str, Any]:
        """
        获取系统状态信息
        
        Args:
            verbose: 是否返回详细信息
        
        Returns:
            包含状态信息的字典
        """
        try:
            logger.info(f"获取系统状态: verbose={verbose}")
            
            rag = self._get_rag_system()
            stats = rag.get_index_stats()
            
            return {
                "success": True,
                "stats": stats,
                "verbose": verbose
            }
        
        except Exception as e:
            logger.error(f"获取状态失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc(),
                "stats": {},
                "verbose": verbose
            }
    
    def delete_index(self, confirm: bool = False) -> Dict[str, Any]:
        """
        删除所有索引
        
        Args:
            confirm: 是否确认删除操作
        
        Returns:
            包含删除结果的字典
        """
        try:
            if not confirm:
                return {
                    "success": False,
                    "error": "必须设置 confirm=True 才能执行删除操作",
                    "warning": "此操作将删除所有索引且不可逆！"
                }
            
            logger.info("删除索引")
            
            rag = self._get_rag_system()
            success = rag.delete_index()
            
            return {
                "success": success,
                "message": "索引删除成功" if success else "索引删除失败"
            }
        
        except Exception as e:
            logger.error(f"删除索引失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc()
            }
    
    def get_config(self) -> Dict[str, Any]:
        """
        获取系统配置信息
        
        Returns:
            包含配置信息的字典
        """
        try:
            logger.info("获取系统配置")
            
            config_info = self.config.display()
            
            return {
                "success": True,
                "config": config_info
            }
        
        except Exception as e:
            logger.error(f"获取配置失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc(),
                "config": {}
            }
    
    def batch_retrieve(
        self,
        questions: List[str],
        mode: Optional[str] = None,
        top_k: Optional[int] = None
    ) -> Dict[str, Any]:
        """
        批量异步检索
        
        Args:
            questions: 问题列表
            mode: 检索模式
            top_k: 每个问题检索的文档数量
        
        Returns:
            包含批量检索结果的字典
        """
        try:
            logger.info(f"批量检索: {len(questions)} 个问题")
            
            rag = self._get_rag_system()
            result = rag.batch_query(questions=questions, mode=mode, top_k=top_k)
            
            return {
                "success": True,
                "results": result,
                "total_questions": len(questions)
            }
        
        except Exception as e:
            logger.error(f"批量检索失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc(),
                "results": []
            }
    
    def insert_documents(self, documents: List[Dict[str, Any]]) -> Dict[str, Any]:
        """
        插入新文档到索引
        
        Args:
            documents: 文档列表，每个文档包含text和metadata字段
        
        Returns:
            包含操作结果的字典
        """
        try:
            logger.info(f"插入文档: {len(documents)} 个")
            
            # 转换为Document对象
            doc_objects = []
            for doc in documents:
                doc_objects.append(
                    Document(
                        text=doc.get("text", ""),
                        metadata=doc.get("metadata", {})
                    )
                )
            
            rag = self._get_rag_system()
            result = rag.insert_documents(doc_objects)
            
            return result
        
        except Exception as e:
            logger.error(f"插入文档失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc()
            }
    
    def update_documents(self, documents: List[Dict[str, Any]]) -> Dict[str, Any]:
        """
        更新索引中的文档
        
        Args:
            documents: 文档列表，每个文档包含doc_id、text和metadata字段
        
        Returns:
            包含操作结果的字典
        """
        try:
            logger.info(f"更新文档: {len(documents)} 个")
            
            # 转换为Document对象
            doc_objects = []
            for doc in documents:
                doc_obj = Document(
                    text=doc.get("text", ""),
                    metadata=doc.get("metadata", {})
                )
                # 设置文档ID
                doc_obj.doc_id = doc.get("doc_id")
                doc_objects.append(doc_obj)
            
            rag = self._get_rag_system()
            result = rag.update_documents(doc_objects)
            
            return result
        
        except Exception as e:
            logger.error(f"更新文档失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc()
            }
    
    def delete_document(self, doc_id: str) -> Dict[str, Any]:
        """
        删除索引中的文档
        
        Args:
            doc_id: 文档ID
        
        Returns:
            包含操作结果的字典
        """
        try:
            logger.info(f"删除文档: {doc_id}")
            
            rag = self._get_rag_system()
            result = rag.delete_document(doc_id)
            
            return result
        
        except Exception as e:
            logger.error(f"删除文档失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc()
            }
    
    def get_document(self, doc_id: str) -> Dict[str, Any]:
        """
        获取索引中的文档
        
        Args:
            doc_id: 文档ID
        
        Returns:
            包含文档信息的字典
        """
        try:
            logger.info(f"获取文档: {doc_id}")
            
            rag = self._get_rag_system()
            result = rag.get_document(doc_id)
            
            return result
        
        except Exception as e:
            logger.error(f"获取文档失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc()
            }
    
    def list_documents(self, limit: int = 100) -> Dict[str, Any]:
        """
        列出索引中的所有文档
        
        Args:
            limit: 返回的文档数量限制
        
        Returns:
            包含文档列表的字典
        """
        try:
            logger.info(f"列出文档: limit={limit}")
            
            rag = self._get_rag_system()
            result = rag.list_documents()
            
            # 应用限制
            if result.get("success") and result.get("documents"):
                documents = result["documents"][:limit]
                result["documents"] = documents
                result["returned_count"] = len(documents)
            
            return result
        
        except Exception as e:
            logger.error(f"列出文档失败: {e}")
            import traceback
            logger.error(traceback.format_exc())
            
            return {
                "success": False,
                "error": str(e),
                "traceback": traceback.format_exc(),
                "documents": []
            }
    
    @staticmethod
    def create() -> "RAGService":
        """
        创建RAGService实例的工厂方法
        
        Returns:
            RAGService实例
        """
        return RAGService()
