import axios from 'axios'
import { Message } from '@arco-design/web-vue'
import tool from '@/utils/tool'
import { get, isEmpty } from 'lodash'
import qs from 'qs'
import { h } from 'vue'
import { IconFaceFrownFill } from '@arco-design/web-vue/dist/arco-vue-icon'
import router from '@/router'

function createExternalService() {
  // 创建一个外部网络 axios 实例
  const service = axios.create()

  // HTTP request 拦截器
  service.interceptors.request.use(
    (config) => config,
    (error) => Promise.reject(error)
  )

  // HTTP response 拦截器
  service.interceptors.response.use(
    (response) => response,
    (error) => {
      Promise.reject(error.response ?? null)
    }
  )
  return service
}

function createService() {
  // 创建一个 axios 实例
  const service = axios.create()

  // HTTP request 拦截器
  service.interceptors.request.use(
    (config) => config,
    (error) => {
      console.log(error)
      // 失败
      return Promise.reject(error)
    }
  )

  // HTTP response 拦截器
  service.interceptors.response.use(
    (response) => {
      if (
        (response.headers['content-disposition'] ||
          !/^application\/json/.test(response.headers['content-type'])) &&
        response.status === 200
      ) {
        return response
      } else if (response.data.size) {
        response.data.code = 500
        response.data.message = '服务器内部错误'
        response.data.success = false
      } else if (response.data.code && response.data.code !== 200) {
        if (response.data.code === 401) {
          throttle(() => {
            Message.error({
              content: response.data.message || response.data.msg,
              icon: () => h(IconFaceFrownFill)
            })
            tool.local.clear()
            router.push({ name: 'login' })
          })()
        } else {
          Message.error({
            content: response.data.message || response.data.msg,
            icon: () => h(IconFaceFrownFill)
          })
        }
      }
      return response.data
    },
    (error) => {
      const err = (text) => {
        Message.error({
          content:
            error.response && error.response.data && error.response.data.message
              ? error.response.data.message
              : text,
          icon: () => h(IconFaceFrownFill)
        })
      }
      if (error.response && error.response.data) {
        switch (error.response.status) {
          case 404:
            err('服务器资源不存在')
            break
          case 500:
            err('服务器内部错误')
            break
          case 401:
            throttle(() => {
              err('登录状态已过期，需要重新登录')
              tool.local.clear()
              router.push({ name: 'login' })
            })()
            break
          case 403:
            err('没有权限访问该资源')
            break
          default:
            err('未知错误！')
        }
      } else {
        err('请求超时，服务器无响应！')
      }
      return Promise.resolve({
        code: error.response.status || 500,
        message: error.response.statusText || '未知错误'
      })
    }
  )
  return service
}

//节流
function throttle(fn, wait = 1500) {
  return function () {
    let context = this
    if (!throttle.timer) {
      fn.apply(context, arguments)
      throttle.timer = setTimeout(function () {
        throttle.timer = null
      }, wait)
    }
  }
}

function stringify(data) {
  return qs.stringify(data, { allowDots: true, encode: false })
}

function formatToken(token) {
  return token ? `Bearer ${token}` : null
}

/**
 * @description 创建请求方法
 * @param service
 * @param externalService
 */
function createRequest(service, externalService) {
  return function (config) {
    const env = import.meta.env
    const token = tool.local.get(env.VITE_APP_TOKEN_PREFIX)
    const setting = tool.local.get('setting')
    const configDefault = {
      headers: Object.assign(
        {
          Authorization: formatToken(token),
          'Accept-Language': setting?.language || 'zh_CN',
          'Content-Type': get(
            config,
            'headers.Content-Type',
            'application/json;charset=UTF-8'
          )
        },
        config.headers
      ),

      timeout: 10000,
      data: {}
    }

    delete config.headers
    // return
    const option = Object.assign(configDefault, config)

    // json
    if (!isEmpty(option.params)) {
      option.url = option.url + '?' + stringify(option.params)
      option.params = {}
    }

    if (!/^(http|https)/g.test(option.url)) {
      option.baseURL =
        env.VITE_APP_OPEN_PROXY === 'true'
          ? env.VITE_APP_PROXY_PREFIX
          : env.VITE_APP_BASE_URL
      return service(option)
    } else {
      return externalService(option)
    }
  }
}

export const service = createService()
export const externalService = createExternalService()
export const request = createRequest(service, externalService)
