import router from "@/router/index.js";
import store from "@/store";
import NProgress from "nprogress"; // progress bar
import "./progress.css";
import { getToken, getUserName } from "@/utils/auth"; // getToken from cookie
import _ from "lodash";

const { initSettings, getSetting, getSettings, getSettingBool } = window.systemParamsUtils;

NProgress.configure({ showSpinner: false }); // NProgress Configuration

// 合并白名单列表
const WHITE_LIST = getSetting("WHITE_LIST");
let whiteList = ["/login", "/auth-redirect"]; // no redirect whitelist
if (WHITE_LIST instanceof Array) {
    whiteList = whiteList.concat(WHITE_LIST);
}

router.beforeEach((to, from, next) => {
    NProgress.start(); // start progress bar
    let queryObject = getQueryObject();
    if (_.isEmpty(getSettings())) {
        initSettings().then(() => location.reload()); // 如果配置信息为空，则先加载配置信息
    } else if (!getSettingBool("NEED_LOGIN") || whiteList.indexOf(to.path) !== -1) {
        noNeedLogin(to, from, next); // 如果项目不需要登录或页面url在白名单中，则不需要获取用户信息和权限
    } else if (getSettingBool("IS_OAUTH2") && queryObject.code) {
        getAccessToken(queryObject); // 如果使用oauth2登录并且地址栏中有code参数，则去请求token
    } else {
        checkLogin(to, next); // 检查是否登录
    }
});

/**
 * 将url的参数转为对象
 * 不传默认获取当前浏览器地址的参数
 */
function getQueryObject(url = window.location.href) {
    const search = url.substring(url.lastIndexOf("?") + 1);
    const obj = {};
    const reg = /([^?&=]+)=([^?&=]*)/g;
    search.replace(reg, (rs, $1, $2) => {
        const name = decodeURIComponent($1);
        let val = decodeURIComponent($2);
        val = String(val);
        obj[name] = val;
        return rs;
    });
    return obj;
}

// permission judge function
function hasPermission(userPermissions = [], routePermissions = []) {
    if (routePermissions && routePermissions.length === 0) {
        return true;
    }
    return userPermissions.some(userPermission => {
        return routePermissions.indexOf(userPermission) >= 0;
    });
}

router.afterEach(() => {
    NProgress.done(); // finish progress bar
});

/**
 * 不需要登录则直接加载所有路由
 * @param to
 * @param from
 * @param next
 */
function noNeedLogin(to, from, next) {
    if (store.getters.addRouters.length === 0) {
        generateRoutes([], next, to);
    } else {
        next();
    }
}

/**
 * 如果是Oauth2登录并且地址栏上有code字段，则去请求access_token
 * @param queryObject   地址栏上的参数
 */
async function getAccessToken(queryObject) {
    let code = queryObject.code.split("#/")[0];
    try {
        await store.dispatch("GetOAuthToken", { code });
        if (getToken()) {
            window.location.href = "http://" + window.location.host + decodeURIComponent(window.location.pathname);
        }
    } catch (reason) {
        console.error(reason);
        store.dispatch("FedLogout").then(() => {
            location.reload();
        });
    }
}

/**
 * 检查是否在白名单中,进行页面跳转
 * @param to
 * @param next
 * @param link
 */
function checkIsInWhiteList(to, next, link, result) {
    if (whiteList.indexOf(to.path) !== -1) {
        next(); // 在免登录白名单，直接进入
    } else if (result instanceof Promise) {
        result.then(result => {
            if (result && result.status === 403 && result.link) {
                console.error("oauth2验证不通过，将跳转到登录页");
            }
        });
    } else {
        !link && next(`/login?redirect=${to.path}`); // 否则全部重定向到登录页
        NProgress.done(); // if current page is login will not trigger afterEach hook, so manually handle it
    }
}

/**
 * 生成路由
 * @param permissions   用户权限
 * @param next
 * @param to
 */
function generateRoutes(permissions, next, to) {
    store.dispatch("GenerateRoutes", { permissions }).then(() => {
        // 根据权限生成可访问的路由表
        router.addRoutes(store.getters.addRouters); // 动态添加可访问路由表

        if (hasPermission(store.getters.permissions, to.meta.permission)) {
            next({ ...to, replace: true });
        } else {
            next({
                path: "/",
                replace: true
            });
        }
        // next({ ...to, replace: true }); // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
    });
}

function checkLogin(to, next) {
    console.log(getUserName());
    if (getUserName()) {
        if (to.path === "/login") {
            next({ path: "/" });
            NProgress.done(); // if current page is dashboard will not trigger	afterEach hook, so manually handle it
        } else {
            let permissionsLength = store.getters.permissions.length;
            if (!store.getters.name && !permissionsLength) {
                try {
                    // 获取用户信息
                    // await ;
                    store.dispatch("GetUserInfo").then(() => {
                        let permissions = store.getters.permissions;
                        generateRoutes(permissions, next, to);
                    });
                } catch (err) {
                    store.dispatch("FedLogout").then(() => {
                        if (!err.link) {
                            next(`/login?redirect=${to.path}`); // 否则全部重定向到登录页
                        } else {
                            next({ path: "/" });
                        }
                    });
                    // await store.dispatch("FedLogout")   // 如果获取用户信息失败，则将本地的用户信息相关的东西清空，并登出
                    // if (!err.link) {
                    //     next(`/login?redirect=${to.path}`); // 否则全部重定向到登录页
                    // } else {
                    //     next({ path: "/" });
                    // }
                }
            } else {
                // 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
                // if (hasPermission(store.getters.roles, to.meta.roles)) {
                next();
                // } else {
                //     next({
                //         path: "/401",
                //         replace: true,
                //         query: { noGoBack: true }
                //     });
                // }
                // 可删 ↑
            }
        }
    } else {
        if (getSetting("BASE_API") === "/easy-mock") {
            checkIsInWhiteList(to, next); // 检查是否在白名单中
        } else {
            try {
                store.dispatch("GetUserInfo").then(() => {
                    window.location.reload();
                });
                // await store.dispatch("GetUserInfo")
                // window.location.reload();
            } catch (result) {
                let link;
                result && (link = result.link);

                checkIsInWhiteList(to, next, link, result); // 检查是否在白名单中
            }
        }
    }
}
