/**
 * API 错误处理包装器
 * 提供统一的错误处理逻辑，减少重复代码
 */

import { ErrorHandler, AppError } from './errorHandler';
import type { ToastInterface } from '../types/toast';

/**
 * API 操作配置
 */
interface ApiOperationConfig {
  /** 操作成功时的消息 */
  successMessage?: string;
  /** 操作失败时的默认消息 */
  errorMessage?: string;
  /** 是否在成功时显示通知 */
  showSuccessToast?: boolean;
  /** 是否在失败时显示通知 */
  showErrorToast?: boolean;
  /** 是否在失败时抛出错误 */
  throwOnError?: boolean;
}

/**
 * 包装 API 调用，提供统一的错误处理
 *
 * @param operation - 要执行的异步操作
 * @param toast - Toast 通知接口
 * @param config - 操作配置
 * @returns 操作结果，失败时返回 null
 *
 * @example
 * ```typescript
 * const result = await handleApiOperation(
 *   () => request.delete(`/api/v1/documents/${id}`),
 *   toast,
 *   {
 *     successMessage: '删除成功',
 *     errorMessage: '删除失败'
 *   }
 * )
 * ```
 */
export async function handleApiOperation<T>(
  operation: () => Promise<T>,
  toast: ToastInterface,
  config: ApiOperationConfig = {}
): Promise<T | null> {
  const {
    successMessage,
    errorMessage = '操作失败',
    showSuccessToast = true,
    showErrorToast = true,
    throwOnError = false,
  } = config;

  try {
    const result = await operation();

    if (successMessage && showSuccessToast) {
      toast.success(successMessage);
    }

    return result;
  } catch (error: any) {
    const appError = ErrorHandler.parseError(error);

    if (showErrorToast) {
      const message = appError.message || errorMessage;
      toast.error(message);
    }

    if (throwOnError) {
      throw appError;
    }

    return null;
  }
}

/**
 * 批量操作错误处理
 *
 * @param operations - 操作数组
 * @param toast - Toast 通知接口
 * @param config - 操作配置
 * @returns 成功和失败的结果
 *
 * @example
 * ```typescript
 * const { succeeded, failed } = await handleBatchOperation(
 *   items.map(item => () => deleteItem(item.id)),
 *   toast,
 *   { errorMessage: '删除失败' }
 * )
 * ```
 */
export async function handleBatchOperation<T>(
  operations: Array<() => Promise<T>>,
  toast: ToastInterface,
  config: ApiOperationConfig = {}
): Promise<{ succeeded: T[]; failed: AppError[] }> {
  const succeeded: T[] = [];
  const failed: AppError[] = [];

  for (const operation of operations) {
    try {
      const result = await operation();
      succeeded.push(result);
    } catch (error: any) {
      const appError = ErrorHandler.parseError(error);
      failed.push(appError);
    }
  }

  // 显示批量操作结果
  if (succeeded.length > 0 && config.successMessage) {
    toast.success(`${config.successMessage}: ${succeeded.length} 项`);
  }

  if (failed.length > 0) {
    const errorMessage = config.errorMessage || '部分操作失败';
    toast.error(`${errorMessage}: ${failed.length} 项`);
  }

  return { succeeded, failed };
}

/**
 * 带重试的 API 操作
 *
 * @param operation - 要执行的异步操作
 * @param toast - Toast 通知接口
 * @param config - 操作配置
 * @param maxRetries - 最大重试次数
 * @param retryDelay - 重试延迟（毫秒）
 * @returns 操作结果
 *
 * @example
 * ```typescript
 * const result = await handleApiOperationWithRetry(
 *   () => request.get('/api/v1/data'),
 *   toast,
 *   { errorMessage: '加载失败' },
 *   3,
 *   1000
 * )
 * ```
 */
export async function handleApiOperationWithRetry<T>(
  operation: () => Promise<T>,
  toast: ToastInterface,
  config: ApiOperationConfig = {},
  maxRetries: number = 3,
  retryDelay: number = 1000
): Promise<T | null> {
  let lastError: AppError | null = null;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const result = await operation();

      if (config.successMessage && config.showSuccessToast !== false) {
        toast.success(config.successMessage);
      }

      return result;
    } catch (error: any) {
      lastError = ErrorHandler.parseError(error);

      // 如果不是网络错误或已达到最大重试次数，直接失败
      if (lastError.code !== 'NETWORK_ERROR' || attempt === maxRetries) {
        break;
      }

      // 等待后重试
      await new Promise((resolve) => setTimeout(resolve, retryDelay * (attempt + 1)));
    }
  }

  // 所有重试都失败
  if (config.showErrorToast !== false && lastError) {
    const message = lastError.message || config.errorMessage || '操作失败';
    toast.error(message);
  }

  if (config.throwOnError && lastError) {
    throw lastError;
  }

  return null;
}

/**
 * 提取错误消息
 *
 * @param error - 错误对象
 * @param fallbackMessage - 默认消息
 * @returns 错误消息
 */
export function extractErrorMessage(error: any, fallbackMessage: string = '操作失败'): string {
  const appError = ErrorHandler.parseError(error);
  return appError.message || fallbackMessage;
}
