<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="subheader" />
                    <alert
                        v-if="displayRecalibrationWarning"
                        ref="alertRecalNoMobile"
                        class="my-5"
                        cmsWidgetName="AlertRecalNoMobileWidget"
                        alertClass="alert-warning"
                        @text-link-clicked="openModalAction" />
                    <alert
                        v-if="displayBigTruckNoShops"
                        ref="alertBigTruckNoShops"
                        class="my-5"
                        cmsWidgetName="AlertBigTruckNoShopsWidget"
                        alertClass="alert-warning" />
                    <div class="appointment-type">
                        <div class="appointment-type-question-text d-flex">
                            <span class="w-100 recal-text" v-if="recalibrationRequired">{{ scheduleRecalText }}</span>
                            <span class="w-100" v-if="!requiresInshopRecalibration">{{ appointmentQuestionText }}</span>
                        </div>
                        <alert
                            v-if="displayServiceableInshopOnly"
                            ref="alertInshopOnly"
                            cmsWidgetName="AlertInshopOnlyWidget"
                            :manualCopy="inShopOnlyCopy"
                            :isCollapsible="true"
                            alertClass="alert-warning" />
                        <alert
                            v-if="displayServiceableMobileOnly"
                            ref="alertMobileOnly"
                            cmsWidgetName="AlertMobileOnlyWidget"
                            :manualCopy="mobileOnlyCopy"
                            :isCollapsible="true"
                            alertClass="alert-warning" />
                        <appointmentTypeQuestion
                            v-if="!requiresInshopRecalibration && isServiceableMobile"
                            ref="appointmentTypeQuestion"
                            v-model="selectedAppointmentType"
                            groupName="appointmentTypeQuestion"
                            cmsWidgetName="AppointmentTypeQuestionWidget"
                            validationRules="option-required" />
                    </div>
                    <div
                        v-if="isInshop">
                        <alert
                            v-if="displayLowAvailabilityInshop"
                            ref="alertLowAvailabilityInshop"
                            cmsWidgetName="AlertLowAvailabilityInshopWidget"
                            :isCollapsible="true"
                            alertClass="alert-warning" />
                        <shopAddress
                            ref="shopAddress"
                            v-model="selectedProvider"
                            :serviceZipcode="zipCode"
                            :selectedAppointmentType="selectedAppointmentType"
                            modalWidgetName="ChangeLocationModalWidget"
                            cmsWidgetName="ShopAddressWidget"
                            @zip-updated="handleInShopZipUpdated" />
                        <!-- INTEGRATION TODO: Put this right under the calendar -->
                        <alert
                            v-if="selectedProvider === null"
                            ref="alertNoAvailableShops"
                            cmsWidgetName="AlertNoAvailableShopsWidget"
                            :isCollapsible="true"
                            alertClass="alert-danger" />
                    </div>
                    <div
                        v-if="isMobile">
                        <div class="expandable-link-container">
                            <a
                                v-if="displayMilitaryZipAlert && !militaryBaseWarningExpanded"
                                href="#"
                                class="expandable-link"
                                @click.prevent="militaryBaseWarningExpanded = true">
                                {{ militaryBaseWarningLinkText }}
                            </a>
                            <div
                                v-if="displayMilitaryZipAlert && militaryBaseWarningExpanded"
                                class="expandable-link-text">
                                {{ militaryBaseWarningText }}
                            </div>
                        </div>
                        <serviceZipQuestion
                            ref="mobileServiceZipCodeQuestion"
                            v-model="mobileZipCode"
                            customInputId="mobileServiceZipCode"
                            class="mobile-service-zip-question"
                            :placeholderText="mobileZipPlaceholder"
                            :serviceZipFormatErrorMessage="errorMessages.MOBILE_SERVICE_ZIP_FORMAT"
                            :hasError="mobileZipError !== ''"
                            cmsWidgetName="MobileZipWidget" />
                        <div
                            v-if="mobileZipError"
                            ref="errorMessageDiv"
                            class="row my-1 form-test-error">
                            <span
                                class="d-inline-flex mt-0"
                                role="alert">{{ mobileZipError }}</span>
                        </div>
                        <textBlock
                            v-if="displayMobileFeeDisclaimer"
                            cmsWidgetName="MobileFeeDisclaimerWidget"
                            typeStyle="disclaimer" />
                    </div>
                    <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 || displayBigTruckNoShops
                        "
                        @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 errorMessages from '@/constants/error-messages';
import { useMainStore } from '@/store';
import {
    getPricedMobileFeePart,
    getServiceabilityDetails,
    getZipCodeData,
    getMobileZipCodeData
} from '@/helpers/service-location-helper';
import { toTitleCase } from '@/helpers/text-helper.js';
import { getAvailabilityRating } from '@/helpers/service-location-helper';

// Import Component
import alert from '@/ux-components/alert/alert.vue';
import textBlock from '@/digital-components/text-block/text-block.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 { Form, defineRule } from 'vee-validate';
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 shopAddress from '@/layouts/service-location/shop-address/shop-address.vue';
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
import widgetFields from '@/constants/cms-widget-fields';

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

export default {
    name: 'service-location',
    components: {
        alert,
        textBlock,
        appointmentTypeQuestion,
        contentGroupModal,
        siteFooter,
        siteHeader,
        siteSubHeader,
        // eslint-disable-next-line vue/no-reserved-component-names
        Form,
        shopAddress,
        serviceZipQuestion
    },
    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 getGlassFeesPromise = useMainStore().getGlassFees();
        const providersPromise = useMainStore().getProviders(serviceZipCode);

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

        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.glassFees,
                resultMap.providers
            );
        });
    },
    setup() {
        const mainStore = useMainStore();
        return { mainStore };
    },
    data() {
        return {
            streetAddress: this.getServiceAddressFromStore(),
            streetAddress2: this.getServiceAddress2FromStore(),
            city: this.getServiceCityFromStore(),
            state: this.getServiceStateFromStore(),
            zipCode: this.getServiceZipCodeFromStore(),
            isGlassServiceableInshop: null,
            isRecalibrationServiceableInshop: null,
            isGlassServiceableMobile: null,
            isRecalibrationServiceableMobile: null,
            selectedAppointmentType: this.getSelectedAppointmentType(),
            selectedProvider: this.getSelectedProvider(),
            mobileFeePart: null,
            mobileProviderNumber: null,
            zipContainsMilitaryBase: false,
            zipCodeCtu: null,
            mobileZipCode: '',
            mobileZipError: '',
            militaryBaseWarningExpanded: false,
            availabilityRating: null,
            RECAL_MODAL_REF_NAME,
            SITE_FOOTER_REF_NAME,
            errorMessages
        };
    },
    computed: {
        questionText() {
            return this.getCmsContent(
                'ServiceTypeQuestionWidget',
                'QuestionText'
            );
        },
        answersFromCms() {
            return this.getCmsContent('ServiceTypeQuestionWidget', 'Answers');
        },
        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;
        },
        isInshop() {
            return (
                this.selectedAppointmentType === 'Inshop'
                || this.selectedAppointmentType === 'Dropoff'
            );
        },
        isMobile() {
            return this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
        },
        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;
        },
        displayLowAvailabilityInshop() {
            return this.availabilityRating === 'low' && this.isInshop;
        },
        displayServiceableInshopOnly() {
            return !this.isServiceableMobile && this.isServiceableInshop && !this.displayRecalibrationWarning;
        },
        displayServiceableMobileOnly() {
            return this.isServiceableMobile && this.recalibrationRequired && !this.isServiceableInshop;
        },
        displayMobileFeeDisclaimer() {
            return this.mainStore.isNoComp || this.mainStore.isITAC;
        },
        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;
        },
        mobileZipPlaceholder() {
            return this.getCmsContent('MobileZipPlaceHolderWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
        },
        militaryBaseWarningLinkText() {
            return this.getCmsContent('AlertMilitaryBaseZipWidget', widgetFields.ALERT_WIDGET.HEADLINE_TEXT);
        },
        militaryBaseWarningText() {
            return this.getCmsContent('AlertMilitaryBaseZipWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
        },
        appointmentQuestionText() {
            return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT);
        },
        scheduleRecalText() {
            if(this.requiresInshopRecalibration) {
                return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2);
            } else {
                return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT);
            }
        },
        inShopOnlyCopy() {
            let content = this.getCmsContent('AlertInshopOnlyWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
            content = content.replace('{custom:city}', toTitleCase(this.city));
            return content;
        },
        mobileOnlyCopy() {
            let content = this.getCmsContent('AlertMobileOnlyWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
            content = content.replace('{custom:city}', toTitleCase(this.city));
            return content;
        },
        recalibrationRequired() {
            return this.mainStore.hasRecalibrationPart;
        }
    },
    methods: {
        arePagePrerequisitesValid() {
            return (
                useMainStore().order.serviceLocation.zipCode !== null
            );
        },
        async forwardButtonAction() {
            let provider = this.selectedProvider;
            this.mainStore.updateMobileFee(null);
            if (this.isMobile) {
                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,
                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
            );
        },
        getSelectedAppointmentType() {
            return useMainStore().order.serviceLocation.appointmentType;
        },
        getSelectedProvider() {
            return useMainStore().order.serviceLocation.provider;
        },
        setCtuForMobile(val) {
            this.zipCodeCtu = val;
        },
        async setData(
            zipCodeData,
            serviceabilityDetails,
            mobileFeePart,
            glassFees,
            providers
        ) {
            if (zipCodeData) {
                this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
                this.zipCodeCtu = zipCodeData.zipCodeCtu;
                this.city = zipCodeData.city;
            }

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

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

            if (providers) {
                this.setMobileProviderNumber(providers.mobileProviderNumber);
                let foundMatch = false;
                if(this.selectedProvider && this.selectedProvider.providerNumber) {
                    const matchedProvider = providers.shopProviders.find(
                        (provider) => provider.providerNumber === this.selectedProvider.providerNumber
                    );
                    if (matchedProvider) {
                        foundMatch = true;
                        this.selectedProvider = matchedProvider;
                    }
                }
                if(providers.shopProviders.length > 0 && !foundMatch) {
                    this.selectedProvider = providers.shopProviders[0];
                }
                else if(providers.shopProviders.length === 0) {
                    this.selectedProvider = null;
                }
            }

            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;
        },
        setServiceabilityDetails(serviceabilityDetails) {
            this.isGlassServiceableInshop =
                serviceabilityDetails.isGlassServiceableInshop;
            this.isRecalibrationServiceableInshop =
                serviceabilityDetails.isRecalibrationServiceableInshop;
            this.isGlassServiceableMobile =
                serviceabilityDetails.isGlassServiceableMobile;
            this.isRecalibrationServiceableMobile =
                serviceabilityDetails.isRecalibrationServiceableMobile;
            if (!this.isServiceableMobile) {
                this.selectedAppointmentType = AppointmentTypeStrings.IN_SHOP;
            }
        },
        async updateMobileZip() {
            this.mobileZipError = '';

            const zipCodeData = await getMobileZipCodeData(this.mobileZipCode);

            if (!zipCodeData.isValid) {
                this.mobileZipError = errorMessages.INVALID_ZIP;
            } else if (!zipCodeData.isServiceable) {
                this.mobileZipError = errorMessages.NO_SERVICE_IN_AREA(toTitleCase(zipCodeData.city));
            } else {
                this.city = zipCodeData.city;
                this.zipCode = this.mobileZipCode;
                this.setCtuForMobile(zipCodeData.zipCodeCtu);
                this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);

                const serviceabilityDetailsPromise = getServiceabilityDetails(this.mobileZipCode);
                serviceabilityDetailsPromise.then((result) => {
                    const details = result.data;
                    if (details) {
                        this.setServiceabilityDetails(details);
                    }
                });

                const providersPromise = useMainStore().getProviders(this.mobileZipCode);
                providersPromise.then((result) => {
                    const providers = result.data;
                    if (providers) {
                        this.setMobileProviderNumber(providers.mobileProviderNumber);
                        if(providers.shopProviders.length > 0) {
                            this.selectedProvider = providers.shopProviders[0];
                        }
                        else {
                            this.selectedProvider = null;
                        }
                    }
                });
            }
        },
        async handleInShopZipUpdated(newZip) {
            this.zipCode = newZip;
            const zipCodeData = await getZipCodeData(this.zipCode);
            this.city = zipCodeData.city;
            this.setCtuForMobile(zipCodeData.zipCodeCtu);
            this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);

            const serviceabilityDetailsPromise = getServiceabilityDetails(this.zipCode);
            serviceabilityDetailsPromise.then((result) => {
                const details = result.data;
                if (details) {
                    this.setServiceabilityDetails(details);
                }
            });
        }
    },
    watch: {
        mobileZipCode(newZip) {
            if(newZip !== '') {
                this.updateMobileZip();
            }
        },
        selectedAppointmentType() {
            this.mobileZipCode = '';
            if(this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP && this.selectedProvider) {
                const startDate = new Date();
                const endDate = new Date();
                endDate.setDate(startDate.getDate() + 6);
                const formattedStartDate = startDate.toISOString().split('T')[0];
                const formattedEndDate = endDate.toISOString().split('T')[0];
                getAvailabilityRating(
                    formattedStartDate,
                    formattedEndDate,
                    AppointmentTypeStrings.IN_SHOP,
                    this.selectedProvider ? this.selectedProvider.providerNumber : null
                ).then((rating) => {
                    this.availabilityRating = rating;
                });
            }
        }
    }
};
</script>

<style lang="scss" scoped>
$page-side-padding: 1.5rem;
.iss-heritage-container-width {
    .service-location-container {
        position: relative;
        min-height: 1px;
        padding-left: .9375rem;
        padding-right: .9375rem;
    }
}

.service-location-container {
    .subheader {
        margin: 1.25rem 0;
    }
    .form-test-error {
        font-weight: $font-weight-bold;
    }
    .appointment-type-question-text {
        color: $black;
        font-weight: 600;
        margin-bottom: 1rem;
        font-size: 1rem;
        line-height: 1.625rem;
        flex-direction: column;
        .recal-text {
            margin-bottom: 1.25rem;
            font-weight: $font-weight-bold;
        }
    }
    .mobile-service-zip-question {
        :deep(.form-test-error span) {
            font-weight: $font-weight-bold;
        }
    }
    .expandable-link-container {
        margin-bottom: 1rem;
    }
    .expandable-link {
        font-style: italic;
        font-weight: $font-weight-bold;
        text-decoration: none;
        color: $heritage-blue-primary;
        line-height: 1.375rem;
        &:hover {
            text-decoration: underline;
        }
    }
}
</style>
