import axios from 'axios'
import qs from 'qs'
import { Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'

// // create an axios instance
// const service = axios.create({
//   baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
//   // withCredentials: true, // send cookies when cross-domain requests
//   timeout: apiConfig.timeout // request timeout
// })

/**
 * 设置全局参数
 */
axios.defaults.baseURL = process.env.VUE_APP_BASE_API
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
// axios.defaults.withCredentials = true
axios.defaults.timeout = process.env.VUE_APP_API_TIMEOUT

// request interceptor
axios.interceptors.request.use(
  config => {
    // do something before request is sent
    if (store.getters.token) {
      // let each request carry token
      // ['X-Token'] is a custom headers key
      // please modify it according to the actual situation
      config.headers['authorization'] = `Bearer ${getToken()}`
    }
    return config
  },
  error => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

// response interceptor
axios.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
  */

  /**
   * 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
    console.log(response)
    if (res.type === 'application/octet-stream') {
      return res
    }
    // if the custom code is not 200, it is judged as an error.
    if (res.code !== 200) {
      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
        // to re-login
        // msgBox.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()
        //   })
        // })
      }

      Message({
        message: res.msg || 'Error',
        type: 'error',
        duration: 5 * 1000
      })
      return Promise.reject(new Error(res.msg || 'Error'))
    } else {
      return res
    }
  },
  error => {
    console.log() // for debug
    Message.error({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  }
)

// 预处理配置文件
const pretreatConfig = (_config) => {
  if (_config && 'dataType' in _config) {
    if (_config.dataType === 'json') {
      Object.assign(_config, {
        headers: {
          'Content-Type': 'application/json;charset=UTF-8'
        }
      })
    } else if (_config.dataType === 'formdata') {
      Object.assign(_config, {
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
        }
      })
    }
  }
  if (process.env.NODE_ENV !== 'production' &&
  _config &&
  'mock' in _config &&
  _config.mock
  ) {
    Object.assign(_config, {
      baseURL: process.env.VUE_APP_BASE_API_MOCK
    })
  }
  return _config
}

/**
 * 处理response
 * @param {axios请求结果} fetchResult
 */
const formatResponse = fetchResult => fetchResult
  .then(response => formatStatus(response))
  .then(res => formatCode(res), handleNetworkError)

/**
 * 格式化status
 */
const formatStatus = (response) => {
  // 如果http状态码正常，则直接返回数据
  if (response && (response.code === 200 || response.code === 304 || response.code === 400)) {
    response.success = true
    return response
    // 如果不需要除了data之外的数据，可以直接 return response.data
  }
  let txt = '网络异常'
  if (!response) {
    txt = '通信错误'
  } else if (response.code === 500) {
    txt = '服务器错误'
  // } else if (response.code === 401) {
  //   txt = '身份验证失败'
  }
  // 异常状态下，把错误信息返回去
  return {
    code: -404,
    msg: txt,
    request: response.request || {}
  }
}

/**
 * 格式化code
 */
const formatCode = ({
  code,
  data,
  msg
}) => {
  // 如果code异常(这里已经包括网络错误，服务器错误，后端抛出的错误)，可以弹出一个错误提示，告诉用户
  if (code === -404) {
    return {
      code: code,
      success: false,
      msg,
      data: {}
    }
  }
  // // api内置错误类型
  // if (data && !data.success) {
  //   let msg = data.msg
  //   if (data.code === 500) {
  //     msg = '内部服务器错误'
  //   }
  //   return {
  //     success: false,
  //     msg,
  //     code: data.code,
  //     errorObj: data.error,
  //     data: {}
  //   }
  // }
  console.log()
  return {
    success: true,
    msg: msg || '',
    code,
    data
  }
}

// 处理网络通信错误
const handleNetworkError = (error) => {
  if (error) {
    if (error.response && error.response.status === 500) {
      return {
        code: 500,
        success: false,
        msg: '通信错误',
        data: {}
      }
    } if (error.message.includes('timeout')) {
      return {
        code: 1,
        success: false,
        msg: '通信超时',
        data: {}
      }
    // } if (error.msg.includes('404')) {
    //   return {
    //     code: 1,
    //     success: false,
    //     msg: '通信失败',
    //     data: {}
    //   }
    }
  }
  return {
    code: -1,
    success: false,
    msg: '',
    data: {}
  }
}

const formatDownload = fetchResult => fetchResult
  .then(response => {
    console.log(response)
    const filename = `宝宝成长曲线.zip`
    const blob = response
    if (typeof window.navigator.msSaveBlob !== 'undefined') {
      // IE workaround for "HTML7007: One or more blob URLs were
      // revoked by closing the blob for which they were created.
      // These URLs will no longer resolve as the data backing
      // the URL has been freed."
      window.navigator.msSaveBlob(blob, filename)
    } else {
      const blobURL = window.URL.createObjectURL(blob)
      const tempLink = document.createElement('a')
      tempLink.style.display = 'none'
      tempLink.href = blobURL
      tempLink.setAttribute('download', filename)

      // Safari thinks _blank anchor are pop ups. We only want to set _blank
      // target if the browser does not support the HTML5 download attribute.
      // This allows you to download files in desktop safari if pop up blocking
      // is enabled.
      if (typeof tempLink.download === 'undefined') {
        tempLink.setAttribute('target', '_blank')
      }

      document.body.appendChild(tempLink)
      tempLink.click()
      document.body.removeChild(tempLink)
      window.URL.revokeObjectURL(blobURL)
    }
    //   Message({
    //     message: '请求下载文件失败,请稍后重试~',
    //     type: 'error',
    //     duration: 5 * 1000
    //   })
    // }
  })

export const get = (url, data = {}, config) => {
  config = pretreatConfig(config)
  return formatResponse(axios.get(url, {
    ...config,
    params: data,
    paramsSerializer(params) {
      return qs.stringify(params, { arrayFormat: 'brackets' })
    }
  }))
}

export const del = (url, data = {}, config, type) => {
  config = pretreatConfig(config)
  return formatResponse(axios.delete(url, {
    ...config,
    params: data,
    paramsSerializer(params) {
      return qs.stringify(params, { arrayFormat: 'brackets' })
    }
  }))
}

export const delData = (url, data = {}, params, config) => {
  config = pretreatConfig(config)
  return formatResponse(axios.delete(url, {
    ...config,
    data: data,
    params: params,
    paramsSerializer(params) {
      return qs.stringify(params, { arrayFormat: 'brackets' })
    }
  }))
}

export const post = (url, data = {}, config) => {
  config = pretreatConfig(config)
  config = Object.assign({
    headers: {
      'Content-Type': 'application/json; charset=UTF-8'
    }
  }, config)
  return formatResponse(axios.post(url, data, config))
}

export const put = (url, data = {}, config) => {
  config = pretreatConfig(config)
  config = Object.assign({
    headers: {
      'Content-Type': 'application/json; charset=UTF-8'
    }
  }, config)
  return formatResponse(axios.put(url, data, config))
}

// export const download = (url, params, { baseURL } = {}) => {
//   const urls = process.env.VUE_APP_BASE_API
//   const relUrl = urls + url
//   // location.href = config.baseURL + url + '?' + qs.stringify(params);
//   window.open(`${relUrl}?${qs.stringify(params)}`, '_blank')
// }

export const download = (url, data = {}, config) => {
  config = pretreatConfig(config)
  config = Object.assign({
    headers: {
      'Content-Type': 'application/json'
    },
    responseType: 'blob'
  }, config)
  return formatDownload(axios.post(url, data, config))
}

// export default service
export default {
  get,
  post,
  del,
  put,
  delData,
  download
}
