import axios from 'axios';
import qs from "qs";

// 创建axios实例
const httpService = axios.create({
    baseURL: window.location.origin,
    timeout: 10 * 60 * 1000,
    withCredentials: true // 跨域请求时发送Cookie
});

// request拦截器
httpService.interceptors.request.use(
    config => {
        return config;
    },
    error => Promise.reject(error)
)

// response拦截器
httpService.interceptors.response.use(
    response => {
        // // 后端返回状态码为-10003表示鉴权失败, 直接路由到登陆页
        // if (res && res.code === -10003){
        //     return router.push('/login');
        // }
        return response.data;
    },
    error => {
        if (error && error.response) {
            switch (error.response.status) {
                case 400:
                    error.message = '错误请求';
                    break;
                case 401:
                    error.message = '未授权，请重新登录';
                    break;
                case 403:
                    error.message = '拒绝访问';
                    break;
                case 404:
                    error.message = '请求错误,未找到该资源';
                    break;
                case 405:
                    error.message = '请求方法未允许';
                    break;
                case 408:
                    error.message = '请求超时';
                    break;
                case 500:
                    error.message = '服务器端出错';
                    break;
                case 501:
                    error.message = '网络未实现';
                    break;
                case 502:
                    error.message = '网络错误';
                    break;
                case 503:
                    error.message = '服务不可用';
                    break;
                case 504:
                    error.message = '网络超时';
                    break;
                case 505:
                    error.message = 'http版本不支持该请求';
                    break;
                default:
                    error.message = `未知错误${error.response.status}`;
            }
        } else {
            error.message = "连接到服务器失败";
        }
        return Promise.reject(error);
    }
)

/**
 * get请求
 * @param url
 * @param params
 * @returns {Promise<unknown>}
 */
export function get(url, params = {}) {
    return new Promise((resolve, reject) => {
        httpService({
            url: url,
            method: 'get',
            params: params,
            headers: {'Content-Type': 'application/json'}
        }).then(response => {
            resolve(response);
        }).catch(error => {
            reject(error);
        });
    });
}

/**
 * post请求, 默认请求头信息为: application/json
 * @param url
 * @param params
 * @returns {Promise<unknown>}
 */
export function post(url, params = {}) {
    return new Promise((resolve, reject) => {
        httpService({
            url: url,
            method: 'post',
            data: params
        }).then(response => {
            resolve(response);
        }).catch(error => {
            reject(error);
        });
    });
}

/**
 * put请求, 默认请求头信息为: application/json
 * @param url
 * @param params
 * @returns {Promise<unknown>}
 */
 export function put(url, params = {}) {
    return new Promise((resolve, reject) => {
        httpService({
            url: url,
            method: 'put',
            data: params
        }).then(response => {
            resolve(response);
        }).catch(error => {
            reject(error);
        });
    });
}
/**
 * delete请求, 默认请求头信息为: application/json
 * @param url
 * @param params
 * @returns {Promise<unknown>}
 */
 export function deleteApi(url, params = {}) {
    return new Promise((resolve, reject) => {
        httpService({
            url: url,
            method: 'delete',
            data: params
        }).then(response => {
            resolve(response);
        }).catch(error => {
            reject(error);
        });
    });
}

/**
 * post请求, 表单提交, 请求头为: application/x-www-form-urlencoded
 * @param url
 * @param params
 * @returns {Promise<unknown>}
 */
export function postForm(url, params = {}) {
    return new Promise((resolve, reject) => {
        httpService({
            url: url,
            method: 'post',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            data: qs.stringify(params, {skipNulls: true})
        }).then(response => {
            resolve(response);
        }).catch(error => {
            reject(error);
        });
    });
}

/**
 *  表单携带文件上传, Post请求, 表单参数与file在同一个对象参数中, 特定文件key为file或者files
 *  后端直接对象接收即可或者和文件接收类似的一个个属性接收@RequestParam("files") MultipartFile[] files
 * @param url
 * @param params
 * @returns {Promise<unknown>}
 */
export function postFormData(url, params = {}) {
    let formData = new FormData()
    for (let [key, value] of Object.entries(params)) {
        if ((key === 'file' || key === 'files') && value instanceof Array && value.length !== 0) {
            value.forEach(f => {
                formData.append(key, f)
            })
        } else {
            if (value !== null && value !== undefined) {
                formData.append(key, params[key])
            }
        }
    }
    return fileUpload(url, formData);
}

/**
 *  表单携带文件上传, Post请求, 表单参数与file分开接收
 *  1、后端参数部分使用@RequestPart("param") JacocoVo jacocoVo
 *  2、内部根据传入的参数和files 进行formData的填充
 * @param url
 * @param params
 * @param files
 * @returns {Promise<unknown>}
 */
export function postFormMulitFile(url, params = {}, files = []) {
    let formData = new FormData()
    files.forEach(file => {
        formData.append('files', file)
    })
    formData.append('param',
        new Blob(
            [
                JSON.stringify(params)
            ], {
                type: "application/json"
            }));
    return fileUpload(url, formData);
}

/**
 * 文件上传
 * @param url
 * @param formData   参数需要是一个let formData = new FormData()类型, 后端直接用实体接收文件之外的参数, 文件通过@RequestParam("files") MultipartFile[] files接收
 * @returns {Promise<unknown>}
 */
function fileUpload(url, formData = {}) {
    return new Promise((resolve, reject) => {
        httpService({
            url: url,
            method: 'post',
            data: formData
        }).then(response => {
            resolve(response);
        }).catch(error => {
            reject(error);
        });
    });
}

export default {
    get,
    post,       // json
    put,  //json
    postForm,   // 表单
    postFormData, // 表单带文件
    postFormMulitFile, // 表单带文件, 其他参数为json
    deleteApi
}
