"""重试策略模块"""
import logging
import time
from typing import Callable, Any, Type, Tuple

logger = logging.getLogger(__name__)


class RetryStrategy:
    """重试策略
    
    支持指数退避的重试机制
    """
    
    def __init__(
        self,
        max_retries: int = 3,
        initial_delay: float = 1.0,
        max_delay: float = 60.0,
        exponential_base: float = 2.0,
        exceptions: Tuple[Type[Exception], ...] = (Exception,)
    ):
        """初始化重试策略
        
        Args:
            max_retries: 最大重试次数
            initial_delay: 初始延迟时间（秒）
            max_delay: 最大延迟时间（秒）
            exponential_base: 指数退避基数
            exceptions: 需要重试的异常类型元组
        """
        self.max_retries = max_retries
        self.initial_delay = initial_delay
        self.max_delay = max_delay
        self.exponential_base = exponential_base
        self.exceptions = exceptions
    
    def execute(self, func: Callable, *args, **kwargs) -> Any:
        """执行带重试的函数调用
        
        Args:
            func: 要执行的函数
            *args: 位置参数
            **kwargs: 关键字参数
            
        Returns:
            函数返回值
            
        Raises:
            最后一次重试的异常
        """
        last_exception = None
        
        for attempt in range(self.max_retries + 1):
            try:
                result = func(*args, **kwargs)
                if attempt > 0:
                    logger.info(f"第 {attempt + 1} 次尝试成功")
                return result
            
            except self.exceptions as e:
                last_exception = e
                
                if attempt < self.max_retries:
                    # 计算延迟时间（指数退避）
                    delay = min(
                        self.initial_delay * (self.exponential_base ** attempt),
                        self.max_delay
                    )
                    
                    logger.warning(
                        f"第 {attempt + 1} 次尝试失败: {e}, "
                        f"{delay:.1f} 秒后重试..."
                    )
                    
                    time.sleep(delay)
                else:
                    logger.error(
                        f"已达到最大重试次数 {self.max_retries}, "
                        f"最后一次异常: {e}"
                    )
        
        # 抛出最后一次的异常
        raise last_exception
    
    def execute_with_callback(
        self,
        func: Callable,
        on_success: Callable = None,
        on_failure: Callable = None,
        *args,
        **kwargs
    ) -> bool:
        """执行带回调的重试
        
        Args:
            func: 要执行的函数
            on_success: 成功回调
            on_failure: 失败回调
            *args: 位置参数
            **kwargs: 关键字参数
            
        Returns:
            是否执行成功
        """
        try:
            result = self.execute(func, *args, **kwargs)
            if on_success:
                on_success(result)
            return True
        
        except Exception as e:
            if on_failure:
                on_failure(e)
            return False
