import { queryStrings } from "@/constants/query-strings";
import { externalUrls } from "@/router/router-constants/externalUrl-values";
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { storeActions } from "@/constants/store-actions.js";
import { settleAllPromises } from "@/helpers/layout-helper";
import experimentMixin from "@/mixins/experiment-mixin";
import { experimentSettings } from "@/constants/experiments";
import { includesWindshieldReplacement } from "@/helpers/damage-helper";
import store from "@/store";
import router from "@/router";

/*
    If the user has visited the funnel before this method will determine the bets place to
    drop them so they don't start at the beginning again. This method will return 'heritage' if
    the user has an existing order and they come back in from the Safelite.com CTA.
*/
export async function getPageToRouteExistingOrderTo(toRoute = {}, existingHeritageOrder = false) {
    // If the user is coming in via the Safelite.Com CTA
    if (toRoute.query[queryStrings.START_TYPE] === "fmg") {
        // If they have an existing order, return 'heritage' for the page name.
        if (existingHeritageOrder) {
            return fmgPageValues.HERITAGE;
        }

        return await getLatestPageForRedirection();
    }

    // If navigating to a specific page, and that page is not part of the vin pages.
    // Return that page, so that it can navigate like normal.
    if (
        toRoute.query[queryStrings.FMG_PAGE] !== undefined &&
        toRoute.query[queryStrings.FMG_PAGE] !== fmgPageValues.SERVICE_LOCATION &&
        toRoute.query[queryStrings.FMG_PAGE] !== fmgPageValues.SCHEDULE &&
        !isVinRelatedPage(toRoute)
    ) {
        return overrideYmmsDirectionIfNeeded(toRoute);
    }

    // If this is not a direct link to a page using fmgPage, not from Safelite.com CTA or this is a vin related page.
    // Get the latest page for redirection.
    const latestPageRoute = await getLatestPageForRedirection();

    return latestPageRoute;
}

/*
    Used to navigate to the heritage funnel with the correct query string and url.
*/

export async function navigateToHeritageFunnel({ shouldSaveSession = true, loadingModal }) {
    // Create the order (or save existing order) when navigating to Heritage Funnel.
    if (shouldSaveSession) {
        await saveSession({ shouldAwaitSaveSessionQueue: true });
    }

    if (loadingModal && loadingModal.showModal) {
        loadingModal.showModal();
    }

    router.navigateToExternalUrl(externalUrls.HERITAGE_FUNNEL, {
        corid: store.getters.order.referralCorrelationId,
        src: "concept-funnel",
        conceptsqid: store.getters.applicationUser.savedSessionId,
        isInsurance: store.getters.payment.isInsurance,
    });
}

export async function skipVinLookup() {
    const isVinOptionalVehicle = store.getters.order.vehicle.make
        ? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
        : false;

    return (
        store.getters.damage.isRepair ||
        isVinOptionalVehicle ||
        !includesWindshieldReplacement() ||
        experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
    );
}

export async function skipVinLookupNotRepair() {
    const isVinOptionalVehicle = store.getters.order.vehicle.make
        ? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
        : false;

    return (
        !store.getters.damage.isRepair &&
        (isVinOptionalVehicle ||
            !includesWindshieldReplacement() ||
            experimentMixin.methods.hasSettingEqualTo(
                experimentSettings.SUPPRESS_VIN_CAPTURE,
                "true"
            ))
    );
}

/*
    Logic for getting the last "valid" page a user visited.
*/
async function getLatestPageForRedirection() {
    // If this is a non-CTA navigation, determine where to send the user based on page prerequisites.
    // This also works if a user has a 'fmg' start_type query string but no current order.
    // That shouldn't happen, but it's possible.
    const vehicleDamageComponent = await getLazyLoadedComponent(fmgPageValues.VEHICLE_DAMAGE);
    const estimateComponent = await getLazyLoadedComponent(fmgPageValues.ESTIMATE);
    const vinLookupComponent = await getLazyLoadedComponent(fmgPageValues.VIN_LOOKUP);
    const partQuestionsComponent = await getLazyLoadedComponent(fmgPageValues.PART_QUESTIONS);
    const vehiclePartsComponent = await getLazyLoadedComponent(fmgPageValues.VEHICLE_PARTS);
    const moldingQuestionsComponent = await getLazyLoadedComponent(fmgPageValues.MOLDING_QUESTIONS);
    const capabilityQuestionsComponent = await getLazyLoadedComponent(
        fmgPageValues.CAPABILITY_QUESTIONS
    );
    const quoteComponent = await getLazyLoadedComponent(fmgPageValues.QUOTE);
    const serviceLocationComponent = await getLazyLoadedComponent(fmgPageValues.SERVICE_LOCATION);
    const scheduleComponent = await getLazyLoadedComponent(fmgPageValues.SCHEDULE);

    const skipVin = await skipVinLookup();

    if (!vehicleDamageComponent.methods.arePagePrerequisitesValid()) {
        return fmgPageValues.VEHICLE;
    } else if (!estimateComponent.methods.arePagePrerequisitesValid()) {
        return fmgPageValues.VEHICLE_DAMAGE;
    } else {
        if (scheduleComponent.methods.arePagePrerequisitesValid()) {
            return fmgPageValues.SCHEDULE;
        } else if (serviceLocationComponent.methods.arePagePrerequisitesValid()) {
            return fmgPageValues.SERVICE_LOCATION;
        } else if (quoteComponent.methods.arePagePrerequisitesValid()) {
            return fmgPageValues.QUOTE;
        } else if (capabilityQuestionsComponent.methods.arePagePrerequisitesValid()) {
            return fmgPageValues.CAPABILITY_QUESTIONS;
        } else if (moldingQuestionsComponent.methods.arePagePrerequisitesValid()) {
            return fmgPageValues.MOLDING_QUESTIONS;
        } else if (vehiclePartsComponent.methods.arePagePrerequisitesValid()) {
            return fmgPageValues.VEHICLE_PARTS;
        } else if (partQuestionsComponent.methods.arePagePrerequisitesValid()) {
            return fmgPageValues.PART_QUESTIONS;
        } else if (
            // capture vin
            vinLookupComponent.methods.arePagePrerequisitesValid() &&
            !skipVin
        ) {
            return fmgPageValues.VIN_LOOKUP;
        } else {
            // do not capture vin
            return fmgPageValues.ESTIMATE;
        }
    }
}

/*
    Overrides functionality to go to the YMMS pages in certain cases.
    If this is not one of the cases, it returns the 'to' fmgPage value.
*/

/* istanbul ignore next */
function overrideYmmsDirectionIfNeeded(toRoute) {
    const fmgPageValue = toRoute.query[queryStrings.FMG_PAGE];

    if (store.getters.payment.insuranceCoverage.isVerified) {
        switch (fmgPageValue) {
            case fmgPageValues.VEHICLE: {
                return fmgPageValues.VEHICLE_DAMAGE;
            }
            default: {
                return fmgPageValue;
            }
        }
    } else {
        return fmgPageValue;
    }
}

/*
    Determine if the page is a vin related page.
*/

/* istanbul ignore next */
function isVinRelatedPage(toRoute) {
    const fmgPageValue = toRoute.query[queryStrings.FMG_PAGE];

    return (
        fmgPageValue === fmgPageValues.VIN_LOOKUP ||
        fmgPageValue === fmgPageValues.LICENSE_PLATE_LOOKUP ||
        fmgPageValue === fmgPageValues.ADDRESS_LOOKUP ||
        fmgPageValue === fmgPageValues.ADDRESS_VEHICLES ||
        fmgPageValue === fmgPageValues.ESTIMATE
    );
}

async function getLazyLoadedComponent(pageName) {
    return (await lazyLoadComponent(pageName)()).default;
}
