import axios from 'axios'
import store from '../bc-store'
import config from '@/config'
import router from '../bc-router'

const publicIp = require('public-ip');
// import { Spin } from 'view-design'
import {TOKEN_TYPE, getToken, getRefreshToken, setToken, TOKEN_KEY} from './token-util'
import Cookies from 'js-cookie'
import CONSTANT from '../bc-config/constant'
import {getNewToken} from '../bc-store/user-api'
import md5 from 'js-md5';

const addErrorLog = errorInfo => {
  const {statusText, status, request: {responseURL}} = errorInfo
  let info = {
    type: 'ajax',
    code: status,
    mes: statusText,
    url: responseURL
  }
  if (!responseURL.includes('save_error_logger')) store.dispatch('addErrorLog', info)
}

class HttpRequest {
  constructor(baseUrl = baseURL) {
    this.baseUrl = baseUrl
    this.queue = {}
  }

  getInsideConfig() {
    const config = {
      baseURL: this.baseUrl,
      headers: {
        //请求头
        'Authorization': `${getToken() == null ? '' : TOKEN_TYPE + getToken()}`//token
      }
    }
    //加入本机ip
    let ip = sessionStorage.getItem("ip")
    //记录当前登设备的ip,这里的没啥用.第一次提交的时候,由于异步,根本拿不到ip,
    //有用的在login登录页面
    /*if (!ip) {
      publicIp.v4().then(ip => {
        sessionStorage.setItem("ip", ip)
      });
    }*/
    if (ip)config.headers.ip = ip
    return config
  }

  destroy(url) {
    delete this.queue[url]
    if (!Object.keys(this.queue).length) {
      // Spin.hide()
    }
  }

  interceptors(instance, url) {
    // 请求拦截
    instance.interceptors.request.use(config => {
      // 添加全局的loading...
      if (!Object.keys(this.queue).length) {
        // Spin.show() // 不建议开启，因为界面不友好
      }
      this.queue[url] = true
      return config
    }, error => {
      return Promise.reject(error)
    })
    // 响应拦截
    instance.interceptors.response.use(res => {
      this.destroy(url)
      if (res.status === 200) {
        if (res.data.result && res.data.result === 'dep404') {
          store._vm.$Message.warning("当前操作用户没有绑定部门")
        }
      }
      const {data, status} = res
      return {data, status}
    }, error => {
      this.destroy(url)
      let errorInfo = error.response
      if (!errorInfo) {
        const {request: {statusText, status}, config} = JSON.parse(JSON.stringify(error))
        errorInfo = {
          statusText,
          status,
          request: {responseURL: config.url}
        }
      }
      if (errorInfo.status === 401) {//试着刷新一下token
        sessionStorage.setItem(getToken(), false)
        return this.doRequest(error);
      }
      console.log(errorInfo)
      //addErrorLog(errorInfo)
      return Promise.reject(error)
    })
  }

  request(options) {
    const instance = axios.create()
    options = Object.assign(this.getInsideConfig(), options)
    this.interceptors(instance, options.url)
    // 如果是不需要登陆的API则删掉Authorization
    if (options.url.indexOf('noTokenApi') > -1) {
      delete options.headers.Authorization
    }
    //判断重复请求
    this.checkRepeatRequest(options)
    return instance(options)
  }

  checkRepeatRequest(options){
    //防止重复请求 主要是针对post请求,原理如下:
    //不需管登录者,天然的环境就是一个浏览器的一个标签页.将请求参数进行排序,然后md5加密,并存入缓存(定时).
    //拦截到请求时,先判断试一下缓存中有没有这个请求的参数的MD5串,如果有,代表上一个相同请求才发完,就取消此请求,并提示 操作频繁
    if (config.request_frequency_control && config.request_frequency_control.toLowerCase() === 'true') {//判断是否开启
      if (config.request_frequency_control_scope.toLowerCase() &&
        (config.request_frequency_control_scope.toLowerCase() === 'all'
          || options.method.toLowerCase() === config.request_frequency_control_scope.toLowerCase())) {
        //json参数,进行排序,并转换成字符串
        let postParams = options.data
        if (!postParams) postParams = options.params
        let jsonStr = options.url
        if (postParams) {
          let keysArr = Object.keys(postParams)
          keysArr.sort()
          for (let key in keysArr) {
            jsonStr += '?' + keysArr[key] + "-" + postParams[keysArr[key]] + "|"
          }
        }
        //就算是post请求,也有可能在url后面拼参数的
        if (options.url.indexOf("?") > 0 && options.url.indexOf("=") > 0) {
          let arrSource = options.url.substring(options.url.indexOf("?") + 1, window.location.search.length).split("&"), i = 0;
          arrSource.sort()
          while (i < arrSource.length) {
            jsonStr += arrSource[i].split("=")[0] + "-" + arrSource[i].split("=")[1] + "|"
            i++
          }
        }
        //将参数字符串通过MD5加密
        let md5Str = md5(jsonStr);
        /*if (md5Str === 'a9f5e773c82085f136757d978ae9a624'){
          debugger
        }*/
        //判断缓存内有没有这个MD5
        let newTime = new Date().getTime()
        let oldTime = sessionStorage.getItem(md5Str)
        let interval = 2000
        if (config.request_frequency_control_interval){
          interval = parseInt(config.request_frequency_control_interval)
        }
        if (oldTime && newTime - oldTime < interval) {
          store._vm.$Message.warning("操作太快了,缓一缓吧!")
          console.log(options)
          //console.log(md5Str)
        }
        sessionStorage.setItem(md5Str, newTime)
      }
    }
  }

  async doRequest(error) {
    try {
      const data = await getNewToken(getRefreshToken());
      let token = data.data.access_token;
      setToken(token);
      error.config.headers.Authorization = TOKEN_TYPE + getToken()
      const res = await this.request(error.config)
      return res;
    } catch (err) {
      //if (!Cookies.get(CONSTANT.IS_GOING_LOGOUT_KEY)) {//这样子可以防止后面的请求频繁的触发弹超时提示
      store._vm.$Message.error({
        content: '登录超时,请重新登录! 即将跳转登录页面...',
        duration: 3,
        onClose: () => {
          let url = window.location.href;
          if (url.indexOf('/login') === -1) {
            //window.location.reload();
            //将正在退出的状态标记为 是 ,这样子可以防止后面的请求频繁的触发弹超时提示
            //Cookies.set(CONSTANT.IS_GOING_LOGOUT_KEY, true, 1)
            if (config.deploymentStandAlone) {
              router.push({
                name: 'logout'
              })
            } else {
              window.location.href = config.logout_url;//直接退出登录
            }
          }
        }
      })
      //}
      return err;
    }
  }
}

export default HttpRequest


