import Auth from "@/api/Auth";
import VimConfig from "@/config/VimConfig";
import MessageUtils from "@/utils/MessageUtils";

/**
 * 请求类，支持无感刷新token
 * @author 乐天
 */
class FetchRequest {
    private static instance: FetchRequest;

    private constructor() {
    }

    /**
     * 单例构造方法，构造一个广为人知的接口，供用户对该类进行实例化
     * @returns {FetchRequest}
     */
    static getInstance() {
        if (!this.instance) {
            this.instance = new FetchRequest();
        }
        return this.instance;
    }

    /**
     * 请求方法
     * @param url 请求路径
     * @param params 参数
     * @param method 方法
     * @param isNeedToken 是否需要token
     */
    request = (
        url: string,
        params: string,
        method: string,
        isNeedToken = false
    ) => {
        const header: HeadersInit = {
            Accept: "application/json",
            "Content-Type": "application/json",
        };

        const token = Auth.getToken();
        if (isNeedToken && token) {
            header.Authorization = "Bearer " + token;
        }

        const config: RequestInit = {
            method: method,
            mode: "cors",
            headers: header,
        };

        if (method !== "GET") {
            config.body = params;
        }

        return this.fetch(this.getHost() + url, config)
            .then((response: any) => {
                return this.check(response);
            });
    };

    fetch = (url: string, config: RequestInit): Promise<any> => {
        return new Promise((resolve, reject) => {
            // @ts-ignore
            uni.request({
                url: url,
                method: config.method,
                data: config.body,
                header: config.headers,
                success(res) {
                    resolve(res)
                },
                fail(err) {
                    MessageUtils.error('无法链接网络');
                    reject(err)
                }
            })
        })

    }

    /**
     * 检查请求返回值，如果token失效,执行刷新方法
     * @param response 请求响应数据
     */
    check = (response: any) => {
        //token 失效
        if (response.statusCode === 200) {
            let res = response.data;
            if (res.code === 401) {
                Auth.logout()
            } else if (res.code !== 200) {
                MessageUtils.error(res.msg)
                return Promise.reject(res);
            } else {
                return Promise.resolve(res);
            }

        } else {
            MessageUtils.error("请求出错，状态码：" + response.statusCode)
            return Promise.reject("请求出错");
        }
    };
    /**
     * 获取有效的ip
     */
    getEffectiveIp = (): string => {
        return VimConfig.host;
    };
    getHost = (): string => {
        // return `${VimConfig.httProtocol}://${VimConfig.host}:${VimConfig.httPort}`
        return `${VimConfig.httProtocol}://${VimConfig.host}`
    };

    // 有些 api 并不需要用户授权使用，则无需携带 access_token；默认不携带，需要传则设置第三个参数为 true
    get = (url: string, isNeedToken = false) => {
        return this.request(url, "", "GET", isNeedToken);
    };

    post = (url: string, params: string, isNeedToken = false) => {
        return this.request(url, params, "POST", isNeedToken);
    };

    put = (url: string, params: string, isNeedToken = false) => {
        return this.request(url, params, "PUT", isNeedToken);
    };

    del = (url: string, params: string, isNeedToken = false) => {
        return this.request(url, params, "DELETE", isNeedToken);
    };

    patch = (url: string, params: string, isNeedToken = false) => {
        return this.request(url, params, "PATCH", isNeedToken);
    };
}

export default FetchRequest.getInstance();
