import {
  DEFAULT_REQUEST_ERROR_CODE,
  DEFAULT_REQUEST_ERROR_MSG,
  ERROR_STATUS,
  NETWORK_ERROR_CODE,
  NETWORK_ERROR_MSG,
  REQUEST_TIMEOUT_CODE,
  REQUEST_TIMEOUT_MSG,
} from './service'
import type { BackendServiceResult, RequestServiceError } from './types'
import { showErrorMsg } from '@/utils/toast'
import type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import type { MessageHandler } from 'element-plus'
import service from './index'
import { useUserStore } from '@/stores/user'

/**
 * 后端逻辑code报错处理
 * @param backendServiceResult 后端传来错误信息
 */
export function handleBackendError<T>(backendServiceResult: BackendServiceResult<T>) {
  const error: RequestServiceError = {
    type: 'backend',
    code: backendServiceResult.code || DEFAULT_REQUEST_ERROR_CODE,
    msg: backendServiceResult.message,
  }
  showErrorMsg(error)
  return Promise.reject(backendServiceResult)
}

/**
 * 处理请求成功后错误
 */
export function handleResponseError(response: AxiosResponse) {
  const error: RequestServiceError = {
    type: 'axios',
    code: DEFAULT_REQUEST_ERROR_CODE,
    msg: DEFAULT_REQUEST_ERROR_MSG,
  }

  if (!window.navigator.onLine) {
    // 网路错误
    Object.assign(error, { code: NETWORK_ERROR_CODE, msg: NETWORK_ERROR_MSG })
  } else {
    // 请求成功的状态码非200的错误
    const errorCode: ErrorStatus = response.status as ErrorStatus
    const msg = ERROR_STATUS[errorCode] || DEFAULT_REQUEST_ERROR_MSG
    Object.assign(error, { type: 'backend', code: errorCode, msg })
  }
  showErrorMsg(error)

  return Promise.reject(response)
}

/**
 * 处理请求失败
 */
type ErrorStatus = keyof typeof ERROR_STATUS
export function handleRequestError<T>(axiosError: AxiosError<BackendServiceResult<T>>) {
  const error: RequestServiceError = {
    type: 'axios',
    code: DEFAULT_REQUEST_ERROR_CODE,
    msg: DEFAULT_REQUEST_ERROR_MSG,
  }
  // 网络错误
  if (!window.navigator.onLine || axiosError.message === 'Network Error') {
    Object.assign(error, { code: NETWORK_ERROR_CODE, msg: NETWORK_ERROR_MSG })
  }
  // 请求超时
  else if (axiosError.code === REQUEST_TIMEOUT_CODE && axiosError.message.includes('timeout')) {
    /** 超时错误 */
    Object.assign(error, { code: REQUEST_TIMEOUT_CODE, msg: REQUEST_TIMEOUT_MSG })
  }
  // 请求出错,如404， 403
  else {
    const errorCode: ErrorStatus = axiosError.response?.status as ErrorStatus
    const msg =
      axiosError.response?.data.message || ERROR_STATUS[errorCode] || DEFAULT_REQUEST_ERROR_MSG
    Object.assign(error, { code: errorCode || DEFAULT_REQUEST_ERROR_CODE, msg })
    // 敏感词
    if (axiosError.response?.data.code === 501) {
      const message = axiosError.response?.data.message
      if (message && JSON.parse(message)) {
        ElMessage({
          showClose: true,
          message: `敏感词不可出现：${JSON.parse(message).join(',')}`,
          type: 'error',
          duration: 0,
        })
      }
    }
    if (axiosError.response?.data.code === 502) {
      // 502 企业微信登录错误
      ElMessage({
        showClose: true,
        message: `当前链接有问题，请从同事吧入口进入登录后，再点击该连接，如果有其他问题，请联系 张惠忠 解决`,
        type: 'error',
        duration: 0,
      })
    } else if (error.code === 401) {
      // 处理401的
      console.log(error, '这里是401么', axiosError)
      // 重新发送一遍请求
      // service.request(axiosError.config as AxiosRequestConfig)
      return handleUnAuthorized(axiosError)
    } else {
      console.log(error, axiosError, '这里是其他错误么')
      showErrorMsg(error)
    }
    // 鉴权错误
    if (axiosError.response?.status === 403) {
      useService404()
    }
  }

  return Promise.reject(axiosError.response)
}

// 403鉴权错误
function useService404() {
  // useUserStroe().loginout()
  // router.replace('/login')
}

// 处理401的
let promiseFlashing: Promise<void> | null = null
async function handleUnAuthorized(axiosError: AxiosError) {
  const userStore = useUserStore()
  if (!promiseFlashing) {
    promiseFlashing = userStore.getNewToken()
  }
  try {
    // 捕捉这一个错误
    await promiseFlashing
    return service.request(axiosError.config as AxiosRequestConfig)
  } catch (e) {
    // 获取refreshToken接口报错
    console.log(e)
    create401ErrorMsg()
    userStore.clearAllUserInfo()
    return Promise.reject(e)
  } finally {
    promiseFlashing = null
  }
}

let msgIns: MessageHandler | null = null

function create401ErrorMsg() {
  if (!msgIns) {
    msgIns = ElMessage({
      message: '重新获取token失败，请关闭标签页，重新打开',
      type: 'error',
      duration: 0,
    })
  }
  return msgIns
}
