import { createRouter, createWebHistory, NavigationGuardNext, RouteLocationNormalized, RouteRecordRaw } from "vue-router";
import store, { Action } from "../store";

/**
 * Check if the user is a guest; redirect otherwise
 */
function requiresGuest(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {
    if (store.getters.isAuthenticated) {
        console.log("Checking guest...");
        next({ name: "Home" });
        return;
    }
    next();
}

/**
 * Check if the user is authenticated; redirect otherwise
 */
function requiresAuth(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {
    if (!store.getters.isAuthenticated) {
        next({ name: "Login" });
        return;
    }
    next();
}

/**
 * Check if the user is an authenticated admin, redirect otherwise
 */
function requiresAdmin(to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) {
    if (store.getters.isAuthenticated && !store.getters.isAdmin) {
        next({ name: "Home" });
        return;
    }
    next();
}

const routes: RouteRecordRaw[] = [
    {
        path: "/",
        name: "Home",
        redirect: to => ({ name: "Dashboard" })
    },
    {
        path: "/dashboard",
        name: "Dashboard",
        component: () => import("../views/Dashboard.vue"),
        beforeEnter: requiresAuth
    },
    {
        path: "/search",
        name: "Search",
        component: () => import("../views/Search.vue"),
        beforeEnter: requiresAuth,
        children: [
            {
                path: ":tmdbId",
                name: "Lookup",
                component: () => import("../components/modals/MovieModal.vue"),
                props: true
            }
        ]
    },
    {
        path: "/admin",
        name: "Admin",
        redirect: to => ({ name: "AdminDashboard" }),
        component: () => import("../views/admin/Admin.vue"),
        beforeEnter: requiresAdmin,
        children: [
            {
                path: "dashboard",
                name: "AdminDashboard",
                component: () => import("../views/admin/AdminDashboard.vue"),
                props: true
            }
        ]
    },

    // Auth Routes ---------------------------------------------------------------------------------

    {
        path: "/login",
        name: "Login",
        component: () => import("../views/Login.vue"),
        beforeEnter: requiresGuest,
        meta: {
            disableNavBar: true
        }
    },
    {
        path: "/register",
        name: "Register",
        component: () => import("../views/Register.vue"),
        beforeEnter: requiresGuest,
        meta: {
            disableNavBar: true
        }
    },
    {
        path: "/logout",
        name: "Logout",
        component: {
            beforeRouteEnter(to, from, next) {
                store.dispatch(Action.AuthForget, undefined);
                next({ name: "Login" });
            }
        }
    },
    {
        path: "/link/discord/:token",
        name: "LinkDiscord",
        component: () => import("../views/LinkDiscord.vue"),
        meta: {
            disableNavBar: true
        }
    },
    {
        path: "/:pathMatch(.*)*",
        component: () => import("../views/Error404.vue")
    }
];

const router = createRouter({
    history: createWebHistory(),
    routes,
});

/**
 * Guard authentication and guest routes
 */
router.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.requiresAuth)) {
        if (localStorage.getItem("jwt") == null) {
            next({ name: "Login" });
            return;
        }
        let user = JSON.parse(<any>localStorage.getItem("user"));
        if (to.matched.some(record => record.meta.requiresAdmin)) {
            if (!user.isAdmin) {
                next({ name: "Home" });
                return;
            }
        }
    } else if (to.matched.some(record => record.meta.guest)) {
        if (localStorage.getItem("jwt") != null) {
            next({ name: "Home" });
            return;
        }
    }
    next();
});

export default router;
