<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 mt-4">
                    <funnelSubHeader class="pb-4" cmsWidgetName="FunnelSubHeaderWidget" />
                    <div>
                        <textboxQuestion
                            class="mb-4"
                            cmsWidgetName="ServiceZipQuestionWidget"
                            v-model="serviceZipCode"
                            inputId="serviceZipCode"
                            mask="#####"
                            isRequired
                            validationRules="zip-required|zip-format" />

                        <textboxQuestion
                            class="mb-0"
                            cmsWidgetName="EmailAddressQuestionWidget"
                            v-model="emailOrSms"
                            inputId="emailOrSms"
                            :isRequired="!IsEmailOptional"
                            disableAutoFill
                            :validationRules="EmailOrSmsValidationRules"
                            :addOptionalText="IsEmailOptional" />
                        <textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />

                        <alert
                            ref="alertInvalidZip"
                            v-if="displayInvalidZipAlert"
                            class="my-4"
                            cmsWidgetName="AlertInvalidZipWidget"
                            alertClass="alert-danger"
                            v-bind:isDismissible="false" />

                        <alert
                            class="my-4"
                            :manualHeadline="AlertNonServiceableZipHeader"
                            :manualCopy="AlertNonServiceableZipBody"
                            v-model="customAlertData"
                            v-if="displayNonServiceableZipAlert"
                            alertClass="alert-danger" />

                        <navbar
                            cmsWidgetName="FunnelFooterWidget"
                            ref="navbar"
                            :isForwardActionDisabled="!meta.valid"
                            @back-clicked="backButtonAction"
                            @ForwardClicked="forwardButtonAction" />
                    </div>
                </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 funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import buttonQuestion from "@/digital-components/button-question/button-question";
import alert from "@/ux-components/alert/alert";
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
import textBlock from "@/digital-components/text-block/text-block";
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";

//Supporting Files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { required, regex } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import { Form, defineRule } from "vee-validate";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { vinLookupMethodSelections } from "@/constants/vin-lookup-method-selections.js";
import {
    skipVinLookup,
    skipVinLookupNotRepair,
} from "@/helpers/heritage-integration/navigation-helper";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import baseMixin from "@/mixins/base-mixin.js";
import { queryStrings } from "@/constants/query-strings";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";

// Define Validation Rules
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT));
defineRule("email-sms-required", required(errorMessages.EMAIL_SMS_REQUIRED));
defineRule(
    "email-sms-format",
    regex(
        /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$|^\(?(\d{3})\)?[-. ]?(\d{3})[-. ]?(\d{4})$/,
        errorMessages.EMAIL_SMS_FORMAT
    )
);
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));

export default {
    name: "service-zip",
    mixins: [vinPagesMixin],
    data() {
        return {
            serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
            emailOrSms: this.getEmailOrSmsFromStore(),
            carId: this.getCarIdfromStore(),
            isHeavyTruck: this.getIsVehicleHeavyTruckServiceableFromStore(),
            displayInvalidZipAlert: false,
            displayNonServiceableZipAlert: false,
        };
    },

    async beforeRouteEnter(to, from, next) {
        //Call APIs
        const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);

        //Settle promises and get results
        const promiseResultMap = [
            {
                resultKey: "cmsContent",
                promise: cmsContentPromise,
            },
        ];

        const resultMap = await settleAllPromises(promiseResultMap);

        next(async (vm) => {
            vm.setCmsContent(resultMap.cmsContent);

            if (store.getters.externalParameterState?.isExternalParameter) {
                if (store.getters.externalParameterServiceZip.zipCode) {
                    await baseMixin.methods.dispatchStoreAction(
                        storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
                        {
                            zipCode: store.getters.externalParameterServiceZip.zipCode,
                            state: null,
                            zipCodeCtu: null,
                        },
                        false
                    );
                }

                if (store.getters.externalParameterCustomer?.phoneNumber) {
                    await baseMixin.methods.dispatchStoreAction(
                        storeActions.SAVE_PHONE_NUMBER,
                        store.getters.externalParameterCustomer.phoneNumber,
                        false
                    );

                    await baseMixin.methods.dispatchStoreAction(
                        storeActions.SAVE_IS_SMS_OPT_IN,
                        true,
                        false
                    );
                }

                const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
                if (isValid) {
                    vm.forwardButtonAction();
                } else {
                    baseMixin.methods.ResetExternalParamsAndHideModal();
                }
            }
        });
    },
    methods: {
        getZipFromStore() {
            return (
                store.getters.externalParameterServiceZip.zipCode ??
                store.getters.order.serviceLocation.zipCode
            );
        },
        getEmailOrSmsFromStore() {
            return store.getters.emailOrSms;
        },
        getPhoneFromStore() {
            return store.getters.order.customer.phoneNumber;
        },
        arePagePrerequisitesValid() {
            return store.getters.damage.isRepair || store.getters.damage.glassToReplace?.length > 0;
        },
        getCarIdfromStore() {
            return store.getters.vehicle.carId;
        },
        getIsVehicleHeavyTruckServiceableFromStore() {
            return store.getters.vehicle.isBigTruck && store.getters.vehicle.canSafeliteService;
        },
        async findClosestApplicableShops() {
            return await this.dispatchStoreActionWithLogging(
                storeActions.GET_CLOSEST_APPLICABLE_SHOPS,
                { zip: this.serviceZipCode, carId: this.carId },
                "service-zip"
            );
        },

        async backButtonAction() {
            const skipVin = await skipVinLookup();
            // route to move backwards
            if (skipVin) {
                this.$router.navigateWithoutSaving(
                    this.navigationScenarios.CLICKED_BACK_WITH_SKIP_VIN,
                    this.$route
                );
            } else {
                this.$router.navigateWithoutSaving(
                    this.navigationScenarios.CLICKED_BACK,
                    this.$route
                );
            }
        },
        async forwardButtonAction() {
            const zipCodeData = await this.getZipCodeData(this.serviceZipCode);

            // if no value due to field being optional, blank both phone and email address
            if (!this.emailOrSms) {
                await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, "", false);
                await this.dispatchStoreAction(storeActions.SAVE_EMAIL, "", false);
            } else {
                if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) {
                    const phone = this.emailOrSms.replace(/[()]/g, "");
                    await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false);
                } else {
                    await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false);
                }
            }

            await this.dispatchStoreAction(
                storeActions.SAVE_PAGE_DATA,
                {
                    page: fmgPageValues.EMAIL_SMS_PAGES,
                    data: { emailOrSmsValue: this.emailOrSms },
                },
                false
            );

            await this.dispatchStoreAction(
                storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
                {
                    zipCode: this.serviceZipCode,
                    state: zipCodeData.state,
                    zipCodeCtu: zipCodeData.zipCodeCtu,
                },
                false
            );
            await this.getAndSaveBillToAccountNumber();

            if (!zipCodeData.isValid) {
                this.displayInvalidZipAlert = true;
                if (store.getters.externalParameterState?.isExternalParameter) {
                    baseMixin.methods.ResetExternalParamsAndHideModal();
                }
                return this.$refs.navbar.removeLoader();
            }
            this.displayInvalidZipAlert = false;

            if (!zipCodeData.isServiceable) {
                this.displayNonServiceableZipAlert = true;
                if (store.getters.externalParameterState?.isExternalParameter) {
                    baseMixin.methods.ResetExternalParamsAndHideModal();
                }
                return this.$refs.navbar.removeLoader();
            }
            this.displayNonServiceableZipAlert = false;
            if (this.isHeavyTruck) {
                const closestShops = await this.findClosestApplicableShops(
                    this.serviceZipCode,
                    this.carId
                );
                this.displayNoServiceAlert = !closestShops?.data?.providers?.length;
                if (this.displayNoServiceAlert) {
                    return this.$refs.navbar.removeLoader();
                }
            }
            if (this.isHeavyTruck) {
                const closestShops = await this.findClosestApplicableShops(
                    this.serviceZipCode,
                    this.carId
                );
                this.displayNoServiceAlert = !closestShops?.data?.providers?.length;
                if (this.displayNoServiceAlert) {
                    return this.$refs.navbar.removeLoader();
                }
            }

            const payment = this.$store.getters.payment;
            const policy = this.$store.getters.policy;

            if (this.$store.getters.order.referralNumber?.length === 6) {
                await this.navigateForwardWithSingleCarMatch();
            } else if (this.isRepair) {
                const supportingItemsPromise = await this.dispatchStoreActionWithLogging(
                    storeActions.GET_SUPPORTING_ITEMS,
                    null,
                    "service-zip"
                );

                const promiseResultMap = [
                    {
                        resultKey: "supportingItems",
                        promise: supportingItemsPromise,
                    },
                ];

                const resultMap = await settleAllPromises(promiseResultMap);

                this.dispatchStoreAction(
                    this.storeActions.SAVE_SUPPORTING_ITEMS,
                    resultMap.supportingItems,
                    false
                );

                // call saveSession here - navigateWithSaving saves too late in the flow
                await saveSession({ pageNameToLog: "service-zip" });
                return this.$router.navigateWithSaving(
                    this.navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS,
                    this.$route
                );
            } else {
                // if we're skipping the vin-lookup but it's not a repair, we still need to get the parts
                await this.navigateForwardWithSingleCarMatch();
            }
        },
    },
    computed: {
        AlertNonServiceableZipHeader() {
            return this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll(
                "{custom:serviceZip}",
                this.serviceZipCode
            );
        },
        AlertNonServiceableZipBody() {
            return this.getCmsContent("AlertNonServiceableZipWidget", "BodyText");
        },
        isRepair() {
            return store.getters.damage.isRepair;
        },
    },
    watch: {
        serviceZipCode() {
            this.displayNonServiceableZipAlert = false;
            this.displayNoServiceAlert = false;
            this.displayNoServiceAlert = false;
        },
    },
    components: {
        funnelHeader,
        funnelSubHeader,
        navbar,
        Form,
        alert,
        textboxQuestion,
        textBlock,
        loadingModal,
    },
};
</script>

<style lang="scss">
.vinlookupquestion p {
    margin-bottom: 0;
}
.vinlookupquestion strong {
    font-weight: 500;
    color: $black;
}
.vinlookupquestion p:nth-child(2) {
    font-size: 0.875rem;
    margin-bottom: 1rem;
}
</style>
