<template>
    <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
        <loadingModal ref="loadingModal" />
        <div class="container-fluid page-container-grouped-styles">
            <div class="row justify-content-center">
                <div class="col-md-6">
                    <funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
                </div>
            </div>
            <div class="row justify-content-center">
                <div class="col-md-6 col-xl-4">
                    <vehicleBanner
                        cmsWidgetName="VehicleBannerWidget"
                        :displayGenericVehicleImage="false" />

                    <funnelSubHeader class="mb-5" cmsWidgetName="FunnelSubHeaderWidget" />

                    <cashOrInsuranceQuestion
                        ref="cashOrInsurance"
                        cmsWidgetName="CashOrInsuranceQuestionWidget"
                        v-model="isInsuranceSelected"
                        groupName="CashOrInsuranceQuestion" />

                    <servicePackageQuestion
                        ref="servicePackage"
                        cashCmsWidgetName="CashServicePackageQuestionWidget"
                        insuranceCmsWidgetName="InsuranceServicePackageQuestionWidget"
                        groupName="ServicePackageQuestion"
                        :availableLineItems="availableLineItems"
                        :isInsuranceSelected="isInsuranceSelected"
                        @vapsItemsSelected="vapsItemsSelectedAction"
                        :activePromos="lineItems.promos"
                        v-on="{ 'buttonEvent.openModal': openModalAction }"
                        validationRules="option-required"
                        isRequired />

                    <afterpayModalBanner
                        v-if="!isInsuranceSelected"
                        cmsWidgetName="AfterpayModalWidget"
                        :lineItems="availableLineItems" />

                    <promoModalQuestion
                        class="small mt-4"
                        v-model="lineItems"
                        :addableVaps="addableVaps"
                        pageName="quote"
                        :taxPromos="false"
                        modalWidgetName="PromoModalWidget" />

                    <textBlock
                        cmsWidgetName="quoteDisclaimer"
                        justifyText="left"
                        typeStyle="caption"
                        class="mt-4" />

                    <contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
                    <contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
                    <contentGroupModal ref="RearWiperModal" cmsWidgetName="RearWiperModal" />
                    <contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />

                    <navbar
                        cmsWidgetName="FunnelFooterWidget"
                        :isForwardActionDisabled="!meta.valid"
                        :isBackButtonHidden="shouldHideBackButton"
                        @back-clicked="backButtonAction"
                        @ForwardClicked="forwardButtonAction" />
                </div>
            </div>
        </div>
    </Form>
</template>

<script>
// Components
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import navbar from "@/fmg-components/nav-bar/nav-bar";
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import cashOrInsuranceQuestion from "./cash-or-insurance-question/cash-or-insurance-question";
import servicePackageQuestion from "./service-package-question/service-package-question";
import textBlock from "@/digital-components/text-block/text-block";
import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
import afterpayModalBanner from "@/layouts/quote/afterpay-modal-banner/afterpay-modal-banner";
import baseMixin from "@/mixins/base-mixin.js";
import vehicleQuestionsMixin from "../../mixins/vehicle-questions-mixin";
import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions";
import { deepClone } from "@/helpers/object-helper";
import store from "@/store";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import { Form, defineRule } from "vee-validate";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { applicationConfig } from "@/constants/application-config";
import { payWithInsuranceStates } from "@/constants/pay-with-insurance-states";
import {
    revalidatePromosAndValidateQueryStringPromo,
    buildToastMessagesFromRevalidateOrValidatePromoResponse,
    createPromoSuccessAlert,
} from "@/helpers/promotions-helper";
import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import promoModalQuestion from "@/fmg-components/promo-modal-question/promo-modal-question";

defineRule("option-required", required(errorMessages.OPTION_REQUIRED));

export default {
    name: "quote",
    async beforeRouteEnter(to, from, next) {
        // Call APIs
        const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
        const wipersPromise = baseMixin.methods.dispatchStoreActionWithLogging(
            storeActions.GET_WIPERS,
            {
                serviceZipCode: store.getters.order.serviceLocation.zipCode,
                carId: store.getters.vehicle.carId,
            },
            "quote"
        );
        const rainDefensePromise = baseMixin.methods.dispatchStoreActionWithLogging(
            storeActions.GET_RAIN_DEFENSE,
            null,
            "quote"
        );
        const supportingItemsPromise = baseMixin.methods.dispatchStoreActionWithLogging(
            storeActions.GET_SUPPORTING_ITEMS,
            null,
            "quote"
        );

        const promiseResultMap = [
            {
                resultKey: "cmsContent",
                promise: cmsContentPromise,
            },
            {
                resultKey: "wipers",
                promise: wipersPromise,
            },
            {
                resultKey: "rainDefense",
                promise: rainDefensePromise,
            },
            {
                resultKey: "supportingItems",
                promise: supportingItemsPromise,
            },
        ];

        const resultMap = await settleAllPromises(promiseResultMap);
        const lineItems = deepClone(store.getters.order.lineItems);
        lineItems.vaps = lineItems.vaps ?? [];
        const nullSafeGlassParts = lineItems.glassParts ?? [];
        const availableLineItems = [
            resultMap.rainDefense,
            ...resultMap.supportingItems,
            ...resultMap.wipers,
            ...nullSafeGlassParts,
        ];

        const pricingResults = await baseMixin.methods.dispatchStoreActionWithLogging(
            storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
            {
                availableLineItems: availableLineItems,
            },
            "quote",
            false
        );

        baseMixin.methods.dispatchStoreAction(
            storeActions.SAVE_SUPPORTING_ITEMS,
            resultMap.supportingItems,
            false
        );
        lineItems.supportingItems = resultMap.supportingItems;
        const addableVaps = [...resultMap.wipers, resultMap.rainDefense];

        // Promo logic
        // Populate the previous state of promos for toast message usage in "next()"
        const oldActivePromos = store.getters.lineItems.promos?.slice(0);
        const oldInactivePromos = store.getters.order.payment.inactivePromos?.slice(0);

        const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
        const { validatePromoResponse, revalidatePromoResponse } =
            await revalidatePromosAndValidateQueryStringPromo(
                promoCodeFromQueryString,
                pricingResults,
                "quote"
            );
        // Sync local promos with any new promos added by validate/revalidate
        lineItems.promos = store.getters.lineItems.promos ?? [];
        // End of promo logic

        // Call the "next" function to complete the transition to this page.
        next((vm) => {
            vm.setCmsContent(resultMap.cmsContent);
            vm.addableVaps = addableVaps;
            vm.lineItems = lineItems;
            vm.availableLineItems = pricingResults;
            vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems);

            if (revalidatePromoResponse) {
                const revalidateAlerts = buildToastMessagesFromRevalidateOrValidatePromoResponse(
                    revalidatePromoResponse,
                    oldActivePromos,
                    oldInactivePromos
                );
                revalidateAlerts.forEach((alert) => {
                    vm.$refs.funnelHeader.pushGlobalAlert(alert, alert.shouldAutoFade);
                });
            }
            if (validatePromoResponse) {
                const validateAlerts =
                    buildToastMessagesFromRevalidateOrValidatePromoResponse(validatePromoResponse);
                vm.$refs.funnelHeader.pushGlobalAlert(
                    validateAlerts[0],
                    validateAlerts[0].shouldAutoFade
                );
            }
        });
    },
    data() {
        return {
            isInsuranceSelected: null,
            availableLineItems: null,
            lineItems: [],
            addableVaps: [],
        };
    },
    computed: {
        lineItemsCloneForWatcher() {
            return Object.assign({}, this.lineItems);
        },
    },
    methods: {
        openModalAction(modalName) {
            this.$refs[modalName].openModal();
        },
        arePagePrerequisitesValid() {
            return (
                store.getters.order.serviceLocation.zipCode &&
                store.getters.order.serviceLocation.zipCodeCtu &&
                (store.getters.order.damage.isRepair ||
                    (store.getters.order.lineItems?.glassParts != null &&
                        store.getters.order.lineItems.glassParts.length > 0)) &&
                store.getters.order.referralNumber?.length !== 6
            );
        },
        getDefaultIsInsuranceSelectedValue(availableLineItems) {
            const serviceLocationState = store.getters.order.serviceLocation.state;
            // Override if coming back from QuoteDetails. Remove override after Quote release
            const isInsuranceOverrideValue = this.$route.query?.isInsurance;

            const defaultIsInsuranceSelectedValue = this.$store.getters.order.payment.isInsurance;
            //Default to Insurance Tab if user Service zip is from certain States
            if (
                serviceLocationState != null &&
                payWithInsuranceStates.find((item) => item === serviceLocationState)
            )
                return true;
            else if (isInsuranceOverrideValue != null) {
                return isInsuranceOverrideValue == "true";
            } else if (defaultIsInsuranceSelectedValue != null) {
                return defaultIsInsuranceSelectedValue;
            } else {
                return availableLineItems
                    ? baseMixin.methods.getTierOnePackagePrice(
                          baseMixin.methods.filterOutFees(availableLineItems)
                      ) > 300
                    : null;
            }
        },
        vapsItemsSelectedAction(vapsItemsSelected) {
            this.lineItems.vaps = vapsItemsSelected;
        },
        backButtonAction() {
            vehicleQuestionsMixin.methods.navigateBack(this);
        },
        forwardButtonAction() {
            this.dispatchStoreAction(
                this.storeActions.SAVE_PAYMENT_TYPE,
                this.isInsuranceSelected,
                false
            );

            if (!this.isInsuranceSelected) {
                this.dispatchStoreAction(
                    this.storeActions.SAVE_PARENT_ACCOUNT_NUMBER,
                    applicationConfig.CASH_PARENT_ACCOUNT_NUMBER,
                    false
                );
                this.dispatchStoreAction(
                    this.storeActions.SAVE_BILL_TO_ACCOUNT_NUMBER,
                    applicationConfig.CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER,
                    false
                );
            }

            if (
                this.$store.getters.order.payment.parentAccountNumber !=
                applicationConfig.CASH_PARENT_ACCOUNT_NUMBER
            ) {
                this.lineItems.supportingItems = this.filterOutFees(this.lineItems.supportingItems);
            }

            if (this.lineItems.glassParts?.length > 0) {
                this.dispatchStoreAction(
                    this.storeActions.SAVE_GLASS_PARTS_SUPPRESSING_STATE_RESETTING,
                    this.lineItems.glassParts,
                    false
                );
            }

            this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.lineItems.vaps, false);
            this.dispatchStoreAction(
                storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
                {
                    activePromos: this.lineItems.promos,
                },
                false
            );

            const payment = this.$store.getters.payment;
            if (payment.isInsurance) {
                this.$router.navigateWithSaving(
                    this.navigationScenarios.CLICKED_FORWARD_WITH_INSURANCE,
                    this.$route
                );
            } else {
                this.$router.navigateWithSaving(
                    this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,
                    this.$route
                );
            }
        },
    },
    watch: {
        lineItemsCloneForWatcher: {
            handler(newValue, oldValue) {
                if (
                    !oldValue ||
                    oldValue.length == 0 ||
                    !oldValue.vaps ||
                    !newValue ||
                    newValue.length == 0
                ) {
                    return;
                }
                if (oldValue.promos.length < newValue.promos.length) {
                    const oldPromoCodes = oldValue.promos.map(
                        (promoObject) => promoObject.promoCode
                    );
                    const newlyActivatedPromoCodes = newValue.promos.filter(
                        (newPromo) => !oldPromoCodes.includes(newPromo.promoCode)
                    );
                    const alert = createPromoSuccessAlert(newlyActivatedPromoCodes[0].promoCode);
                    this.$refs.funnelHeader.pushGlobalAlert(alert, alert.shouldAutoFade);
                }
            },
            deep: true,
        },
    },
    components: {
        funnelHeader,
        navbar,
        vehicleBanner,
        funnelSubHeader,
        Form,
        textBlock,
        cashOrInsuranceQuestion,
        servicePackageQuestion,
        contentGroupModal,
        loadingModal,
        afterpayModalBanner,
        promoModalQuestion,
    },
};
</script>
<style scoped>
.text-block {
    display: block;
}
</style>
