import axios, {
  AxiosError,
  type AxiosInstance,
  type AxiosRequestConfig,
  type AxiosResponse,
} from "axios";
import router from "@/router";
import Loading from "@/shared/classes/Loading";
import { message } from "@/utils";
import { CLIENT_TYPE, LOGIN_ROUTER } from "@/config/constant";
import { useUserStore } from "@/stores/user";
const axiosConfig: AxiosRequestConfig = {
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout:
    import.meta.env.VITE_APP_ENV === "production" ? 10 * 1000 : 60 * 1000,
  timeoutErrorMessage: "请求超时......",
};

class RequestHttp {
  service: AxiosInstance;

  public constructor(config: AxiosRequestConfig) {
    this.service = axios.create(config);
    //1.添加请求拦截
    this.service.interceptors.request.use(
      (config) => {
        const userStore = useUserStore();
        //请求必须带上当前客户端类型
        config.headers.set("Client-Type", CLIENT_TYPE);
        config.headers.set(
          userStore.tokenInfo?.tokenName,
          userStore.tokenInfo?.tokenValue
        );
        if (config.loading) {
          Loading.show(config.loadingMessage);
        }
        //todo 默认带上用户token
        return config;
      },
      async (error: AxiosError): Promise<string> => {
        Loading.close();
        message.error(error.message);
        return Promise.reject(error);
      }
    );
    //2.添加响应拦截
    this.service.interceptors.response.use(
      async (response: AxiosResponse): Promise<any> => {
        Loading.close();
        const jsonResult: JsonResult<unknown> = response.data;
        if (jsonResult && jsonResult.code !== 200) {
          //todo 一些特定的错误需要重新登录
          if ([-1].includes(jsonResult.code)) {
            //清除登录信息
            useUserStore().resetUserInfo();
            //跳转登录页
            await router.push({
              path: LOGIN_ROUTER.path,
            });
          }
          message.error(jsonResult.message);
          return Promise.reject(jsonResult);
        }
        return Promise.resolve(jsonResult);
      },
      async (error: AxiosError): Promise<string> => {
        Loading.close();
        message.error(error.message);
        return Promise.reject(error);
      }
    );
  }

  /**
   *  常用请求方法封装
   */
  get<T>(
    url: string,
    params?: object,
    _object: AxiosRequestConfig = {}
  ): Promise<JsonResult<T>> {
    return this.service.get(url, { params, ..._object });
  }

  post<T>(
    url: string,
    params?: object | object[],
    _object: AxiosRequestConfig = {}
  ): Promise<JsonResult<T>> {
    return this.service.post(url, params, _object);
  }

  put<T>(
    url: string,
    params?: object | object[],
    _object: AxiosRequestConfig = {}
  ): Promise<JsonResult<T>> {
    return this.service.put(url, params, _object);
  }

  delete<T>(
    url: string,
    params?: object,
    _object: AxiosRequestConfig = {}
  ): Promise<JsonResult<T>> {
    return this.service.delete(url, { params, ..._object });
  }

  download(
    url: string,
    params?: object,
    _object: AxiosRequestConfig = {}
  ): Promise<BlobPart> {
    return this.service.post(url, params, { ..._object, responseType: "blob" });
  }
}

const api = new RequestHttp(axiosConfig);
export default api;
