import type {
  AxiosTransform,
  CreateAxiosOptions
} from '@/utils/http/AxiosTransform'
import { VAxios } from '@/utils/http/Axios'
import type { RequestOptions, Result } from '@/types/axios'
import { deepMerge, VerifyHttpParams } from '@/utils/'
import { ApiCustomeCode, Client } from '@/enums/api'
import { useUserStore } from '@/store'
import useUser from '@/hooks/user'

import type { AxiosResponse } from 'axios'
import { Message } from '@arco-design/web-vue'
import { getTime } from 'date-fns'

// import { ElMessage, ElNotification } from 'element-plus'

const { VITE_API_VER, VITE_APP_ID, VITE_API_URL } = import.meta.env // 获取环境变量
const CODEMESSAGE: { [key: number]: string } = {
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时(Gateway Timeout)。'
}
/**
 * @description: 数据处理，方便区分多种处理方式
 */
const transform: AxiosTransform = {
  /**
   * @description: 处理请求数据。如果数据不是预期格式，可直接抛出错误
   */
  transformRequestHook: async (
    res: AxiosResponse<Result>,
    options: RequestOptions
  ) => {
    // const { t } = useI18n();

    const { isTransformResponse, isReturnNativeResponse } = options
    // 是否返回原生响应头 比如：需要获取响应头时使用该属性
    if (isReturnNativeResponse) {
      return res
    }
    // 不进行任何处理，直接返回
    // 用于页面代码可能需要直接获取code，data，message这些信息时开启
    if (!isTransformResponse) {
      return res.data
    }
    // 错误的时候返回
    const { data } = res

    if (!data) {
      // return '[HTTP] Request has no return value';
      throw new Error('返回数据错误！')
    }
    //  这里 code，result，message为 后台统一的字段，需要在 types.ts内修改为项目自己的接口返回格式
    const { code, msg, ...result } = data
    // const router = useRouter()
    const userStore = useUserStore()
    const { getRouter } = userStore
    // 这里逻辑可以根据项目进行修改
    const hasSuccess =
      data && Reflect.has(data, 'code') && code === ApiCustomeCode.SUCCESS
    if (hasSuccess) {
      return result.data
    }
    const { logout } = useUser(getRouter)
    switch (code) {
      case 11000:
        logout()
        return false
      default:
        break
    }
    Message.error({
      content: msg.toString() || '内部错误',
      duration: 5000
    })
    throw new Error(msg || '请求错误')
  },

  // 请求之前处理config
  beforeRequestHook: (config, options) => {
    const userStore = useUserStore()
    const { apiUrl } = options
    // 添加http请求公共参数，并判断url是否属于白名单
    const publicRequestParams: VerifyHttpParams = {
      ver: VITE_API_VER as string,
      app_id: VITE_APP_ID as string,
      timestamp: getTime(new Date()),
      token: !(Client.LOGIN === config.url) ? userStore.getToken : undefined
    }
    config.url = `${apiUrl}${config.url}`
    config.data = Object.assign(publicRequestParams, { data: config.data })
    return config
  },

  /**
   * @description: 请求拦截器处理
   */
  requestInterceptors: config => {
    return config
  },

  /**
   * @description: 响应拦截器处理
   */
  responseInterceptors: (res: AxiosResponse<any>) => {
    return res
  },

  /**
   * @description: 响应错误处理
   */
  responseInterceptorsCatch: (error: any) => {
    const { response, code, message } = error || {}
    const msg: string = response?.data?.error?.message ?? ''
    const err: string = error?.toString?.() ?? ''
    let errMessage = ''
    try {
      if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
        errMessage = '请求超时！'
      }
      if (err?.includes('Network Error')) {
        errMessage = '网络异常！'
      }
      if (errMessage) {
        Message.error(errMessage)
        return Promise.reject(error)
      }
    } catch (e) {
      throw new Error(e as unknown as string)
    }

    checkStatus(error?.response?.status, msg)
    return Promise.reject(error)
  }
}

function createAxios(opt?: Partial<CreateAxiosOptions>) {
  return new VAxios(
    deepMerge(
      {
        timeout: 7500,
        // 基础接口地址
        headers: { 'Content-Type': 'application/json;charset=UTF-8' },
        // 数据处理方式
        transform,
        // 配置项，下面的选项都可以在独立的接口请求中覆盖
        requestOptions: {
          // 是否返回原生响应头 比如：需要获取响应头时使用该属性
          isReturnNativeResponse: false,
          // 需要对返回数据进行处理
          isTransformResponse: true,
          // 接口地址
          apiUrl: VITE_API_URL,
          errorMessageMode: 'message',
          // 忽略重复请求
          ignoreCancelToken: true
        }
      },
      opt || {}
    )
  )
}

export function checkStatus(status: number, statusText: string): void {
  if ((status >= 200 && status < 300) || status === 401 || status === undefined)
    return
  const errorText = CODEMESSAGE[status] || statusText
  // throw new Error(errorText)
  Message.error({
    content: `${status}: ${errorText}`,
    duration: 5000
  })
  //   ElMessage.error(`请求错误 ${status}: ${errorText}`)
  //   ElNotification({
  //     title: '请求错误',
  //     message: ` ${status}: ${errorText}`,
  //     type: 'error'
  //   })
}

export const request = createAxios()
