import Vue from 'vue'
import { Loading } from 'element-ui'
import axios from 'axios'
import store from '@/store'
import router from '@/router'
import Storage from '@/utils/storage'
import https from 'https'
import checkToken from '@/utils/checkToken'
import { api } from '~/ui-domain'

const qs = require('qs')

// 创建axios实例
const service = axios.create({
  baseURL: api.admin,
  timeout: 5000,
  httpsAgent: new https.Agent({
    rejectUnauthorized: false
  }),
  paramsSerializer: params => qs.stringify(params, { arrayFormat: 'repeat' })
})

// request拦截器
service.interceptors.request.use(config => {
  // 如果是put/post请求，用qs.stringify序列化参数
  if (config.useMockApi && process.env.NODE_ENV === 'development') {
    // 开发环境使用mock api
    config.baseURL = api.mockApi
  }
  const is_put_post = config.method === 'put' || config.method === 'post'
  const is_json = config.headers['Content-Type'] === 'application/json'
  const is_form_data = Object.prototype.toString.call(config.data) === '[object FormData]'
  if (is_put_post && is_json) {
    config.data = JSON.stringify(config.data)
  }
  if (is_put_post && !is_json && !is_form_data) {
    config.data = qs.stringify(config.data, { arrayFormat: 'repeat' })
  }

  // uuid
  const uuid = Storage.getItem('admin_uuid')
  config.headers['uuid'] = uuid
  config.headers['AppType'] = 'Admin'

  /** 设置令牌 */
  let accessToken = Storage.getItem('admin_access_token')
  if (accessToken) {
    config.headers['Authorization'] = accessToken
  }
  // 如果是上传接口，不限制超时时间
  if (config.url === `${api.admin}/uploaders`) {
    config.timeout = 0
  }
  return config
}, error => {
  Promise.reject(error)
})

// respone拦截器
service.interceptors.response.use(
  async response => {
    await closeLoading(response)
    return response.data
  },
  async error => {
    await closeLoading(error)
    const error_response = error.response || {}
    const error_data = error_response.data || {}
    if (error_response.status === 403) {
      if (!Storage.getItem('admin_refresh_token')) return
      store.dispatch('fedLogoutAction')
      let to = Storage.getItem('admin_franchise') ? '/franchise/login' : '/login'
      window.location.replace(router.resolve(to).href)
      return
    }
    if (error.config.message !== false) {
      let _message = error.code === 'ECONNABORTED' ? '连接超时，请稍候再试！' : '网络错误，请稍后再试！'
      Vue.prototype.$message.error(error_data.message || _message)
    }
    return Promise.reject(error)
  }
)

/**
 * 关闭全局加载
 * 延迟200毫秒关闭，以免晃眼睛
 * @param target
 */
const closeLoading = (target) => {
  if (!target.config.loading) return true
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      target.config.loading.close()
      resolve()
    }, 200)
  })
}

export default function request(options) {
  if (options.needToken === false) return service(options)
  return new Promise((resolve, reject) => {
    checkToken(options).then(() => {
      service(options).then(resolve).catch(reject)
    })
  })
}
