import axios from 'axios'
import settings from '@/config'
import router from '@/router/index'
import {Message, MessageBox} from 'element-ui';
import {storage} from "@/utils/storage";
import qs from 'qs';
import Vue from "vue";

const baseURL = process.env.NODE_ENV === 'development' ? settings.baseUrl.dev : settings.baseUrl.pro;

axios.defaults.baseURL = baseURL;
axios.defaults.paramsSerializer = (params) => qs.stringify(params, {arrayFormat: 'repeat'});
axios.defaults.headers.common['Platform'] = "web";
// axios.defaults.headers.get['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.headers.get['Content-Type'] = 'application/json;charset=UTF-8';
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8';
axios.defaults.headers.delete['Content-Type'] = 'application/json;charset=UTF-8';
axios.defaults.headers.put['Content-Type'] = 'application/json;charset=UTF-8';
axios.defaults.withCredentials = false;
axios.defaults.timeout = 5000;

const requestPermissions = () => {
    // 更新本地权限
    const userInfo = storage.getUserInfo();
    axios.get(settings.responseKey.permissionsUrl).then(data => {
        userInfo.permissions = data;
        if (process.env.NODE_ENV === 'development') {
            if (userInfo.permissions) {
                userInfo.permissions.push("developer");
            } else {
                userInfo.permissions = ["developer"];
            }
        }
        storage.setUserInfo(userInfo);
    })
}

axios.interceptors.request.use(config => {
    config.headers[settings.tokenKey] = storage.getToken();
    console.log(config.url, config);
    // TODO 重复提交校验
    return config;
}, error => {
    console.log("request", error);
    Message.warning(error);
    return Promise.reject(error);
});

axios.interceptors.response.use(response => {
    console.log(response.config.url, response);
    const message = response.data[settings.responseKey.message];
    let code = response.data[settings.responseKey.code];
    code = code && parseInt(code)
    if (code === settings.responseKey.successCode) {
        return response.data[settings.responseKey.data];
    } else if (code === settings.responseKey.authFailCode) { // 登录过期
        // 可以操作store
        // store.dispatch('user/LOGOUT').then(() => {});
        if (router.currentRoute.path !== '/login') {
            message && Message.warning(message);
            storage.removeUserInfo();
            router.push({
                path: '/login',
                query: {redirect: router.currentRoute.path, ...router.currentRoute.query}
            }).then();
        }
        return Promise.reject(new Error(message))
    } else if (code === settings.responseKey.permissionsExpiredCode) { // 权限过期
        // 更新本地权限
        requestPermissions();
        // 提示用户刷新界面
        MessageBox.confirm('权限已被更改, 页面将被刷新?', '提示', {
            confirmButtonText: '立即刷新',
            cancelButtonText: '稍后手动刷新',
            type: 'warning'
        }).then(() => {
            location.reload();
        });
        return Promise.reject(new Error(message))
    } else if (!code) {
        return response
    } else { // 其他错误
        Message.warning(message || "error");
        return Promise.reject(new Error(message))
    }
}, error => {
    console.log("response", error.response && error.response.data || error);
    error.response && error.response.data && Message.warning(error.response.data.message || error.response.data);
    return Promise.reject(error);
});

if (storage.getToken()) {
    requestPermissions();
}


const axiosLoading = {
    ...axios,
    get: (url, config, showLoading = true) => {
        if (config?.params) {
            Object.keys(config.params).forEach(key => {
                if (config.params[key] === null) {
                    delete config.params[key];
                }
            });
            config.params = JSON.parse(JSON.stringify(config.params))
        }
        if (showLoading) {
            const loading = Vue.prototype.loading();
            return new Promise((resolve, reject) => {
                axios.get(url, config).then(data => {
                    resolve(data);
                }).catch(error => {
                    reject(error)
                }).finally(() => {
                    loading.close();
                })
            })
        } else {
            return axios.get(url, config);
        }
    },
    post: (url, data, showLoading = true) => {
        // let config = {};
        // if (data instanceof FormData) {
        //     config.headers = {"Content-Type": "multipart/form-data"};
        // } else
        if (data) {
            data = JSON.parse(JSON.stringify(data))
        }
        if (showLoading) {
            const loading = Vue.prototype.loading();
            return new Promise((resolve, reject) => {
                axios.post(url, data).then(data => {
                    resolve(data);
                }).catch(error => {
                    reject(error)
                }).finally(() => {
                    loading.close();
                })
            })
        } else {
            return axios.post(url, data);
        }
    },
    put: (url, data, showLoading = true) => {
        if (data) {
            data = JSON.parse(JSON.stringify(data))
        }
        if (showLoading) {
            const loading = Vue.prototype.loading();
            return new Promise((resolve, reject) => {
                axios.put(url, data).then(data => {
                    resolve(data);
                }).catch(error => {
                    reject(error)
                }).finally(() => {
                    loading.close();
                })
            })
        } else {
            return axios.put(url, data);
        }
    },
    delete: (url, config, showLoading = true) => {
        if (config?.params) {
            Object.keys(config.params).forEach(key => {
                if (config.params[key] === null) {
                    delete config.params[key];
                }
            });
            config.params = JSON.parse(JSON.stringify(config.params))
        }
        if (showLoading) {
            const loading = Vue.prototype.loading();
            return new Promise((resolve, reject) => {
                axios.delete(url, config).then(data => {
                    resolve(data);
                }).catch(error => {
                    reject(error)
                }).finally(() => {
                    loading.close();
                })
            })
        } else {
            return axios.delete(url, config);
        }
    },
    // POST multipart/form-data 格式上传文件
    upload: (url, file, filename) => {
        let formData = new FormData();
        formData.append("file", file, filename || file.name);
        let config = {
            headers: {"Content-Type": "multipart/form-data"}
        }
        return axios.post(url, formData, config);
    }
};

export const $axios = axiosLoading;

export default {
    install: function (Vue) {
        Vue.prototype.$axios = axiosLoading;
    }
};
