/** http请求类 */
import axios, { AxiosInstance, AxiosRequestConfig, Method, AxiosPromise } from "axios"
import Nprogress from "@/plugin/nprogress"
import { ElMessage } from "element-plus"
import { TokenInvalidFlag, CODE401, CODE_ERR_CANCELED } from "@/libs/auth"
import userStore from "@/store/modules/user"
import useSecureAnth from "@/hooks/useSecureAnth"

//重写 axios 传参
interface AxiosConfigType extends AxiosRequestConfig {
   method: Method //method 必须为Method 格式
}

// axiosObj 传值
type axiosObjType = {
   getTokenFun?: () => string | undefined // 获取token的函数
   tokenName?: string // headers token的名字
   nprogress?: boolean // 是否显示滚动条
}

/** api接口 */
export interface axiosApiType {
   (...param: any[]): AxiosPromise<any>
}

class HttpAsynAxios {
   constructor(url: string, axiosObj?: axiosObjType) {
      this.URL = url
      this.axiosObj = axiosObj
   }
   private URL = ""
   private axiosObj: axiosObjType | undefined = undefined
   private httpInterceptor(instance: AxiosInstance) {
      ;(this.axiosObj ? !(this.axiosObj.nprogress === false) : true) && Nprogress.start() //开启
      //http request 请求拦截器
      instance.interceptors.request.use(
         config => {
            return config
         },
         error => {
            console.log(error)
            Nprogress.done()
            const rejectData: apiResDataType = {
               code: 500,
               message: "系统运行异常，请刷新页面",
               data: null
            }
            return Promise.reject(rejectData)
         }
      )
      // http response 结果拦截器
      instance.interceptors.response.use(
         response => {
            Nprogress.done()
            // *** 转换msg为message  正常是没有的 这里2个系统所以合并一下
            response.data.msg && (response.data.message = response.data.msg)
            //如果返回401则跳转到登录页
            if (response.data.code === CODE401) {
               response.data.message = "登录过期，请重新登录" // 自定义接口返回错误
               //如果token登录状态 才提示和退出
               if (TokenInvalidFlag) {
                  const responseData: apiResDataType = response.data
                  ElMessage.error(responseData.message)
                  //登出
                  userStore().resetUser()
               }
            }
            return response
         },
         error => {
            console.log(error)
            Nprogress.done()
            // if (error.response) {
            //     // 响应错误之后的操作
            //     switch (error.response.status) {
            //         case 401:
            //     }
            // }
            if (error.response?.status === 511) {
               // isLogin=true 带有这个是登录时候的判断弹窗验证证书  其他的走正常弹窗
               if (!/isLogin=true/.test(error.config?.url)) {
                  useSecureAnth()
               }
               return Promise.reject({
                  code: 511,
                  message: "请下载安装安全数据证书",
                  data: null
               })
            }
            const rejectData: apiResDataType =
               //取消接口返回自己的 CODE_ERR_CANCELED
               error.code === CODE_ERR_CANCELED
                  ? {
                       code: error.code,
                       message: "系统取消接口",
                       data: null
                    }
                  : {
                       code: 500,
                       message: "系统运行异常，请刷新页面",
                       data: null
                    }
            return Promise.reject(rejectData) // 返回接口返回的错误信息
         }
      )
   }
   //创建实例
   private createInstance() {
      const axiosObj = this.axiosObj
      return axios.create(
         axiosObj?.tokenName
            ? {
                 baseURL: this.URL,
                 headers: {
                    [axiosObj.tokenName]: axiosObj.getTokenFun && axiosObj.getTokenFun()
                 }
              }
            : {
                 baseURL: this.URL
              }
      )
   }
   /**
      axios请求方法
      ```
      {
         data: data,     //get方法的时候为params：data
         method: "post",
         url: '/auth/loginIn'，
         headers:{
                  'Content-Type':'application/json',
         },
         responseType: 'blob',
      }
      ```
   */
   axioseRquest(opt: AxiosConfigType) {
      const instance = this.createInstance()
      this.httpInterceptor(instance)
      return instance(opt)
   }
}

export default HttpAsynAxios
