/**
 * api
 * v1.2
 */

import axios from 'axios'
import { token } from 'common/token'
import status from './status'
/**
 * 最终直接根据url名称调用接口方法
 * 例如
 * import { api } from '@/api'
 * api.getItemGroupType(parmas).then(...)
 */
import urls from './requests'
import { message as Message, notification } from 'antd'

const STATUS = status

axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? '/api' : process.env.REACT_APP_BASE_URL

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.forEach(p => {
                setTimeout(() => {
                    notification.error({
                        duration: 30,
                        message: p.field,
                        description: p.messages.join('/'),
                    })
                })
            })
            break
        default:
            notification.error({
                duration: 30,
                message: code || '错误',
                description: message,
            })
            break
    }
}

const errorMessage = (message) => {
    Message.error(message)
}

const handlerUnauthorized = () => {
    token.value = ''
    window.location.replace('/login')
}

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
                    const isFile = [ArrayBuffer, Blob].includes(data.constructor)
                    const result = isFile ? res : data

                    // 错误的返回码,以通知的形式弹出
                    if (errerCodes.indexOf(data.code) >= 0) {
                        errorNotification(data)
                        reject(result)
                    }

                    // 非文件,返回码正确,但是结果失败,以消息的形式弹出
                    else if (!isFile && !data.success) {
                        errorMessage(data.message)
                        reject(result)
                    }

                    // 未登录
                    else if (data.code === STATUS.Unauthorized) {
                        handlerUnauthorized()
                    }

                    else {
                        reslove(result)
                    }
                })
                .catch(({ response }) => {
                    const { data, status } = response
                    if (data.constructor === String) {
                        errorNotification({
                            message: data,
                            code: status
                        })
                    } else {
                        errorNotification(data)
                    }
                    if (data.code === STATUS.Unauthorized) {
                        handlerUnauthorized()
                    }
                    reject(data)
                })
        })
    }

    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
}
