"""
统一错误处理装饰器模块
提供标准化的错误处理和日志记录
"""
import functools
import traceback
from typing import Callable, Any, Optional, Dict
from loguru import logger


def handle_errors(
    operation_name: str,
    return_on_error: Optional[Any] = None,
    log_traceback: bool = True,
    suppress_exception: bool = False
):
    """
    统一错误处理装饰器
    
    Args:
        operation_name: 操作名称，用于日志记录
        return_on_error: 发生错误时的返回值
        log_traceback: 是否记录完整的堆栈跟踪
        suppress_exception: 是否抑制异常（False会重新抛出）
        
    Example:
        @handle_errors("查询操作", return_on_error={"success": False})
        def query(self, question: str):
            ...
    """
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                logger.error(f"{operation_name}失败: {e}")
                if log_traceback:
                    logger.error(traceback.format_exc())
                
                if suppress_exception:
                    return return_on_error
                else:
                    raise
        
        return wrapper
    return decorator


def log_execution(operation_name: str, log_args: bool = False):
    """
    记录函数执行的装饰器
    
    Args:
        operation_name: 操作名称
        log_args: 是否记录函数参数
        
    Example:
        @log_execution("创建索引", log_args=True)
        def create_index(self, documents):
            ...
    """
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            if log_args:
                logger.info(f"开始 {operation_name} - 参数: args={args[1:]}, kwargs={kwargs}")
            else:
                logger.info(f"开始 {operation_name}")
            
            try:
                result = func(*args, **kwargs)
                logger.info(f"✅ {operation_name} 完成")
                return result
            except Exception as e:
                logger.error(f"❌ {operation_name} 失败: {e}")
                raise
        
        return wrapper
    return decorator


def handle_query_errors(func: Callable) -> Callable:
    """
    专门用于查询/检索操作的错误处理装饰器
    返回标准化的结果字典
    
    Example:
        @handle_query_errors
        def execute_query(self, query_engine, question: str, mode: str):
            ...
    """
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            logger.error(f"查询失败: {e}")
            logger.error(traceback.format_exc())
            
            # 尝试从函数参数中提取mode
            mode = kwargs.get('mode', 'unknown')
            if not mode and len(args) > 2:
                mode = args[2] if isinstance(args[2], str) else 'unknown'
            
            return {
                "success": False,
                "error": str(e),
                "answer": None,
                "sources": [],
                "mode": mode
            }
    
    return wrapper


def handle_retrieval_errors(func: Callable) -> Callable:
    """
    专门用于检索操作的错误处理装饰器
    返回标准化的结果字典
    
    Example:
        @handle_retrieval_errors
        def execute_retrieve(self, retriever, question: str, mode: str):
            ...
    """
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            logger.error(f"检索失败: {e}")
            logger.error(traceback.format_exc())
            
            # 尝试从函数参数中提取mode
            mode = kwargs.get('mode', 'unknown')
            if not mode and len(args) > 2:
                mode = args[2] if isinstance(args[2], str) else 'unknown'
            
            return {
                "success": False,
                "error": str(e),
                "results": [],
                "mode": mode
            }
    
    return wrapper


def retry_on_failure(max_retries: int = 3, delay: float = 1.0):
    """
    失败重试装饰器
    
    Args:
        max_retries: 最大重试次数
        delay: 重试间隔（秒）
        
    Example:
        @retry_on_failure(max_retries=3, delay=2.0)
        def unstable_operation(self):
            ...
    """
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            import time
            
            last_exception = None
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    last_exception = e
                    if attempt < max_retries - 1:
                        logger.warning(f"操作失败，{delay}秒后重试 (尝试 {attempt + 1}/{max_retries}): {e}")
                        time.sleep(delay)
                    else:
                        logger.error(f"操作失败，已达到最大重试次数 ({max_retries}): {e}")
            
            # 重试全部失败，抛出最后的异常
            raise last_exception
        
        return wrapper
    return decorator
