import axios from 'axios';
import basicConfig from '../config';
import localStorage from './localStorage.service';
import Notify from '@qg/cherry-ui/src/notify';

const ERR_MESSAGE_MAP = {
  status: {
    400: '错误请求',
    401: '未授权，请重新登录',
    403: '拒绝访问',
    404: '请求错误,未找到该资源',
    405: '请求方法未允许',
    408: '请求超时',
    500: '服务器端出错',
    501: '网络未实现',
    502: '网络错误',
    503: '服务不可用',
    504: '网络超时',
    505: 'http版本不支持该请求'
  }
};

const CancelToken = axios.CancelToken;
const pending = {};
let reqNum = 0;
axios.defaults.baseURL = basicConfig.apiHost;
axios.defaults.timeout = 30000;
// axios.defaults.xsrfHeaderName = 'x-csrf-token';
// axios.defaults.xsrfCookieName = 'csrfToken';

const wait = async seconds => new Promise(resolve => setTimeout(resolve, seconds));

// 体验优化暂时下掉loading
function beforeRequest() {
  reqNum++;
  // store.dispatch("setIsLoading", true);
}

function afterRequest() {
  clearRequest();
  // setTimeout(clearRequest, 300);
}

function clearRequest() {
  reqNum--;
  if (reqNum <= 0) {
    // store.dispatch("setIsLoading", false);
  }
}

let isRefreshing = true;
let subscriber: Array<() => void> = [];
const addSubscriber = callback => subscriber.push(callback);
const onAccessTokenFetched = () => {
  subscriber.forEach(callback => callback());
  subscriber = [];
};

const refreshtoken = async () => {
  return instance.get(`${basicConfig.opapiHost}/backStms/oauth/refreshtoken?refreshtoken=${localStorage.get('refreshToken')}`);
};

/*
 * 刷新token逻辑
 */
const refreshRequest = async options => {
  const promise = new Promise(resolve => addSubscriber(() => resolve(instance.request(options))));
  if (isRefreshing) {
    isRefreshing = false;
    await wait(500);
    const data = await refreshtoken();
    localStorage.set('token', data.accessToken);
    localStorage.set('refreshToken', data.refreshToken);
    onAccessTokenFetched();
    isRefreshing = true;
  }
  return promise;
};

const instance = axios.create();

// 请求拦截器
instance.interceptors.request.use(
  config => {
    // op-api识别API使用
    config.headers['X-Requested-With'] = 'XMLHttpRequest';
    // beforeRequest();
    // 发起请求时，取消掉当前正在进行的相同请求
    if (pending[config.url as string]) {
      pending[config.url as string]('取消重复请求');
    }
    config.cancelToken = new CancelToken(c => (pending[(config.url + JSON.stringify(config.data)) as string] = c));
    // 添加token
    const token = localStorage.get('token');
    if (token) {
      config.headers['X-Auth-Token'] = token;
      if (config.accessToken) { config.headers['Access-Token'] = token; }
    }
    const tenantId = localStorage.get('tenantId') || basicConfig.yxmTenantId || '';
    config.headers['qg-tenant-id'] = tenantId;
    return config;
  },
  error => {
    return Promise.reject(error);
  }
);

// 响应拦截器即异常处理
instance.interceptors.response.use(
  response => {
    let notifyType = 'danger';
    // afterRequest();

    delete pending[response.config.url as string];
    const codeArr = ['0000', 2000];
    if (codeArr.includes(response.data.code)) { return response.data.data; }

    if (response.data.code === '0001' && response.config.url.includes('oauth/refreshtoken')) {
      window.location.href = `${window.location.origin}/${window.__POWERED_BY_QIANKUN__ ? 'access' : 'editor'}/login`;
    }

      // 后端返回异常信息时提出警告
    if (response.data.code && response.data.msg) { notifyType = 'warning'; }

    Notify({
      type: notifyType,
      message: response.data.msg || '后端服务异常',
      duration: notifyType === 'warning' ? 6000 : 3000
    });
    if (response.data.code === '40100') {
      localStorage.remove('Token');
    }
    return Promise.reject(response.data);
  },
  async err => {
    // afterRequest();
    // 判断是否取消请求
    if (err?.message === '取消重复请求') {
      const res = {
        status: 409,
        data: {}
      };
      return Promise.resolve(res);
    }

    // 提示网络错误时尝试重试
    if (
      err.message === 'Network Error' &&
      (!err.config?.retryCount || err.config?.retryCount <= 3)
    ) {
      if (!err.config?.retryCount) { err.config.retryCount = 1; }
      err.config.retryCount++;
      await wait(3000);
      return axios.request(err.config);
    }

    if (err.response) {
      switch (err.response.status) {
      case 401:
        if (!err.response.config.url.includes('oauth/refreshtoken')) {
          return refreshRequest(err.response.config);
        } else {
          window.location.href = `${window.location.origin}/${window.__POWERED_BY_QIANKUN__ ? 'access' : 'editor'}/login`;
        }
        return;
      }
    }

    // 错误提示
    let message = '';
    if (err.response) {
      message = ERR_MESSAGE_MAP.status[err.response.status] || `连接错误${err.response.status}`;
    } else {
      message = '连接到服务器失败';
    }
    Notify({ type: 'danger', message });
    return Promise.reject(err);
  }
);

export default instance;
