import axios from 'axios';
import '../../utils/index.mjs';
import { ElLoading, ElMessage } from 'element-plus';
import { PUB } from '../../utils/const/index.mjs';
import { Local, Session } from '../../utils/storage/index.mjs';

const abortControllerMap = /* @__PURE__ */ new Map();
const service = axios.create({
  baseURL: window.__env__.VITE_API_URL,
  timeout: 5e4
  // headers: { 'Content-Type': 'application/json' },
});
const accessTokenKey = PUB.accessTokenKey;
const refreshAccessTokenKey = PUB.refreshAccessTokenKey;
const getToken = () => {
  return Local.get(accessTokenKey);
};
const clearTokens = () => {
  Local.remove(accessTokenKey);
  Local.remove(refreshAccessTokenKey);
  Session.clear();
};
const clearAccessTokens = () => {
  clearTokens();
  window.location.reload();
};
const axiosInstance = axios;
let loadingCount = 0;
let loadingInstance = null;
function startLoading() {
  if (loadingCount === 0) {
    loadingInstance = ElLoading.service({
      lock: true,
      text: "\u52A0\u8F7D\u4E2D...",
      background: "rgba(0, 0, 0, 0.7)"
    });
  }
  loadingCount++;
}
function endLoading() {
  if (loadingCount <= 0) return;
  loadingCount--;
  if (loadingCount === 0 && loadingInstance) {
    setTimeout(() => {
      loadingInstance?.close();
      loadingInstance = null;
    }, 200);
  }
}
service.interceptors.request.use(
  (config) => {
    const customConfig = config;
    if (customConfig.loading) {
      startLoading();
    }
    const controller = new AbortController();
    config.signal = controller.signal;
    const url = config.url || "";
    abortControllerMap.set(url, controller);
    const accessToken = Local.get(accessTokenKey);
    if (accessToken) {
      config.headers["Authorization"] = `Bearer ${accessToken}`;
      const jwt = decryptJWT(accessToken);
      const exp = getJWTDate(jwt.exp);
      if (/* @__PURE__ */ new Date() >= exp) {
        const refreshAccessToken = Local.get(refreshAccessTokenKey);
        if (refreshAccessToken) {
          config.headers["X-Authorization"] = `Bearer ${refreshAccessToken}`;
        }
      }
      if (config.method?.toLowerCase() === "get" && config.data) {
        let url2 = config.url + "?" + tansParams(config.data);
        url2 = url2.slice(0, -1);
        config.data = {};
        config.url = url2;
      }
    }
    return config;
  },
  (error) => {
    const customConfig = error.config;
    if (customConfig?.loading === true) {
      endLoading();
    }
    return Promise.reject(error);
  }
);
service.interceptors.response.use(
  (res) => {
    const customConfig = res.config;
    if (customConfig.loading === true) {
      endLoading();
    }
    const url = res.config.url || "";
    abortControllerMap.delete(url);
    var status = res.status;
    var serve = res.data;
    if (status === 401) {
      clearAccessTokens();
    }
    if (status >= 400) {
      throw new Error(res.statusText || "Request Error.");
    }
    if (serve && serve.hasOwnProperty("errors") && serve.errors) {
      throw new Error(JSON.stringify(serve.errors || "Request Error."));
    }
    var accessToken = res.headers[accessTokenKey];
    var refreshAccessToken = res.headers[refreshAccessTokenKey];
    if (accessToken === "invalid_token") {
      clearAccessTokens();
    } else if (refreshAccessToken && accessToken) {
      Local.set(accessTokenKey, accessToken);
      Local.set(refreshAccessTokenKey, refreshAccessToken);
    }
    if (serve.code === 401) {
      clearAccessTokens();
    } else if (serve.code === void 0) {
      return Promise.resolve(res);
    } else if (serve.code !== 200) {
      var message;
      if (serve.message && typeof serve.message == "object") {
        message = JSON.stringify(serve.message);
      } else {
        message = serve.message;
      }
      ElMessage.error(message);
      throw new Error(message);
    }
    return res;
  },
  (error) => {
    const customConfig = error.config;
    if (customConfig?.loading === true) {
      endLoading();
    }
    if (error.response) {
      if (error.response.status === 401) {
        clearAccessTokens();
      } else if (error.response.statusCode === 404) {
        ElMessage.error("\u63A5\u53E3\u5F02\u5E38\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458");
      }
    }
    if (error.message.indexOf("timeout") != -1) {
      ElMessage.error("\u7F51\u7EDC\u8D85\u65F6");
    } else if (error.message == "Network Error") {
      ElMessage.error("\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF");
    } else {
      if (error.response.data) ElMessage.error(error.response.statusText);
      else ElMessage.error("\u63A5\u53E3\u8DEF\u5F84\u627E\u4E0D\u5230");
    }
    return Promise.reject(error);
  }
);
const cancelRequest = (url) => {
  const urlList = Array.isArray(url) ? url : [url];
  for (const _url of urlList) {
    abortControllerMap.get(_url)?.abort();
    abortControllerMap.delete(_url);
  }
};
const cancelAllRequest = () => {
  for (const [_, controller] of abortControllerMap) {
    controller.abort();
  }
  abortControllerMap.clear();
};
function tansParams(params) {
  let result = "";
  for (const propName of Object.keys(params)) {
    const value = params[propName];
    var part = encodeURIComponent(propName) + "=";
    if (value !== null && value !== "" && typeof value !== "undefined") {
      if (typeof value === "object") {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && value[key] !== "" && typeof value[key] !== "undefined") {
            let params2 = propName + "[" + key + "]";
            var subPart = encodeURIComponent(params2) + "=";
            result += subPart + encodeURIComponent(value[key]) + "&";
          }
        }
      } else {
        result += part + encodeURIComponent(value) + "&";
      }
    }
  }
  return result;
}
function decryptJWT(token) {
  token = token.replace(/_/g, "/").replace(/-/g, "+");
  var json = decodeURIComponent(escape(window.atob(token.split(".")[1])));
  return JSON.parse(json);
}
function getJWTDate(timestamp) {
  return new Date(timestamp * 1e3);
}
function request2(config) {
  return new Promise((resolve, reject) => {
    service(config).then((res) => {
      if (res.data.type == "success") {
        resolve(res.data.result);
      } else {
        ElMessage.success(res.data.message);
      }
    }).catch((res) => {
      ElMessage.error(res);
      reject(res);
    });
  });
}

export { accessTokenKey, axiosInstance, cancelAllRequest, cancelRequest, clearAccessTokens, clearTokens, decryptJWT, service as default, getJWTDate, getToken, refreshAccessTokenKey, request2, service, tansParams };
