/**
 * 增强的 API 请求工具
 */
import axios, { AxiosRequestConfig, AxiosError } from 'axios';
import { apiPerformanceMonitor } from './performance';
import { memoryCache } from './cache-manager';
import { getToken } from './token-util';
import { API_BASE_URL, TOKEN_HEADER_NAME } from '@/config/setting';

// 请求配置接口
interface EnhancedRequestConfig extends AxiosRequestConfig {
  // 缓存配置
  cache?: {
    enabled: boolean;
    expiry?: number;
    key?: string;
    tags?: string[];
  };
  // 重试配置
  retry?: {
    times: number;
    delay: number;
    condition?: (error: AxiosError) => boolean;
  };
  // 性能监控
  performance?: boolean;
  // 请求去重
  dedupe?: boolean;
  // 超时重试
  timeoutRetry?: boolean;
}

// 请求队列管理
class RequestQueue {
  private pendingRequests = new Map<string, Promise<any>>();

  // 生成请求键
  private generateKey(config: AxiosRequestConfig): string {
    const { method, url, params, data } = config;
    return `${method}_${url}_${JSON.stringify(params)}_${JSON.stringify(data)}`;
  }

  // 添加请求到队列
  add<T>(config: AxiosRequestConfig, executor: () => Promise<T>): Promise<T> {
    const key = this.generateKey(config);

    if (this.pendingRequests.has(key)) {
      return this.pendingRequests.get(key);
    }

    const promise = executor().finally(() => {
      this.pendingRequests.delete(key);
    });

    this.pendingRequests.set(key, promise);
    return promise;
  }

  // 清除队列
  clear(): void {
    this.pendingRequests.clear();
  }
}

// 重试机制
class RetryManager {
  static async retry<T>(
    fn: () => Promise<T>,
    config: { times: number; delay: number; condition?: (error: any) => boolean }
  ): Promise<T> {
    let lastError: any;

    for (let i = 0; i <= config.times; i++) {
      try {
        return await fn();
      } catch (error) {
        lastError = error;

        // 检查是否应该重试
        if (i < config.times && (!config.condition || config.condition(error as AxiosError))) {
          await this.delay(config.delay * Math.pow(2, i)); // 指数退避
          console.warn(`请求重试 ${i + 1}/${config.times}:`, error);
        } else {
          break;
        }
      }
    }

    throw lastError;
  }

  private static delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// 增强的请求类
export class EnhancedRequest {
  private instance = axios.create({
    baseURL: API_BASE_URL,
    timeout: 30000
  });

  private requestQueue = new RequestQueue();

  constructor() {
    this.setupInterceptors();
  }

  private setupInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
        // 添加认证头
        const token = getToken();
        if (token && config.headers) {
          config.headers[TOKEN_HEADER_NAME] = token;
        }

        // 添加请求时间戳
        (config as any).startTime = Date.now();

        return config;
      },
      (error) => {
        return Promise.reject(error);
      }
    );

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response) => {
        // 记录性能数据
        const config = response.config as any;
        if (config.startTime) {
          const duration = Date.now() - config.startTime;
          apiPerformanceMonitor.recordApiCall(config.url, duration);
        }

        return response;
      },
      (error) => {
        // 记录错误的性能数据
        const config = error.config as any;
        if (config && config.startTime) {
          const duration = Date.now() - config.startTime;
          apiPerformanceMonitor.recordApiCall(config.url, duration);
        }

        return Promise.reject(error);
      }
    );
  }

  // 通用请求方法
  async request<T = any>(config: EnhancedRequestConfig): Promise<T> {
    const {
      cache,
      retry,
      performance = true,
      dedupe = true,
      timeoutRetry = true,
      ...axiosConfig
    } = config;

    // 生成缓存键
    const cacheKey = cache?.key || this.generateCacheKey(axiosConfig);

    // 尝试从缓存获取
    if (cache?.enabled) {
      const cachedData = memoryCache.get<T>(cacheKey);
      if (cachedData !== null) {
        return cachedData;
      }
    }

    // 请求执行器
    const executor = async (): Promise<T> => {
      const response = await this.instance.request<T>(axiosConfig);

      // 缓存响应数据
      if (cache?.enabled && response.data) {
        memoryCache.set(
          cacheKey,
          response.data,
          cache.expiry,
          cache.tags
        );
      }

      return response.data;
    };

    // 请求去重
    if (dedupe) {
      return this.requestQueue.add(axiosConfig, async () => {
        // 重试机制
        if (retry) {
          return RetryManager.retry(executor, {
            ...retry,
            condition: retry.condition || this.shouldRetry
          });
        }

        return executor();
      });
    }

    // 重试机制
    if (retry) {
      return RetryManager.retry(executor, {
        ...retry,
        condition: retry.condition || this.shouldRetry
      });
    }

    return executor();
  }

  // GET 请求
  get<T = any>(url: string, config?: EnhancedRequestConfig): Promise<T> {
    return this.request<T>({
      ...config,
      method: 'GET',
      url
    });
  }

  // POST 请求
  post<T = any>(url: string, data?: any, config?: EnhancedRequestConfig): Promise<T> {
    return this.request<T>({
      ...config,
      method: 'POST',
      url,
      data
    });
  }

  // PUT 请求
  put<T = any>(url: string, data?: any, config?: EnhancedRequestConfig): Promise<T> {
    return this.request<T>({
      ...config,
      method: 'PUT',
      url,
      data
    });
  }

  // DELETE 请求
  delete<T = any>(url: string, config?: EnhancedRequestConfig): Promise<T> {
    return this.request<T>({
      ...config,
      method: 'DELETE',
      url
    });
  }

  // 批量请求
  async batch<T = any>(requests: EnhancedRequestConfig[]): Promise<T[]> {
    const promises = requests.map(config => this.request<T>(config));
    return Promise.all(promises);
  }

  // 并发控制请求
  async concurrent<T = any>(
    requests: EnhancedRequestConfig[],
    limit: number = 5
  ): Promise<T[]> {
    const results: T[] = [];

    for (let i = 0; i < requests.length; i += limit) {
      const batch = requests.slice(i, i + limit);
      const batchResults = await this.batch<T>(batch);
      results.push(...batchResults);
    }

    return results;
  }

  // 生成缓存键
  private generateCacheKey(config: AxiosRequestConfig): string {
    const { method, url, params, data } = config;
    return `api_${method}_${url}_${JSON.stringify(params)}_${JSON.stringify(data)}`;
  }

  // 判断是否应该重试
  private shouldRetry(error: AxiosError): boolean {
    // 网络错误或超时错误重试
    if (!error.response) {
      return true;
    }

    // 5xx 服务器错误重试
    const status = error.response.status;
    return status >= 500 && status < 600;
  }

  // 清除缓存
  clearCache(tags?: string[]): void {
    if (tags) {
      memoryCache.clearByTags(tags);
    } else {
      memoryCache.clear();
    }
  }

  // 取消所有请求
  cancelAll(): void {
    this.requestQueue.clear();
  }
}

// 全局实例
export const enhancedRequest = new EnhancedRequest();

// 便捷方法
export const { get, post, put, delete: del, batch, concurrent } = enhancedRequest;

// 带缓存的 GET 请求
export function cachedGet<T = any>(
  url: string,
  config?: Omit<EnhancedRequestConfig, 'cache'> & {
    expiry?: number;
    tags?: string[];
  }
): Promise<T> {
  const { expiry = 5 * 60 * 1000, tags, ...restConfig } = config || {};

  return enhancedRequest.get<T>(url, {
    ...restConfig,
    cache: {
      enabled: true,
      expiry,
      tags
    }
  });
}

// 带重试的请求
export function retryRequest<T = any>(
  config: EnhancedRequestConfig,
  retryTimes: number = 3,
  retryDelay: number = 1000
): Promise<T> {
  return enhancedRequest.request<T>({
    ...config,
    retry: {
      times: retryTimes,
      delay: retryDelay
    }
  });
}
