import axios, { AxiosRequestConfig } from "axios";
import { loadProgressBar } from "axios-progress-bar";
import { notifyInvalidTokenThrottled } from "./axiosNotice";
import axiosRetry from "axios-retry";
import { store } from "@/store/store";
import moment from "moment";

const config = {
  // baseURL: process.env.baseURL || process.env.apiUrl || ""
  timeout: 1 * 60 * 1000, // Timeout
  withCredentials: true, // Check cross-site Access-Control
};

const _axiosApp = axios.create(config);
// eslint-disable-next-line @typescript-eslint/unbound-method
axiosRetry(_axiosApp, { retries: 0, retryDelay: axiosRetry.exponentialDelay });

_axiosApp.interceptors.request.use(
  function (config) {
    if (config.setGlobalMask) {
      store.increaseGlobalMaskCount("axios");
    }
    const { token, key } = store.user;
    // @ts-ignore
    if (token && config.headers?.common["token"] == null) {
      // @ts-ignore
      config.headers.common["token"] = token;
      // @ts-ignore
      config.headers.common["key"] = key;
    }
    return config;
  },
  function (error) {
    const config: AxiosRequestConfig = error.config;
    if (config.setGlobalMask) {
      store.decreaseGlobalMaskCount("axios");
    }
    $message.error(JSON.stringify(error));
    logger({
      key: "网络请求request error",
      cnl: ["console", "local", "server"],
      pgu: "AUTO",
      aul: config?.url,
    });
    logger({
      key: "网络请求request error",
      cnl: ["console", "local", "server"],
      pgu: "AUTO",
      aul: config?.url,
      lvl: "debug",
      ejn: JSON.stringify(error),
    });
    return Promise.reject(error);
  }
);

// Add a response interceptor
// 这个用途是为了retry网络请求不要疯狂的报错，如果最后没成功，只报第一次的错误
let lastRequestTimeForRetry = 0;
_axiosApp.interceptors.response.use(
  (response) => {
    if (response.config.setGlobalMask) {
      store.decreaseGlobalMaskCount("axios");
    }
    const serverDate = response.headers.date;
    // console.log(response.headers, serverDate);
    store.updateTimeDifference(moment(serverDate).diff(moment()));
    return response;
  },
  (error) => {
    const config: AxiosRequestConfig = error.config;
    logger({
      key: "网络请求response error",
      cnl: ["console", "local", "server"],
      pgu: "AUTO",
      aul: config?.url,
      aus: error.response?.status,
      emsg: error.response?.data?.desc,
    });
    logger({
      key: "网络请求response error",
      cnl: ["console", "local", "server"],
      pgu: "AUTO",
      aul: config?.url,
      aus: error.response?.status,
      lvl: "debug",
      ejn: JSON.stringify(error),
      emsg: error.response?.data?.desc,
      possibleError: error,
    });
    if (config?.setGlobalMask) {
      store.decreaseGlobalMaskCount("axios");
    }
    if (config?.["axios-retry"]) {
      // @ts-expect-error lastRequestTime 并没有声明在它公共的api上
      const thisTime = config["axios-retry"].lastRequestTime;
      if (lastRequestTimeForRetry === thisTime) {
        return Promise.reject(error);
      } else {
        lastRequestTimeForRetry = thisTime;
      }
    }
    const showErrorMessage = !config?.noErrorMessage;
    if (!error.response) {
      if (showErrorMessage) {
        // "Network Error" 网络不通，直接返回
        $message.error("网络连接异常，请检查网络设置。");
      }
      return Promise.reject(error);
    }
    // 这里是返回状态码不为200时候的错误处理
    const status = error.response.status;

    // 登录失效 跳转登录页面
    if (status == 403 || status == 401) {
      notifyInvalidTokenThrottled();
      return Promise.reject(error);
    } else if (status == 405) {
      if (showErrorMessage) {
        $message.error("没有权限！");
      }
      return Promise.reject(error);
    } else if (status == 502) {
      if (showErrorMessage) {
        $message.error("服务器异常(502)！");
      }
      return Promise.reject(error);
    }

    if (status != 200) {
      const showDescOrNot = (descMaybe: { desc: string } | any) => {
        if (descMaybe && descMaybe.desc) {
          if (showErrorMessage) {
            $message.error(descMaybe.desc + "");
          }
        } else {
          if (showErrorMessage) {
            $message.error("未定义异常: " + JSON.stringify(descMaybe, null, 2));
          }
        }
      };
      const data = error.response.data;
      if (data instanceof Blob) {
        const fr = new FileReader();
        fr.addEventListener(
          "load",
          () => {
            let res = fr.result;
            if (typeof res === "string") res = JSON.parse(res);
            showDescOrNot(res);
          },
          false
        );
        fr.readAsText(data);
      } else {
        showDescOrNot(data);
      }

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

// eslint-disable-next-line
loadProgressBar(null, _axiosApp);

export const httpApp = _axiosApp;
