type ProtectOptions = {
  maxRetries?: number;
  delay?: number;
  onRetry?: (error: any, attempt: number) => void;
};

/**
 * 保护函数，用于包裹异步请求并在失败时自动重试
 * @param fn 需要执行的异步函数
 * @param options 配置项
 * @param options.maxRetries 最大重试次数，默认为 3
 * @param options.delay 重试间隔时间（毫秒），默认为 1000
 * @param options.onRetry 重试时的回调函数
 * @returns 返回函数执行结果
 */
export async function protect<T>(fn: () => Promise<T>, options: ProtectOptions = {}): Promise<T> {
  const { maxRetries = 3, delay = 1000, onRetry } = options;

  let lastError: any;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error;

      // 如果已经是最后一次尝试，直接抛出错误
      if (attempt === maxRetries) {
        console.error(`请求失败，已重试 ${maxRetries} 次:`, error);
        throw error;
      }

      // 执行重试回调
      if (onRetry) {
        onRetry(error, attempt);
      } else {
        console.warn(`请求失败，第 ${attempt} 次重试中...`, error);
      }

      // 等待一段时间后重试
      await new Promise((resolve) => setTimeout(resolve, delay * attempt));
    }
  }

  throw lastError;
}

/**
 * 创建一个带保护的函数包装器
 * @param fn 需要包装的异步函数
 * @param options 配置项
 * @returns 返回包装后的函数
 */
export function createProtected<T extends (...args: any[]) => Promise<any>>(
  fn: T,
  options: ProtectOptions = {}
): T {
  return (async (...args: any[]) => {
    return protect(() => fn(...args), options);
  }) as T;
}
