<template>
    <Form
        ref="theForm"
        v-slot="{ meta }"
        @submit="onSubmit"
        @invalidSubmit="onInvalidSubmit">
        <div class="fade-on-route-transition">
            <div class="justify-content-center">
                <siteHeader cmsWidgetName="SiteHeaderWidget" />
            </div>
            <div class="iss-heritage-container-width">
                <div class="service-location-container iss-heritage-content-container-width">
                    <siteSubHeader
                        cmsWidgetName="SiteSubHeaderWidget"
                        class="mt-4" />
                    <serviceZipModalQuestion
                        ref="serviceZipCodeQuestion"
                        v-model="serviceZipCodeQuestion"
                        modalWidgetName="ServiceZipModalWidget"
                        :onZipUpdateCallback="reloadShopData"
                        @updatedServiceability="setServiceabilityDetails"
                        @updatedContainsMilitaryBase="
                            setContainsMilitaryBase
                        " />
                    <alert
                        v-if="displayMilitaryZipAlert"
                        ref="alertMilitaryBaseZip"
                        class="my-5"
                        cmsWidgetName="AlertMilitaryBaseZipWidget"
                        alertClass="alert-warning" />
                    <alert
                        v-if="displayServiceableMobileOnly"
                        ref="alertMobileOnly"
                        class="my-5"
                        cmsWidgetName="AlertMobileOnlyWidget"
                        alertClass="alert-warning" />
                    <alert
                        v-if="displayRecalibrationWarning"
                        ref="alertRecalNoMobile"
                        class="my-5"
                        cmsWidgetName="AlertRecalNoMobileWidget"
                        alertClass="alert-warning"
                        @text-link-clicked="openModalAction" />
                    <alert
                        v-if="displayServiceableInshopOnly"
                        ref="alertInshopOnly"
                        class="my-5"
                        cmsWidgetName="AlertInshopOnlyWidget"
                        alertClass="alert-warning" />
                    <alert
                        v-if="displayNoShopsAlert"
                        ref="alertNoShops"
                        class="my-5"
                        cmsWidgetName="AlertNoShopsWidget"
                        alertClass="alert-warning" />
                    <alert
                        v-if="displayBigTruckNoShops"
                        ref="alertBigTruckNoShops"
                        class="my-5"
                        cmsWidgetName="AlertBigTruckNoShopsWidget"
                        alertClass="alert-warning" />
                    <div class="appointment-type">
                        <appointmentTypeQuestion
                            v-show="isAppointmentTypeDisplayed"
                            ref="appointmentTypeQuestion"
                            v-model="selectedAppointmentType"
                            :isServiceableMobile="isServiceableMobile"
                            :isServiceableInshop="isServiceableInshop"
                            :isDisplayed="isAppointmentTypeDisplayed"
                            groupName="appointmentTypeQuestion"
                            cmsWidgetName="AppointmentTypeQuestionWidget"
                            validationRules="option-required" />
                    </div>
                    <mobileLocationModalQuestions
                        v-if="isMobileLocationDisplayed"
                        ref="mobileLocationQuestions"
                        v-model="mobileLocationQuestions"
                        customComponentId="mobileLocationQuestions"
                        :mobileFeePart="mobileFeePart"
                        validationRules="mobile-location-required"
                        linkWidgetName="MobileLocationLinkWidget"
                        modalWidgetName="MobileLocationModalWidget"
                        :onZipUpdateCallback="reloadShopData"
                        @updated-mobile-fee-part="setMobileFeePart"
                        @updated-serviceability="setServiceabilityDetails"
                        @updated-contains-military-base="setContainsMilitaryBase"
                        @updated-mobile-ctu="setCtuForMobile" />
                    <shopQuestion
                        v-show="isShopQuestionDisplayed"
                        :ref="SHOP_QUESTION_REF_NAME"
                        v-model="selectedProvider"
                        :selectedAppointmentType="selectedAppointmentType"
                        :isDisplayed="isShopQuestionDisplayed"
                        cmsWidgetName="ShopQuestionWidget"
                        @updatedMobileProviderNumber="
                            setMobileProviderNumber
                        " />
                    <contentGroupModal
                        :ref="RECAL_MODAL_REF_NAME"
                        cssModalHeadlineClass="text-center"
                        cmsWidgetName="RecalModal" />
                    <siteFooter
                        :ref="SITE_FOOTER_REF_NAME"
                        class="mt-5"
                        cmsWidgetName="SiteFooterWidget"
                        :isForwardActionDisabled="
                            !meta.valid || displayNoShopsAlert
                        "
                        @backClicked="navigateBack(this, navigateBackScenario)"
                        @forwardClicked="forwardButtonAction" />
                </div>
            </div>
        </div>
    </Form>
</template>
<script>
// Import Supporting Files
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import settleAllPromises from '@/helpers/layout-helper';
import { required } from '@/helpers/validation-rules';
import errorMessages from '@/constants/error-messages';
import { useMainStore } from '@/store';
import {
    getPricedMobileFeePart,
    getServiceabilityDetails,
    getZipCodeData
} from '@/helpers/service-location-helper';

// Import Component
import alert from '@/ux-components/alert/alert.vue';
import appointmentTypeQuestion from '@/layouts/service-location/appointment-type-question/appointment-type-question.vue';
import baseFormMixin from '@/mixins/base-form-mixin';
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
import mobileLocationModalQuestions from '@/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue';
import { Form, defineRule } from 'vee-validate';
import shopQuestion from '@/layouts/service-location/shop-question/shop-question.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
import siteHeader from '@/iss-components/site-header/site-header.vue';
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
import serviceZipModalQuestion from '@/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue';

// DEFINE VALIDATION RULES
defineRule('mobile-location-required', (value) => {
    if (
        value.addressQuestions.streetAddress === ''
        || value.addressQuestions.city === ''
        || value.addressQuestions.state === ''
        || value.addressQuestions.zipCode === ''
        || value.isVehicleProtected == null
    ) {
        return errorMessages.MOBILE_LOCATION_REQUIRED;
    }
    return true;
});
defineRule('selection-required', required(errorMessages.OPTION_REQUIRED));

const SHOP_QUESTION_REF_NAME = 'shopQuestion';
const RECAL_MODAL_REF_NAME = 'RecalModal';
const SITE_FOOTER_REF_NAME = 'siteFooter';

export default {
    name: 'service-location',
    components: {
        alert,
        appointmentTypeQuestion,
        contentGroupModal,
        mobileLocationModalQuestions,
        siteFooter,
        siteHeader,
        siteSubHeader,
        // eslint-disable-next-line vue/no-reserved-component-names
        Form,
        serviceZipModalQuestion,
        shopQuestion
    },
    mixins: [baseFormMixin],
    async beforeRouteEnter(to, from, next) {
        // Call APIs
        const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
        const serviceZipCode = useMainStore().order.serviceLocation.zipCode || useMainStore().order.customer.address.zipCode;
        const zipCodeData = getZipCodeData(serviceZipCode);
        const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
        const serviceabilityDetailsPromise = getServiceabilityDetails(serviceZipCode);
        const shopQuestionInitialDataPromise = shopQuestion.methods.loadInitialData(serviceZipCode);
        const getGlassFeesPromise = useMainStore().getGlassFees();

        // Settle promises and get results
        const promiseResultMap = [
            {
                resultKey: 'cmsContent',
                promise: cmsContentPromise
            },
            {
                resultKey: 'mobileFeePart',
                promise: mobileFeePartPromise
            },
            {
                resultKey: 'glassFees',
                promise: getGlassFeesPromise
            },
            {
                resultKey: 'serviceabilityDetails',
                promise: serviceabilityDetailsPromise
            },
            {
                resultKey: 'shopQuestionInitialData',
                promise: shopQuestionInitialDataPromise
            },
            {
                resultKey: 'zipCodeData',
                promise: zipCodeData
            }
        ];

        const resultMap = await settleAllPromises(promiseResultMap);
        useMainStore().updateIsSafeliteProvider(true);
        next(async (vm) => {
            vm.setCmsContent(resultMap.cmsContent);
            await vm.setData(
                resultMap.zipCodeData,
                resultMap.serviceabilityDetails,
                resultMap.mobileFeePart,
                resultMap.shopQuestionInitialData?.mobileProviderNumber,
                resultMap.glassFees
            );
            vm.$refs[SHOP_QUESTION_REF_NAME].initializeComponent(resultMap.shopQuestionInitialData);
        });
    },
    setup() {
        const mainStore = useMainStore();
        return { mainStore };
    },
    data() {
        return {
            streetAddress: this.getServiceAddressFromStore(),
            streetAddress2: this.getServiceAddress2FromStore(),
            city: this.getServiceCityFromStore(),
            state: this.getServiceStateFromStore(),
            zipCode: this.getServiceZipCodeFromStore(),
            isVehicleProtected: this.getIsVehicleProtectedFromStore(),
            isGlassServiceableInshop: null,
            isRecalibrationServiceableInshop: null,
            isGlassServiceableMobile: null,
            isRecalibrationServiceableMobile: null,
            selectedAppointmentType: this.getSelectedAppointmentType(),
            selectedProvider: this.getSelectedProvider(),
            mobileFeePart: null,
            mobileProviderNumber: null,
            zipContainsMilitaryBase: false,
            zipCodeCtu: null,
            SHOP_QUESTION_REF_NAME,
            RECAL_MODAL_REF_NAME,
            SITE_FOOTER_REF_NAME
        };
    },
    computed: {
        questionText() {
            return this.getCmsContent(
                'ServiceTypeQuestionWidget',
                'QuestionText'
            );
        },
        answersFromCms() {
            return this.getCmsContent('ServiceTypeQuestionWidget', 'Answers');
        },
        serviceZipCodeQuestion: {
            get() {
                return {
                    state: this.state,
                    zipCode: this.zipCode
                };
            },
            set(newValue) {
                if (newValue.zipCode !== this.zipCode) {
                    this.resetMobileLocation();
                    this.selectedAppointmentType = null;
                    this.selectedProvider = null;
                }

                this.state = newValue.state;
                this.zipCode = newValue.zipCode;

                // eslint-disable-next-line vue/valid-next-tick
                this.$nextTick();
            }
        },
        mobileLocationQuestions: {
            get() {
                return {
                    addressQuestions: {
                        streetAddress: this.streetAddress,
                        streetAddress2: this.streetAddress2,
                        city: this.city,
                        state: this.state,
                        zipCode: this.zipCode
                    },
                    isVehicleProtected: this.isVehicleProtected
                };
            },
            set(newValue) {
                this.streetAddress = newValue.addressQuestions.streetAddress;
                this.streetAddress2 = newValue.addressQuestions.streetAddress2;
                this.city = newValue.addressQuestions.city;
                this.state = newValue.addressQuestions.state;
                this.zipCode = newValue.addressQuestions.zipCode;
                this.isVehicleProtected = newValue.isVehicleProtected;

                if (newValue.zipCode !== this.zipCode) {
                    if (
                        !(
                            this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
                            || this.selectedAppointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
                        )
                    ) {
                        this.selectedAppointmentType = null;
                    }
                    this.selectedProvider = null;
                }
            }
        },
        isServiceableMobile() {
            if (this.isRecalibrationServiceableMobile !== null) {
                return (
                    this.isGlassServiceableMobile
                    && this.isRecalibrationServiceableMobile
                );
            }
            return this.isGlassServiceableMobile;
        },
        isServiceableInshop() {
            if (this.isRecalibrationServiceableInshop !== null) {
                return (
                    this.isGlassServiceableInshop
                    && this.isRecalibrationServiceableInshop
                );
            }

            return this.isGlassServiceableInshop;
        },
        isShopQuestionDisplayed() {
            return (
                this.selectedAppointmentType === 'Inshop'
                || this.selectedAppointmentType === 'Dropoff'
            );
        },
        isAppointmentTypeDisplayed() {
            return this.zipCode && !this.displayNoShopsAlert;
        },
        isMobileLocationDisplayed() {
            return (
                this.selectedAppointmentType
                    === AppointmentTypeStrings.MOBILE
                || this.selectedAppointmentType
                    === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
            );
        },
        requiresInshopRecalibration() {
            // Specifically check for isRecalibrationServiceableMobile === false, not null or true.
            return (
                this.isServiceableInshop
                && this.isGlassServiceableMobile
                && this.isRecalibrationServiceableMobile === false
            );
        },
        displayMilitaryZipAlert() {
            return this.zipContainsMilitaryBase && this.isServiceableMobile;
        },
        displayNoShopsAlert() {
            return !this.isBigTruck && !this.isServiceableInshop && !this.isServiceableMobile;
        },
        displayBigTruckNoShops() {
            return this.isBigTruck && !this.isServiceableInshop && !this.isServiceableMobile;
        },
        displayRecalibrationWarning() {
            return this.requiresInshopRecalibration;
        },
        displayServiceableInshopOnly() {
            return (
                !this.displayRecalibrationWarning
                && this.isServiceableInshop
                && !this.isServiceableMobile
            );
        },
        displayServiceableMobileOnly() {
            return this.isServiceableMobile && !this.isServiceableInshop;
        },
        navigateBackScenario() {
            const { isNoComp, isITAC } = useMainStore();
            return isNoComp || isITAC
                ? this.navigationScenarios.CLICKED_BACK_CANNOT_REACH_TPA_FLOW
                : this.navigationScenarios.CLICKED_BACK_CAN_REACH_TPA_FLOW;
        },
        isBigTruck() {
            return this.mainStore.order.vehicle.isBigTruck;
        }
    },
    methods: {
        arePagePrerequisitesValid() {
            return (
                useMainStore().order.serviceLocation.zipCode !== null
            );
        },
        async reloadShopData(zipCode) {
            await this.$refs[SHOP_QUESTION_REF_NAME].reloadShopData(zipCode);
        },
        async forwardButtonAction() {
            let provider = this.selectedProvider;
            this.mainStore.updateMobileFee(null);
            if (this.isMobileLocationDisplayed) {
                if (this.mainStore.isNoComp || this.mainStore.isITAC) {
                    this.mainStore.updateMobileFee(this.mobileFeePart);
                }

                provider = {
                    providerNumber: this.mobileProviderNumber,
                    address: {
                        streetAddress: null,
                        city: null,
                        state: null,
                        zipCode: null,
                        zipCodeCtu: null
                    }
                };
            }

            this.mainStore.saveServiceLocation({
                address: this.streetAddress,
                address2: this.streetAddress2,
                city: this.city,
                state: this.state,
                zipCode: this.zipCode,
                zipCodeCtu: this.zipCodeCtu,
                appointmentType: this.selectedAppointmentType,
                isVehicleProtected: this.isVehicleProtected,
                provider
            });

            this.$router.navigate(
                this.navigationScenarios.CLICKED_FORWARD,
                this.$route
            );
        },
        openModalAction(modalName) {
            this.$refs[modalName].openModal();
        },
        resetDependentState() {},
        getServiceAddressFromStore() {
            return useMainStore().order.serviceLocation.address;
        },
        getServiceAddress2FromStore() {
            return useMainStore().order.serviceLocation.address2;
        },
        getServiceCityFromStore() {
            return useMainStore().order.serviceLocation.city;
        },
        getServiceStateFromStore() {
            return (
                useMainStore().order.serviceLocation.state
                || useMainStore().order.customer.address.state
            );
        },
        getServiceZipCodeFromStore() {
            return (
                useMainStore().order.serviceLocation.zipCode
                || useMainStore().order.customer.address.zipCode
            );
        },
        getIsVehicleProtectedFromStore() {
            return useMainStore().order.serviceLocation.isVehicleProtected;
        },
        getSelectedAppointmentType() {
            return useMainStore().order.serviceLocation.appointmentType;
        },
        getSelectedProvider() {
            return useMainStore().order.serviceLocation.provider;
        },
        setCtuForMobile(val) {
            this.zipCodeCtu = val;
        },
        async setData(
            zipCodeData,
            serviceabilityDetails,
            mobileFeePart,
            mobileProviderNumber,
            glassFees
        ) {
            if (zipCodeData) {
                this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
                this.zipCodeCtu = zipCodeData.zipCodeCtu;
            }

            if (serviceabilityDetails) {
                this.setServiceabilityDetails(serviceabilityDetails);
            }

            if (mobileFeePart) {
                this.mobileFeePart = mobileFeePart;
            }

            if (mobileProviderNumber) {
                this.setMobileProviderNumber(mobileProviderNumber);
            }

            if (glassFees) {
                const pricedGlassFees = await useMainStore().getCombinedQuote(glassFees);
                this.setGlassFeeItems(pricedGlassFees);
            }
        },
        setContainsMilitaryBase(val) {
            if (this.zipContainsMilitaryBase !== val) {
                this.zipContainsMilitaryBase = val;
            }
        },
        setGlassFeeItems(newGlassFeeItems) {
            this.mainStore.updateGlassFees(newGlassFeeItems);
        },
        setMobileFeePart(mobileFeePart) {
            this.mobileFeePart = mobileFeePart;
        },
        setMobileProviderNumber(providerNumber) {
            this.mobileProviderNumber = providerNumber;
        },
        resetMobileLocation() {
            this.streetAddress = '';
            this.streetAddress2 = '';
            this.city = '';

            this.isVehicleProtected = null;
        },
        setServiceabilityDetails(serviceabilityDetails) {
            this.isGlassServiceableInshop =
                serviceabilityDetails.isGlassServiceableInshop;
            this.isRecalibrationServiceableInshop =
                serviceabilityDetails.isRecalibrationServiceableInshop;
            this.isGlassServiceableMobile =
                serviceabilityDetails.isGlassServiceableMobile;
            this.isRecalibrationServiceableMobile =
                serviceabilityDetails.isRecalibrationServiceableMobile;
        }
    }
};
</script>

<style lang="scss">
$page-side-padding: 1.5rem;

.iss-heritage-container-width {
    .service-location-container {
        position: relative;
        min-height: 1px;
        padding-left: .9375rem;
        padding-right: .9375rem;
    }
}

.question-text {
    span {
        line-height: 1.5rem;
        text-align: center;
    }
}
.list-card-content p {
    &:first-of-type {
        line-height: 1.5rem;
    }
    &:not(:nth-of-type(1)) {
        line-height: 1.25rem;
    }
}
.choose-option {
    .button-question > div {
        &:first-of-type {
            margin-bottom: 0.95rem;
            line-height: 1.5rem;
        }
    }
}
.button-question {
    .row.form-test-error {
        line-height: 1.5rem;
        padding-left: 0rem !important;
    }
}
.appointment-type-question {
    .row {
        margin-top: 0;
        .col-12 {
            margin: 0 0 .5rem 0;
            &:last-child {
                margin-bottom: 0;
            }
        }
    }
    .question-text {
        margin: 0;
        span {
            padding: 1rem 0;
            text-align: center;
        }
    }
}
.service-location-button-question {
    .question-text {
        margin-top: 1.5rem;

        span {
            text-align: center;
        }
    }
}
</style>
