/**
 * api
 * v1.2
 */

import axios from 'axios'
import { token } from '@/common/token'
import status from './status'
const STATUS = status
import app from '@/main'

axios.defaults.baseURL = '/api'

/**
 * 最终直接根据url名称调用接口方法
 * 例如
 * import { api } from '@/api'
 * api.getItemGroupType(parmas).then(...)
 */
import urls from './requests'
import { settings } from 'nprogress'

const initInstance = (options) => {
    const instance = axios
        .create({
            headers: {
                Authorization: 'Bearer ' + token.value
            },
            ...options
        })

    instance.interceptors.response.use((res) => {
        if (res.data.status === STATUS.Unauthorized) {
            handlerUnauthorized()
        }
        return res
    }, (err) => {
        return Promise.reject(err)
    })
    return instance
}

const errerCodes = [STATUS.BadRequest, STATUS.InternalServerError, STATUS.Forbidden]

const errorNotification = ({ code, message }) => {
    switch (message.constructor) {
        case Array:
            message.map(p => {
                setTimeout(() => {
                    app.$notification.error({
                        duration: 30,
                        message: p.field,
                        description: p.messages.join('/'),
                    })
                })
            })
            break
        default:
            app.$notification.error({
                duration: 30,
                message: code || '错误',
                description: message,
            })
            break
    }
}

const handlerUnauthorized = () => {
    token.value = ''
    app.$router.replace({
        path: '/login'
    }).catch(() => { })
}

const api = {}

for (let key in urls) {

    const item = urls[key]
    let url = '',
        method = 'get',
        options = {}
    if (item.constructor === String) {
        url = item
    } else if (item.constructor === Array) {
        url = item[0]
        if (item[1]) {
            method = item[1].toLowerCase()
        }
        if (item[2]) {
            options = item[2]
        }
    } else if (item.constructor === Object) {
        url = item.url
        if (item.method) {
            method = item.method.toLowerCase()
        }
    }

    api[`${key}Await`] = function (params = {}) {
        if (method === 'post') {
            return initInstance(options).post(url, params)
        } else {
            let _params = [],
                _url = url
            Object.keys(params).forEach(key => {
                const value = params[key]
                if (value) {
                    switch (value.constructor) {
                        case Array:
                            _params.push(...value.map(p => `${key}=${p}`))
                            break
                        default:
                            _params.push(`${key}=${value}`)
                            break
                    }
                }
            })
            if (_params.length) {
                _url += '?' + _params.join('&')
            }
            return initInstance(options).get(_url)
        }
    }

    api[key] = function (params = {}) {
        return new Promise((reslove, reject) => {
            api[`${key}Await`](params)
                .then((res) => {
                    const { data } = res
                    if (errerCodes.indexOf(data.code) >= 0) {
                        errorNotification(data)
                        reject([ArrayBuffer, Blob].indexOf(data.constructor) > -1 ? res : data)
                    } else if (data.code === STATUS.Unauthorized) {
                        handlerUnauthorized()
                    } else {
                        reslove([ArrayBuffer, Blob].indexOf(data.constructor) > -1 ? res : data)
                    }
                })
                .catch(({ response }) => {
                    if (process.env.VUE_APP_NODE_ENV === 'development') {
                        const { data, status } = response
                        if (data.constructor === String) {
                            errorNotification({
                                message: data,
                                code: status
                            })
                        } else {
                            errorNotification(data)
                        }
                        if (data.code === STATUS.Unauthorized) {
                            handlerUnauthorized()
                        }
                        reject(data)
                    } else {
                        errorNotification({
                            message: '系统发生错误，请联系管理员'
                        })
                    }
                })
        })
    }

    api[key].url = axios.defaults.baseURL + url
    api[key].key = key
}

/**
 * 并发请求,与axios.all方式相同
 * 但是使用的接口函数为this.$api.[接口名]E
 */
api.$queue = function (queue) {
    return new Promise((reslove) => {
        axios.all(queue).then((results) => {
            const res = results.map(p => p.data)
            reslove(res)
        })
    })
}

export {
    axios,
    urls,
    api,
    STATUS
}
