import axios from 'axios';
import type { AxiosRequestConfig, AxiosInstance, AxiosError } from 'axios';
import { REFRESH_TOKEN_CODE } from '@/config';
import {
  getToken,
  transformRequestData,
  handleAxiosError,
  handleResponseError,
  handleBackendError,
  handleServiceResult
} from '@/utils';
import { clearLocal } from '@/utils/storage/local';

/**
 * 封装axios请求类
 * @author Soybean<honghuangdc@gmail.com>
 */
export default class CustomAxiosInstance {
  instance: AxiosInstance;

  backendConfig: Service.BackendResultConfig;

  /**
   *
   * @param axiosConfig - axios配置
   * @param backendConfig - 后端返回的数据配置
   */
  constructor(
    axiosConfig: AxiosRequestConfig,
    backendConfig: Service.BackendResultConfig = {
      codeKey: 'code',
      dataKey: '',
      msgKey: 'message',
      successCode: '00000000'
    }
  ) {
    this.backendConfig = backendConfig;
    this.instance = axios.create(axiosConfig);
    this.setInterceptor();
  }

  /** 设置请求拦截器 */
  setInterceptor() {
    this.instance.interceptors.request.use(
      async config => {
        const handleConfig = { ...config };
        if (handleConfig.headers) {
          // 数据转换
          const contentType = handleConfig.headers['Content-Type'] as string;
          handleConfig.data = await transformRequestData(handleConfig.data, contentType);
          // 设置token
          handleConfig.headers['X-Token'] = `Bearer ${getToken()}`;
          handleConfig.headers['X-Request-Id'] = new Date().getTime().toString();
        }
        return handleConfig;
      },
      (axiosError: AxiosError) => {
        const error = handleAxiosError(axiosError);
        return handleServiceResult(error, null);
      }
    );
    this.instance.interceptors.response.use(
      async response => {
        const { status } = response;
        if (status === 200 || status < 300 || status === 304) {
          const backend = response.data;
          const { codeKey, dataKey, successCode } = this.backendConfig;
          // 请求成功
          if (backend[codeKey] === successCode) {
            return handleServiceResult(null, dataKey ? backend[dataKey] : backend);
          }
          // 下载文件
          if (response.config.responseType === 'arraybuffer' || response.config.responseType === 'blob') {
            return handleServiceResult(null, backend);
          }
          // token失效, 刷新token
          if (REFRESH_TOKEN_CODE.includes(backend[codeKey])) {
            // window.$message?.error('Token失效，请重新登录');
            clearLocal();
            window.location.reload();
          }

          const error = handleBackendError(backend, this.backendConfig);
          return handleServiceResult(error, null);
        }
        const error = handleResponseError(response);
        return handleServiceResult(error, null);
      },
      (axiosError: AxiosError) => {
        const error = handleAxiosError(axiosError);
        return handleServiceResult(error, null);
      }
    );
  }
}
