import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  Canceler,
  AxiosError
} from 'axios';

type RequestInterceptor = (
  config: AxiosRequestConfig
) => AxiosRequestConfig | Promise<AxiosRequestConfig>;
type ResponseInterceptor = (response: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>;

interface AxiosInterceptorOptions {
  requestInterceptors?: RequestInterceptor[];
  responseInterceptors?: ResponseInterceptor[];
}

class AxiosHttp {
  private axiosInstance: AxiosInstance;
  private cancelMap = new Map<string, Canceler>();

  constructor(config?: AxiosRequestConfig, options?: AxiosInterceptorOptions) {
    this.axiosInstance = axios.create(config);

    // 添加请求拦截器
    options?.requestInterceptors?.forEach((interceptor) => {
      this.axiosInstance.interceptors.request.use(
        async (config: any) => {
          config = await interceptor(config);
          return config;
        },
        (error: AxiosError) => Promise.reject(error)
      );
    });

    // 添加响应拦截器
    options?.responseInterceptors?.forEach((interceptor) => {
      this.axiosInstance.interceptors.response.use(
        async (response: AxiosResponse) => {
          response = await interceptor(response);
          return response;
        },
        (error: AxiosError) => Promise.reject(error)
      );
    });

    // 统一请求拦截 - 生成取消Token
    this.axiosInstance.interceptors.request.use((config) => {
      const requestKey = this.getRequestKey(config);
      if (this.cancelMap.has(requestKey)) {
        // 取消重复请求
        const cancel = this.cancelMap.get(requestKey);
        cancel?.(`取消重复请求: ${requestKey}`);
        this.cancelMap.delete(requestKey);
      }
      config.cancelToken = new axios.CancelToken((cancel: Canceler) => {
        this.cancelMap.set(requestKey, cancel);
      });
      return config;
    });

    // 请求完成后清除取消函数
    this.axiosInstance.interceptors.response.use(
      (response: AxiosResponse) => {
        const requestKey = this.getRequestKey(response.config);
        this.cancelMap.delete(requestKey);
        return response;
      },
      (error: AxiosError) => {
        if (axios.isCancel(error)) {
          console.warn(error.message);
        }
        if (error.config) {
          const requestKey = this.getRequestKey(error.config);
          this.cancelMap.delete(requestKey);
        }
        return Promise.reject(error);
      }
    );
  }

  private getRequestKey(config: AxiosRequestConfig): string {
    const url = config.url || '';
    const method = config.method || 'get';
    const params = config.params ? JSON.stringify(config.params) : '';
    const data = config.data ? JSON.stringify(config.data) : '';
    return [method, url, params, data].join('&');
  }

  request<T = any>(config: AxiosRequestConfig): Promise<T> {
    return this.axiosInstance.request<T>(config).then((res: AxiosResponse) => res.data);
  }

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

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

const api = new AxiosHttp(
  { baseURL: '/', timeout: 5000 },
  {
    requestInterceptors: [
      (config) => {
        config.headers = config.headers || {};
        config.headers.Authorization = 'Bearer token';
        return config;
      }
    ],
    responseInterceptors: [
      (response) => {
        if (response.status !== 200) {
          throw new Error('请求失败');
        }
        return response;
      }
    ]
  }
);

// api
//   .get('/users')
//   .then((data) => console.log(data))
//   .catch((err) => console.error(err.message));

// // 同时重复请求会取消前一个请求
// api.get('/users');
// api.get('/users'); // 这会取消上一个
