import axios, { AxiosError } from 'axios'
import { ElMessage } from 'element-plus'
import { setupAuthSign, transformRequestData, transformGetParams, appendExamId } from '@/plugins/request/plugin'
import { filterEmpty, downloadBlob, extractFileName } from '@/utils/common'
import { logout } from '@/utils/shared'
import useMainStore from '@/store/main'

const toastError = (message?: string) => {
  message && ElMessage({ message, type: 'error', grouping: true })
}

const request = axios.create({
  baseURL: import.meta.env.VITE_APP_API_HOST || '/',
  withCredentials: true,
  timeout: 20000,
  method: 'post',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
})

request.interceptors.request.use(
  (config) => {
    if (!config.url) {
      throw new AxiosError('request must should a url parameter', 'REQUEST_PARAMETER_ERROR', config)
    }

    appendExamId(config)

    config.data = filterEmpty(config.data)
    config.params = filterEmpty(config.params)

    transformGetParams(config)

    setupAuthSign(config)
    transformRequestData(config)

    if (config.download) {
      config.responseType ??= 'blob'
    }
    return config
  },
  (error: AxiosError) => {
    if (!error.config.noToast) {
      toastError(error.message || error.name || error.code)
    }
    return Promise.reject(error)
  }
)

request.interceptors.response.use(
  (response) => {
    useMainStore().serverTime = new Date(response.headers?.['date']).getTime()
    useMainStore().diffTime = useMainStore().serverTime - Date.now()
    if (response.data.hasError) {
      const errMsg = response.data?.failRecords.map((v: any) => [v.msg, v.lineNum].join('--'))?.join('\n')
      toastError(errMsg)
      return Promise.reject(response.data)
    }
    if (response.config.download && response.config.responseType === 'blob') {
      downloadBlob(response.data, extractFileName(response.headers?.['content-disposition'] as string))
    }
    return response.data
  },
  async (error: AxiosError<any>) => {
    if (!error.config?.noToast && error?.code !== 'ERR_CANCELED') {
      if (error.isAxiosError) {
        if (
          error.response &&
          ([401, 403].includes(error.response.status) || error.response.data?.code?.toString()?.startsWith('401'))
        ) {
          logout(false)
          toastError('登录状态已过期')
          return Promise.reject(error)
        }
        let msg = ''
        if (error.config?.responseType === 'blob') {
          try {
            const e = JSON.parse(await error?.response?.data?.text())
            msg = e.message || e.error || e
          } catch (error) {
            console.error(error)
          }
        }
        if (!msg) {
          msg = error?.response?.data?.message || error.message || error.code || error.name
        }
        toastError(msg)
      } else {
        toastError(error.message)
      }
    }
    // if (error.response?.data) {
    //   return Promise.reject(error.response.data)
    // }
    return Promise.reject(error)
  }
)

export default request
