import axios from 'axios'
import Vue from "vue";
import {Message, MessageBox} from "element-ui";

import store from "@/store";
import {removeToken,sleep} from "@/utils/auth";
import router, {resetRouter} from "@/router";
import {doEncrypt, doDecryptStr,doSign,doVerifySignature,userinfoEncrypt,userinfoDecrypt} from '@/utils/smutil'
const service = axios.create({
  headers: {'Cache-Control': 'no-cache'},
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 1000 * 60 * 10 // request timeout
})

service.interceptors.request.use(
  config =>  {
    const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
    // get请求映射params参数
    if (config.method === 'get' && config.params) {
      if (config.params.toString().indexOf('secretData') ==-1 && config.params.toString().indexOf('paramSign')==-1){
        // 不是token刷新后执行上次操作,进行参数加密。
        let encryptParam = doEncrypt(JSON.stringify(config.params))
        // 参数签名
        let paramSign = doSign(JSON.stringify(config.params))
        let result = 'secretData=' + encryptParam + '&paramSign=' + paramSign
        config.params = result
      }
    }

    if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put' || config.method === 'delete')) {
      if (config.url != '/getMailCode') {
        if (config.data !== undefined) {
          // 参数加密
          let encryptParam = doEncrypt(JSON.stringify(config.data))
          // 参数签名
          let paramSign = doSign(JSON.stringify(config.data))
          const param = {
            secretData: encryptParam,
            paramSign: paramSign
          }
          config.data = param
          if (config.url!='/user/login'){
            config.headers.post['Content-Type'] = 'application/json';
          }
        }
        else{
          Message({
            message: '请求拦截器检测出config.data是undefined不能提交!',
            type: 'error',
            duration: 5 * 1000
          })
          return
        }
      }
    }

    if (localStorage.getItem("jy")!=="undefined" && localStorage.getItem("jy")!==undefined && localStorage.getItem("jy")!=null) { // 判断是否存在token，如果存在的话，则每个http header都加上token
      let tokenStr = localStorage.getItem("jy")

      config.headers['Authorization'] = tokenStr.split("&")[0]
      config.headers['JySign'] = tokenStr.split("&")[1]
      // console.log('Authorization='+tokenStr)
      // console.log('TokenSign='+config.headers['TokenSign'])
    }
    return config
  },
  error => {
    // do something with request error
    // console.log(error) // for debug
    return Promise.reject(error)
  }
)

// 是否正在刷新的标记
let isRefreshing = false
//重试队列
let requests = []
// response interceptor
service.interceptors.response.use(
  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  response => {
    const res = response.data
    let returnStr = res.split("&")
    let returnData = returnStr[0].split("=")[1]
    let returnSign = returnStr[1].split("=")[1]
    // 解密
    let decData = doDecryptStr(returnData)
    // 验签
    let verifyResult = doVerifySignature(decData, returnSign)
    if (!verifyResult) {
      return Promise.reject(new Error('返回数据验签失败' || 'Error'))
    }
    let data = JSON.parse(decData)
    // if the custom code is not 20000, it is judged as an error.
    //console.log(res.code)
    if (data.code > 1) {
      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
      if (data.code === 50008 || data.code === 50012 || data.code === 50014) {
        // to re-login
        MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
          confirmButtonText: 'Re-Login',
          cancelButtonText: 'Cancel',
          type: 'warning'
        }).then(() => {
          store.dispatch('user/resetToken').then(() => {
            location.reload()
          })
        })
      }
      return Promise.reject(new Error(data.data))
    } else {
      return data
    }
  },
  async error => {
    if (error.response) {
      switch (error.response.status) {
        case 400:
          Message({
            message: '系统异常,请联系管理员！',
            type: 'error',
            duration: 5 * 1000
          })
          break
        case 405:
          Message({
            message: error.response.data,
            type: 'error',
            duration: 5 * 1000
          })
          break
        case 401:
          console.log('用户验证失败！')
          // 返回 401 清除token信息并跳转到登录页面
          removeToken()
          resetRouter()
          await sleep(2000);
          router.push('/login')
          Message({
            message: error.response.data,
            type: 'error',
            duration: 5 * 1000
          })
          break
        case 402:
          console.log('权限不足！')
          // 返回 401 清除token信息并跳转到登录页面
          removeToken()
          resetRouter()
          Message({
            message: error.response.data,
            type: 'error',
            duration: 5 * 1000
          })
          break
        case 406:
          // 返回 401 清除token信息并跳转到登录页面
          removeToken()
          resetRouter()
          await sleep(2000);
          router.push('/login')
          Message({
            message: error.response.data,
            type: 'error',
            duration: 5 * 1000
          })
          break
        case 407:
          Message({
            message: error.response.data,
            type: 'error',
            duration: 5 * 1000
          })
          router.push('/login')
          break
        case 410:
          removeToken()
          router.push('/404')
          Message({
            message: error.response.data,
            type: 'error',
            duration: 5 * 1000
          })
          break
        case 409:
          if (!isRefreshing) {
            isRefreshing = true
            //调用刷新token的接口
            return await  Vue.prototype.$axios.post(
              '/refreshToken',{}
            ).then((res) => {
              // const { token } = res.data
              // 替换token
              let tokenStr = doEncrypt(res.data)
              let sign = doSign(res.data)
              localStorage.setItem('jy', tokenStr+'&'+sign)
              // Vue.prototype.$axios(error.response.config)
              // 重新请求接口 前过期的接口
              error.config.headers.Authorization = res.data;
              requests.length > 0 && requests.map((cb) => {
                cb();
              });
              requests = [];  //注意要清空
              return Vue.prototype.$axios.request(error.config);
              // return error.response.config
            }).catch(err => {
              console.log(err)
              //跳到登录页
              removeToken()
              router.push('/login')
              // return Promise.reject(err)
            }).finally(() => {
              isRefreshing = false
            })
          }
          else {
            // 正在刷新token ,把后来的接口缓冲起来
            return new Promise((resolve) => {
              requests.push(() => {
                error.config.headers.Authorization = localStorage.getItem('jy');
                resolve(Vue.prototype.$axios.request(error.config));
              });
            })
          }
          break
        case 500:
          Message({
            message: '服务器关闭了！请联系相关工作人员',
            type: 'error',
            duration: 5 * 1000
          })
          removeToken()
          resetRouter()
          await sleep(2000);
          router.push('/login')
          break
        case 504:
          console.log('服务器关闭了！')
          removeToken()
          resetRouter()
          break

        // return Promise.reject(error.response.data)
      }
    }
    else{
      return Promise.reject(error)
    }
  }
)

export default service
