/**
 * API请求合并工具
 * 用于合并相同的请求，减少API调用次数
 */

interface PendingRequest {
  promise: Promise<any>;
  timestamp: number;
}

class ApiDebounce {
  private pendingRequests: Map<string, PendingRequest> = new Map();
  private cache: Map<string, { data: any; timestamp: number }> = new Map();
  private cacheExpiry = 5000; // 缓存过期时间（毫秒）

  /**
   * 生成请求键
   * @param url 请求URL
   * @param params 请求参数
   * @returns 请求键
   */
  private generateKey(url: string, params: any): string {
    return `${url}_${JSON.stringify(params)}`;
  }

  /**
   * 合并请求
   * @param url 请求URL
   * @param requestFn 请求函数
   * @param params 请求参数
   * @param useCache 是否使用缓存
   * @returns 请求结果
   */
  async debounce<T>(
    url: string,
    requestFn: () => Promise<T>,
    params: any = {},
    useCache: boolean = true
  ): Promise<T> {
    const key = this.generateKey(url, params);

    // 检查缓存
    if (useCache) {
      const cached = this.cache.get(key);
      if (cached && Date.now() - cached.timestamp < this.cacheExpiry) {
        return cached.data as T;
      }
    }

    // 检查是否有 pending 请求
    const pending = this.pendingRequests.get(key);
    if (pending) {
      return pending.promise as Promise<T>;
    }

    // 创建新请求
    const promise = requestFn()
      .then((data) => {
        // 缓存结果
        if (useCache) {
          this.cache.set(key, {
            data,
            timestamp: Date.now(),
          });
        }
        return data;
      })
      .finally(() => {
        // 移除 pending 请求
        this.pendingRequests.delete(key);
      });

    this.pendingRequests.set(key, {
      promise,
      timestamp: Date.now(),
    });

    return promise;
  }

  /**
   * 清除缓存
   * @param url 请求URL
   * @param params 请求参数
   */
  clearCache(url: string, params: any = {}): void {
    const key = this.generateKey(url, params);
    this.cache.delete(key);
  }

  /**
   * 清除所有缓存
   */
  clearAllCache(): void {
    this.cache.clear();
  }

  /**
   * 清除所有 pending 请求
   */
  clearAllPending(): void {
    this.pendingRequests.clear();
  }
}

export const apiDebounce = new ApiDebounce();
export default apiDebounce;