import axios from 'axios';
import store from '@/store'
import { getToken,getUserId,removeToken,removeUserId } from '@/utils/token';
import { DES3 } from '@/utils/3des';
import router from '@/router/index'
import { message } from '../utils/message.js'
import { Caegw_ProUrl,Caegw_LogUrl } from '@/settings' ;// 引入settings.js


const requestList = []; // 请求列表
const CancelToken = axios.CancelToken;
let sources = {};
let successCode = '000000000' | '0000000';//成功编码

//axios配置
//全局的 axios 默认值:指定将被用在各个请求的配置默认值
axios.defaults.timeout = 20000;//设置超时时间
axios.defaults.baseURL = import.meta.env.VITE_BASE_URL;// `baseURL` 将自动加在 `url` 前面，除非 `url` 是一个绝对 URL。它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
//axios.defaults.headers.common['Authorization'] = AUT202H_TOKEN;//根据项目需要配置
//axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';//设置请求头的类型
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';//设置请求头的类型
// 添加请求拦截器
axios.interceptors.request.use(config => {
  const request = JSON.stringify(config.url) + (!!config.data ? JSON.stringify(config.data) : JSON.stringify(config.params))
  config.cancelToken = new CancelToken((cancel) => {
    sources[request] = cancel
  })
  //判断请求是否已存在请求列表，避免重复请求，将当前请求添加进请求列表数组；
  if (requestList.includes(request)) {
    // console.log(request)
    // sources[request]('取消重复请求')
    // requestList.splice(requestList.findIndex(item => item === request), 1)
    requestList.push(request)
  } else {
    requestList.push(request)
  }

  //因本项目部分请求需要重复获取所以不用去重
  // requestList.push(request)


  // 登录控制中根据本地是否存在token判断用户的登录情况，
  // 但即使token存在，也有可能token是过期的，所以在每次的请求头中携带token，
  // 后台根据携带的token判断用户的登录情况，并返回给我们对应的状态码，
  // 而后我们可以在响应拦截器中，根据状态码进行一些统一的操作。

  //本项目不用请求头判断而是在报文体中发送token
  // let token = store.getters.token || getToken();
  // token && (config.headers.Authorization = token);
  return config;
}, error => Promise.reject(error));


// 添加响应拦截器
axios.interceptors.response.use(res => {
  const request = JSON.stringify(res.config.url) + (!!res.config.data ? JSON.stringify(res.config.data) : JSON.stringify(res.config.params))
  requestList.splice(requestList.findIndex(item => item === request), 1)
  if (res.status === 200) {
    let { data } = res
    if (data.returnCode == successCode) {
      return Promise.resolve(data)
    } else {
      if (data.returnMsg === '系统没有登录或会话超时!' || data.returnMsg === '用户验证失败！') {
        removeToken();
        removeUserId();
        router.replace({ path: '/login' });
      }
      return Promise.reject(data)
    }
  } else {
    return Promise.reject(res)
  }
}, err => {
  const { res } = err;
  if (res) {
    // 请求已发出，但是不在2xx的范围
    requestList.length = 0;
    errorHandle(res.status, res.data.message);
    return Promise.reject(res);
  } else {
    console.log(err)
    if (err.message == '取消上传') {
      return Promise.reject('cancel')
    }
    // 处理断网的情况
    // eg:请求超时或断网时，更新network状态，可在app.vue中控制着一个全局的断网提示组件的显示隐藏
    if (err.message == '取消重复请求') {
      // console.log(err)
    } else {
      let error = err.message.indexOf('timeout') != -1 ? { returnMsg: '请求超时' } : { returnMsg: '网络通讯异常' };
      requestList.splice(requestList.findIndex(item => item === request), 1)
      return Promise.reject(error)
    }
  }
});

//完善请求url
function getUrl(channelNo = 'service') {
  let url = ''
  if (channelNo == 'service') {
    url = '/TransServlet'
  } else if (channelNo == 'manager') {
    url = '/managersvr/TransServlet'
  }
  return url
}

//配置上行报文公共包头
function getParams(params, channelNo) {
 // params['clientToken'] = "11112";
  params['clientToken'] = getToken()||"e47b87eec69545559d1e81e56626da68";
  let userId =getUserId() ||'5f06c8bc77234f969d13e160b54c27e3';
  // let userId = store.getters.userId;
  // if (userId) {
  params['userId'] = userId;
  // }
  params['channelNo'] = channelNo;
  return params;
}

// 请求
const request = (params, channelNo = 'service', method = 'post') => {
  let url = getUrl(channelNo);//完善请求url
  params = getParams(params, channelNo);//配置上行报文公共包头
  return new Promise((resolve, reject) => {
    if (method == 'post') {//'http://192.168.131:8187/TransServlet'
      axios.post(url, params).then(res => {
        resolve(res)
      }).catch(err => {
        // Message.error(err.returnMsg)
        reject(err)
      })
    } else if (method == 'get') {
      axios.get(url, { params }).then(res => {
        resolve(res)
      }).catch(err => {
        // Message.error(err.returnMsg)
        reject(err)
      })
    }
  })
}

// 文件上传
const uploadFile = (params, channelNo = 'service', callback1) => {
  let config = {
    timeout: 60000,
    headers: { "Content-Type": "multipart/form-data" },
    onUploadProgress: progressEvent => {
      //属性lengthComputable主要表明总共需要完成的工作量和已经完成的工作是否可以被测量,如果lengthComputable为false，就获取不到progress.total和progress.loaded
      if (progressEvent.lengthComputable) {
        let loaded = progressEvent.loaded
        let total = progressEvent.total
        // let progress = Math.floor((loaded / total) * 100) > 1 ? Math.floor((loaded / total) * 100) : 1;
        // console.log('上传进度 ' + progress + '%');
        // callback1(progress)
        
      }
    }
  }
  let url = getUrl(channelNo);//完善请求url
  params.append("clientToken", store.getters.token || getToken());
  params.append("userId", store.getters.userId);
  params.append("channelNo", channelNo);//配置上行报文公共包头
  console.log(params);
  return new Promise((resolve, reject) => {
    axios.post(url, params, config).then(res => {
      resolve(res)
    }).catch(err => {
      if (err != 'cancel') {
        message.error(err.returnMsg)
      }
      reject(err)
    })
  })
}

// 获取图片验证码
const getCode = (channelNo = 'service') => {
  let rand = Math.random();
  let token = store.getters.token || getToken();
  return process.env.VUE_APP_BASE_API + getUrl(channelNo) + '?transCode=HM0000&randomKey=' + rand + '&clientToken=' + token;
}

// 获取图片Url
const getImage = (id, channelNo = 'service') => {
  if (!id) return '';
  let token =  getToken() || store.token;
  let userId = getUserId();
  return import.meta.env.VITE_BASE_URL + getUrl(channelNo) + "?transCode=B00022&clientToken=" + token + "&userId=" + userId + "&id=" + id;
}

//加密密码
const enPassword = (password) => {
  let token =  getToken() || store.token;
  return DES3.encrypt(token, password);
}

export {
  request,
  uploadFile,
  getCode,
  getImage,
  enPassword,
  sources
}