"use strict";

import axios from "axios";
import NProgress from "nprogress";
import { getToken, clearToken } from "@/utils/auth";

const HTTP_MSG = {
  400: "请求错误",
  401: "未授权，请登录",
  403: "没有权限，拒绝访问",
  404: "请求地址出错",
  408: "请求超时",
  500: "服务器内部错误",
  501: "服务未实现",
  502: "网关错误",
  503: "服务不可用",
  504: "网关超时",
  505: "HTTP版本不受支持",
};

const install = (app, { router, opt = "VE_API" }) => {
  const _axios = axios.create({ Global: true });
  let loadingCount = 0;

  _axios.interceptors.request.use(
    (config) => {
      NProgress.done();
      loadingCount++;
      const token = getToken();
      if (token) {
        config.headers.token = token;
      }
      return config;
    },
    (error) => Promise.reject(error)
  );

  _axios.interceptors.response.use(
    (response) => {
      loadingCount--;
      if (loadingCount <= 0) {
        NProgress.done();
      }
      return response.data;
    },
    (error) => {
      loadingCount--;
      if (loadingCount <= 0) {
        NProgress.done();
      }

      if (error?.response) {
        const status = error.response.status;
        const message = HTTP_MSG[status] || "网络异常";
        console.error(`[API] ${status}: ${message}`);

        if (status === 401) {
          clearToken();
          if (router?.hasRoute?.("Home")) {
            router.replace({ name: "Home" });
          }
        }
      }
      return Promise.reject(error);
    }
  );

  const method = {
    post: (url, p, config) => _axios.post(url, p, config),
    get: (url, p, config) => _axios.get(url, Object.assign(config || {}, { params: p })),
    put: (url, p, config) => _axios.put(url, p, config),
    delete: (url, p, config) => _axios.delete(url, config),
  };

  const api = {};
  const files = import.meta.glob("@/api/modules/*.js", { eager: true });
  Object.keys(files).forEach((key) => {
    const fileName = key.replace(/(\.\/|\.js)/g, "").split("/").pop();
    api[fileName] = {};
    const obj = files[key].default || files[key];
    Object.keys(obj).forEach((item) => {
      api[fileName][item] = (p, config = {}) => {
        if (obj[item].mock) {
          return Promise.resolve(obj[item].response(p));
        }
        return method[obj[item].type](pathVariable(obj[item].url, p), p, config);
      };
    });
  });

  window[opt] = api;
  app.config.globalProperties[opt] = api;
};

function pathVariable(url, obj) {
  const prefix = url.indexOf("{");
  if (prefix > -1) {
    const suffix = url.indexOf("}");
    const key = url.substr(prefix + 1, suffix - prefix - 1);
    url = url.replace("{" + key + "}", obj[key]);
    return pathVariable(url, obj);
  }
  return url;
}

export default { install };
