//引入axios
import store from "@/store";
import router from "@/router";
import axios from "axios";
import cherry from "@qg/cherry-ui";
import config from "../config";
import localStorage from "./localStorage";

const ERR_MESSAGE_MAP = {
  status: {
    400: "错误请求",
    401: "未授权，请重新登录",
    403: "拒绝访问",
    404: "请求错误,未找到该资源",
    405: "请求方法未允许",
    408: "请求超时",
    500: "服务器端出错",
    501: "网络未实现",
    502: "网络错误",
    503: "服务不可用",
    504: "网络超时",
    505: "http版本不支持该请求"
  }
};
const { Notify } = cherry;
const CancelToken = axios.CancelToken;
let pending = {};
let reqNum = 0;
axios.defaults.baseURL = config.basicHost;
axios.defaults.timeout = 30000;

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);
  }
}

// 请求拦截器
axios.interceptors.request.use(
  config => {
    beforeRequest();

    // 发起请求时，取消掉当前正在进行的相同请求
    if (pending[config.url]) {
      pending[config.url]("取消重复请求");
    }
    config.cancelToken = new CancelToken(c => (pending[config.url] = c));
    // 添加token
    const token = localStorage.get("mongoToken");
    if (token) {
      config.headers["x-auth-token"] = token;
    }

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

// 响应拦截器即异常处理
axios.interceptors.response.use(
  response => {
    let notifyType = "danger";

    afterRequest();

    delete pending[response.config.url];
    if (response.data.code === "0") return response.data.data;

    // 特殊处理，下单已存在时，跳转到保单列表
    if (response.config.url === "policy_order" && response.data.code === "40601") {
      setTimeout(() => {
        router.push("/policy");
      }, 1000);
    }

    // 后端返回异常信息时提出警告
    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("mongoToken");
    }
    return Promise.reject(response.data);
  },
  async err => {
    console.dir(err.response);
    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) {
      err.message = ERR_MESSAGE_MAP.status[err.response.status] || `连接错误${err.response.status}`;
    } else {
      err.message = "连接到服务器失败";
    }
    Notify({ type: "danger", message: err.message });
    return Promise.reject(err.response);
  }
);

export default axios;
