/* eslint-disable no-console */
/* eslint-disable no-param-reassign */

import { get, isObject } from 'lodash-es'
import Axios from 'axios'
import { trimData, isNullOrUndefined } from './util-methods'
import { ErrorCode } from './error-code'

let currentRequests = 0

export class AxiosWrapper {
  constructor({ baseUrl = import.meta.env.VITE_APP_BASE_API, unwrap = true } = {}) {
    this.baseUrl = baseUrl
    this.unwrap = unwrap
  }
  baseUrl
  unwrap

  // 替换uri中的参数变量
  static merge(uri, query) {
    if (!uri.includes(':')) {
      return uri
    }
    const keys = []
    const regexp = /\/:([a-z0-9_]+)/gi
    let res
    // eslint-disable-next-line no-cond-assign
    while ((res = regexp.exec(uri)) != null) {
      keys.push(res[1])
    }
    keys.forEach((key) => {
      const val = get(query, key)
      if (!isNullOrUndefined(val)) {
        uri = uri.replace(`:${key}`, `${val}`)
      }
    })
    return uri
  }

  $get(uri, query, options) {
    return this.$request(uri, undefined, query, options)
  }

  $post(uri, data = {}, query, options) {
    return this.$request(uri, data, query, options)
  }
  $delete(uri, data = {}, query, options = {}) {
    options = { ...options, method: 'delete' }
    return this.$request(uri, data, query, options)
  }
  async $request(uri, data, query, options) {
    if (query && isObject(query)) {
      const keys = Object.keys(query)
      for (const key of keys) {
        const val = get(query, key)
        if (val === '') {
          delete query[key]
        }
      }
    }
    if (isObject(query) && isObject(options)) {
      options = { ...options, params: query, method: 'get' }
    } else if (isObject(query) && !query.params) {
      options = { params: query }
    } else if (isObject(query) && query.params) {
      options = query
    }
    if (!options) options = {}
    if (options.params) options.params = trimData(options.params, null, null)
    const params = get(options, 'params')
    const url = AxiosWrapper.merge(uri, params)
    currentRequests += 1
    // Indicator.open({
    //   spinnerType: 'fading-circle',
    // });
    try {
      let returnData
      const axios = Axios.create({
        baseURL: this.baseUrl,
        withCredentials: true
      })
      // if (util.token && util.token !== null) axios.defaults.headers.common.Authorization = util.token;
      const token = localStorage.getItem('token')
      const apiToken = localStorage.getItem('apiToken')
      if (token) axios.defaults.headers.common['token'] = token
      if (apiToken) axios.defaults.headers.common['api-token'] = apiToken
      const res = await axios.request({
        method: isNullOrUndefined(data) ? 'get' : 'post',
        url,
        data,
        responseType: 'json',
        ...options
      })
      const returnRes = res.data
      const { errcode, errmsg, details } = returnRes
      if (errcode) {
        console.warn(`[${uri}] fail: ${errcode}-${errmsg} ${details}`)
        return returnRes
      }
      // unwrap data
      if (this.unwrap) {
        returnData = returnRes
      }
      // 处理apiToken
      const { apiToken: at, ...others } = returnData
      if (at) localStorage.setItem('apiToken', at)
      return others
    } catch (err) {
      let errmsg = '接口请求失败，请稍后重试'
      if (err.response) {
        const { status } = err.response
        if (status === 401) errmsg = '用户认证失败，请重新登录'
        if (status === 403) errmsg = '当前用户不允许执行该操作'
      }
      console.error(
        `[AxiosWrapper] 接口请求失败: ${err.config && err.config.url} - 
        ${err.message}`
      )
      return { errcode: ErrorCode.SERVICE_FAULT, errmsg, details: err.message }
    } finally {
      /* eslint-disable */
      currentRequests -= 1
      if (currentRequests <= 0) {
        currentRequests = 0
        // Indicator.close();
      }
    }
  }
}
