import axios, { type AxiosInstance, type AxiosRequestConfig, type AxiosResponse } from 'axios'
import router from '@/router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useUserStore } from '@/stores/modules/user'
// import {
//   showFullScreenLoading,
//   tryHideFullScreenLoading
// } from '@monorepo/shared/utils/serviceLoading'

interface codeMessage {
  [key: number]: string
}

const CODE_MESSAGE: codeMessage = {
  200: '服务器成功返回请求的数据。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  456: 'refreshToken过期',
  457: 'accessToken过期',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。'
}

class HttpAxios {
  instance: AxiosInstance
  timeout = 30000
  cancelTokenArr: Array<any> = []

  constructor(config: AxiosRequestConfig) {
    this.instance = axios.create(config)

    // 设置请求拦截
    this.instance.interceptors.request.use(this._requestInterceptors, (error: any) => {
      return Promise.reject(error)
    })

    this.instance.interceptors.response.use(this._responseInterceptors, this._checkResponseError)
  }

  _requestInterceptors = (config: AxiosRequestConfig) => {
    // const _config = { timeout: this.timeout }
    // return { ...config, ..._config }
    return config
  }
  /**
   * 返回拦截
   * @param response
   * @returns
   */
  _responseInterceptors = (response: AxiosResponse) => {
    if (response.status === 200) {
      if (response.data.code === 401 || response.data.code === 403) {
        sessionStorage.clear()
        router.push('/login')
        const userStore = useUserStore()
        userStore.logout(false)
        ElMessage.warning({
          message: 'Please log in to use this feature.',
          grouping: true
        })
      } else if (response.data.code !== 200 && response.data.code !== 400) {
        ElMessageBox.alert(
          response.data?.data?.msg || 'The request failed. Please try again later',
          'Prompt',
          { confirmButtonText: 'OK', confirmButtonClass: 'el-button--dark' }
        )
      }
      return response.data
    }
    return Promise.reject(response)
  }

  _checkResponseError = (error: any) => {
    if (error.code === 'ECONNABORTED') {
      ElMessage.error({
        message: 'Request timed out, please try again later!!',
        grouping: true
      })
      return Promise.reject(error)
    }

    const status = error.response?.status
    const statusText = error.response?.statusText
    const message = error.message
    ElMessage.error({
      message: CODE_MESSAGE[status] || statusText || message,
      grouping: true
    })
    return Promise.reject(error)
  }

  sendRequest = (url: string, params: any, method = 'post', config?: AxiosRequestConfig) => {
    if (!this.instance) return

    // TODO show loading if needed
    // showFullScreenLoading()

    const _method = method.toLowerCase()
    if (_method === 'get') {
      return this.instance.get(url, { params, ...config })
    }

    if (_method === 'post') {
      return this.instance.post(url, params, {
        headers: { 'Content-Type': 'multipart/form-data' },
        ...config
      })
    }

    if (_method === 'put') {
      return this.instance.put(url, params, config)
    }

    if (_method === 'delete') {
      return this.instance.delete(url, { data: params, ...config })
    }

    return this.instance.post(url, params, config)
  }

  get(url: string, params?: object, config?: AxiosRequestConfig) {
    return this.sendRequest(url, params, 'get', config)
  }

  post(url: string, params?: object, config?: AxiosRequestConfig) {
    return this.sendRequest(url, params, 'post', config)
  }

  formdata(url: string, params?: object, config?: AxiosRequestConfig) {
    return this.sendRequest(url, params, 'formdata', config)
  }

  put(url: string, params?: object, config?: AxiosRequestConfig) {
    return this.sendRequest(url, params, 'put', config)
  }

  delete(url: string, params?: any, config?: AxiosRequestConfig) {
    return this.sendRequest(url, params, 'delete', config)
  }

  async clearRequests() {
    if (this.cancelTokenArr.length === 0) return

    this.cancelTokenArr.forEach((token) => {
      token.cancel()
    })
    this.cancelTokenArr = []
  }
}

export default new HttpAxios({})

// export default new HttpAxios({})
