import { sessionStorageKeyConstants } from "@/constants/session-storage";
import {
    getFunnelCookie,
    updateOrCreateFunnelCookie,
} from "@/helpers/heritage-integration/cookie-helper";
import { isSavedSessionStillActive } from "@/helpers/heritage-integration/session-helper";
import analyticsMixin from "@/mixins/analytics-mixin";
import { routeData, FUNNEL_START_PAGE } from "@/router/constants/routes";
import { runExperiments } from "@/router/methods/helpers/run-experiments";

import { handleSoftError, handleHardError } from "@/router/methods/error";
import { checkPagePrerequisites } from "@/router/methods/page-prerequisites";
import { checkLogParam } from "@/helpers/debug-log-helper";
import { debugLog } from "@/helpers/debug-log-helper";
import { handleHeritageReturn } from "@/router/methods/helpers/handle-heritage-return";
import { isVirtualRoute } from "@/router/methods/helpers/is-virtual-route";
import router from "@/router";

export async function beforeEach(to, from) {
    try {
        await analyticsMixin.methods.validateSession();

        // prettier-ignore
        {
            debugLog(`--- before-each.js ${from?.name} start ---`);
            debugLog(" funnel cookie init: ", getFunnelCookie());
        }

        if (getFunnelCookie()?.SuppressConceptFunnel) {
            // Redirect to heritage.
            return {
                name: routeData.HERITAGE.name,
            };
        }

        // Ensure session has not expired
        if (getFunnelCookie() !== null && !isSavedSessionStillActive()) {
            const errorPayload = {
                cause: "expired session",
                currentPage: from?.name,
                nextPage: to?.name,
            };

            await handleSoftError(errorPayload, true);
            return false;
        }

        // Block navigation if an order has been submitted.
        if (window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) !== null) {
            const exceptionPages = [FUNNEL_START_PAGE.name, routeData.CONFIRMATION.name];

            if (!exceptionPages.some((name) => to.name === name) && !isVirtualRoute(to.name)) {
                router.push({
                    name: routeData.CONFIRMATION.name,
                });
                return false;
            }
        }

        // Special logic when returning from insurance flow.
        await handleHeritageReturn(to, from);

        // prettier-ignore
        {
            debugLog(`--- before-each.js ${from?.name} mid ---`);
            debugLog(" funnel cookie after load: ", getFunnelCookie());
        }

        // Process funnel cookie.
        updateOrCreateFunnelCookie();

        // prettier-ignore
        {
            debugLog(`--- before-each.js ${from?.name} end ---`);
            debugLog(" funnel cookie after update: ", getFunnelCookie());
        }

        // Update if logging is enabled.
        checkLogParam();

        // Ensure page-prerequisites are fulfilled
        const arePagePrerequisitesValid = await checkPagePrerequisites(to.name);

        if (!arePagePrerequisitesValid) {
            const errorPayload = {
                cause: "invalid page prerequisites for page",
                currentPage: from?.name,
                nextPage: to?.name,
            };

            await handleSoftError(errorPayload);
            return;
        }

        await runExperiments(to.name);

        // prettier-ignore
        {
            debugLog("--- before-each.js end ---");
        }
    } catch (error) {
        const errorPayload = {
            cause: "Uncaught exception in `beforeEach`.",
            currentPage: from?.name,
            nextPage: to?.name,
        };

        console.log(error);

        // Eject user from Vue app in this scenario and clear localstorage.
        await handleHardError(errorPayload);
        return;
    }
}
