<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="welcome-page-container iss-heritage-content-container-width">
                    <siteSubHeader
                        cmsWidgetName="SiteSubHeaderWidget"
                        class="form-group" />
                    <textboxQuestion
                        v-if="!isPolicyNumberQuestionHidden"
                        ref="policyNumber"
                        v-model="welcomePageModel.policyNumber"
                        inputId="policyNumberField"
                        cmsWidgetName="PolicyNumberQuestion"
                        isRequired
                        disableAutoFill
                        :isDisabled="isPolicyHolderDisabled"
                        :validationRules="rules.policyNumber" />
                    <textboxQuestion
                        v-if="!isPhoneNumberQuestionHidden"
                        ref="phoneNumber"
                        v-model="welcomePageModel.phoneNumber"
                        inputId="phoneNumberField"
                        cmsWidgetName="PhoneNumberQuestion"
                        :validationRules="rules.phoneNumber"
                        isRequired
                        :mask="phoneMask"
                        disableAutoFill
                        placeholderText="###-###-####"
                        class="form-group" />
                    <textboxQuestion
                        v-if="!isPhoneNumberQuestionHidden"
                        ref="extension"
                        v-model="welcomePageModel.extension"
                        inputId="extensionField"
                        cmsWidgetName="ExtensionQuestion"
                        :validationRules="rules.extension"
                        maxLength="5"
                        disableAutoFill
                        class="form-group" />
                    <textboxQuestion
                        ref="dateOfLoss"
                        v-model="welcomePageModel.dateOfLoss"
                        type="date"
                        cmsWidgetName="DateOfLossQuestion"
                        inputId="dateOfLossField"
                        isRequired
                        :isDisabled="isDateOfLossDisabled"
                        disableAutoFill
                        :max="new Date().toJSON().slice(0, 10)"
                        :min="'1972-12-01'"
                        :validationRules="rules.lossDate"
                        class="form-group" />
                    <textBlock
                        cmsWidgetName="DamageDateEstimateWidget"
                        typeStyle="small"
                        class="mt-2" />
                    <dropdownQuestion
                        id="welcomeDropdown"
                        ref="damageCause"
                        v-model="welcomePageModel.damageCause"
                        cmsWidgetName="DamageCauseQuestion"
                        inputId="damageCauseQuestionField"
                        :options="DamageCauseOptions"
                        disableAutoFill
                        :validationRules="rules.damageOption"
                        isRequired
                        placeHolderText="Select an option"
                        class="form-group" />
                    <textboxQuestion
                        ref="policyZip"
                        v-model="welcomePageModel.policyZipCode"
                        inputId="policyZipCode"
                        cmsWidgetName="PolicyZipQuestion"
                        isRequired
                        mask="#####"
                        :isDisabled="isPolicyZipDisabled"
                        :validationRules="rules.policyZip"
                        class="form-group" />
                    <dropdownQuestion
                        v-if="displayDamageStateQuestion"
                        id="welcomeDropdown"
                        ref="state"
                        v-model="welcomePageModel.damageState"
                        class="form-group"
                        cmsWidgetName="DamageStateQuestion"
                        inputId="8fdf9dc2e13e430eb57529499dceb3eb"
                        :options="getStates"
                        :validationRules="rules.lossState"
                        isRequired
                        disableAutoFill
                        placeHolderText="Select State" />
                    <textboxQuestion
                        v-if="displayDamageCityQuestion"
                        ref="damageCity"
                        v-model="welcomePageModel.damageCity"
                        class="form-group"
                        inputId="damageCityField"
                        cmsWidgetName="DamageCityQuestion"
                        isRequired
                        disableAutoFill
                        :validationRules="rules.lossCity" />
                    <buttonQuestion
                        v-if="displayGlassOnlyQuestion"
                        ref="glassOnlyDamage"
                        v-model="welcomePageModel.isDamageGlassOnly"
                        class="px-0 form-group"
                        cmsWidgetName="GlassOnlyQuestion"
                        inputId="isDamageGlassOnly"
                        :answers="DamageGlassOnlyOptions"
                        :questionText="DamageGlassOnlyQuestion"
                        groupName="glassOnlyDamageOption"
                        buttonTypeString="listButtonHorizontal"
                        :validationRules="rules.damageOption"
                        isRequired
                        isSmallQuestionLabelText
                        disableAutoFill />
                    <continueModal
                        ref="continueModal"
                        modalWidgetName="ContinueModalWidget"
                        @continuePreviousReferral="loadReferralFromCookie"
                        @startNewReferral="startNewReferral" />
                    <div
                        id="welcomeFooter"
                        class="row">
                        <alert
                            v-if="displayInvalidZipAlert"
                            ref="alertInvalidZip"
                            class="my-4"
                            cmsWidgetName="AlertInvalidZipWidget"
                            alertClass="alert-danger"
                            :isDismissible="false" />
                        <siteFooter
                            ref="siteFooter"
                            cmsWidgetName="SiteFooterWidget"
                            :isForwardActionDisabled="!meta.valid"
                            @ForwardClicked="forwardButtonAction" />
                    </div>
                </div>
            </div>
        </div>
    </Form>
</template>

<script>
// Components
import { Form, defineRule } from 'vee-validate';
import siteHeader from '@/iss-components/site-header/site-header.vue';
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
import alert from '@/ux-components/alert/alert.vue';
import continueModal from '@/iss-components/continue-modal/continue-modal.vue';
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
import textBlock from '@/digital-components/text-block/text-block.vue';

// Supporting files
import {
    fetchCmsContentForPage,
    fetchGlobalCmsContent,
    updateCmsSiteHeader
} from '@/helpers/cms-content-helper';
import settleAllPromises from '@/helpers/layout-helper';
import { required } from '@/helpers/validation-rules';
import errorMessages from '@/constants/error-messages';
import BaseFormMixin from '@/mixins/base-form-mixin.js';
import { useMainStore } from '@/store';
import states from '@/constants/states';
import globalRules from '@/constants/global-rules';
import routerParams from '@/router/router-constants/router-params';
import MaskaFormattedMasks from '@/constants/maska-masks';
import { getPropertyCaseInsensitive } from '@/helpers/object-helper';
import { saveSession } from '@/helpers/order-helper';
import { getISSCookie } from '@/helpers/cookie-helper.js';
import bailoutMessage from '@/constants/bailoutMessage';
import showIssLoadingModal from '@/helpers/loading-modal-helper';

// define validation rules
defineRule(
    'damage-option-required',
    required(errorMessages.DAMAGE_OPTION_REQUIRED)
);

export default {
    name: 'welcome-page',
    components: {
        siteHeader,
        siteSubHeader,
        alert,
        buttonQuestion,
        continueModal,
        textboxQuestion,
        dropdownQuestion,
        siteFooter,
        textBlock,
        Form
    },
    mixins: [BaseFormMixin],
    async beforeRouteEnter(to, from, next) {
        // Call APIs
        const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
        const cmsGlobalSiteHeaderContentPromise = fetchGlobalCmsContent('iss-siteheader');

        useMainStore().logWelcomePageExperiments(to.query.issPage);
        // Settle promises and get results
        const promiseResultMap = [
            {
                resultKey: 'cmsContent',
                promise: cmsContentPromise
            },
            {
                resultKey: 'globalSiteHeaderCmsContent',
                promise: cmsGlobalSiteHeaderContentPromise
            }
        ];

        // use resultMap to populate layout content.
        const resultMap = await settleAllPromises(promiseResultMap);
        next((vm) => {
            updateCmsSiteHeader(resultMap.globalSiteHeaderCmsContent);
            vm.setCmsContent(resultMap.cmsContent);
            vm.checkContinueFromCookie();
        });
    },
    setup() {
        const mainStore = useMainStore();

        // Set order account number from the issConfig.
        mainStore.order.parentAccountNumber = mainStore.issConfig.parentAccountNumber;
        mainStore.getCarrierAccountInfo().catch((error) => console.error('Error in getCarrierAccountInfo', error));

        return { mainStore };
    },
    data() {
        return {
            welcomePageModel: this.getWelcomePageModelFromStore(),
            answeredContinueModal: false,
            displayInvalidZipAlert: false,
            duplicates: [],
            rules: {
                damageOption: 'damage-option-required',
                extension: `${globalRules.EXTENSION_FORMAT}`,
                lossCity: `${globalRules.DATE_OF_LOSS_CITY_REQUIRED}|${globalRules.DATE_OF_LOSS_CITY_FORMAT}`,
                lossDate: `${globalRules.DATE_OF_LOSS_REQUIRED}|${globalRules.DATE_OF_LOSS_NOT_TEN_YEARS_PAST}|${globalRules.DATE_OF_LOSS_NOT_FUTURE}`,
                lossState: `${globalRules.DATE_OF_LOSS_STATE_REQUIRED}`,
                policyNumber: `${globalRules.POLICY_NUMBER_REQUIRED}|${globalRules.POLICY_NUMBER_FORMAT}`,
                policyZip: `${globalRules.POLICY_ZIP_REQUIRED}|${globalRules.POLICY_ZIP_FORMAT}`,
                phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`
            }
        };
    },
    mounted() {
        if (this.mainStore.applicationUser.firstHit) {
            const isInfoPrefilled = !!(this.mainStore.order.policy.policyNumber
                || this.mainStore.order.policy.dateOfLoss
                || this.mainStore.order.policy.policyZipCode);

            this.pushEventToGA("policy_info", "info_prefilled", isInfoPrefilled ? "Yes" : "No", true);

            this.$nextTick(() => {
                const formRoot = this.$el;
                const requiredFieldCount = formRoot.querySelectorAll('[aria-required="true"]').length;
                this.pushEventToGA("policy_info", "required_fields", requiredFieldCount.toString(), true);
            });

            this.mainStore.applicationUser.firstHit = false;
        }

        // TODO: Check if we're coming from SFA - site does not support SFA yet, add this back when it is enabled.
        // eslint-disable-next-line
        if (false) {
            this.pushEventToGA("co_branded", "welcome_clicked_cta", "yes_clicked", true, null, '0');
            this.pushEventToGA("visitor_info_welcome", "referring_site", "SFA", true);
        }
        else {
            this.pushEventToGA("visitor_info_welcome", "referring_site", "ClientSite", true);
        }

        this.pushEventToGA("visitor_info_welcome", "client_name", this.mainStore.accountNameForEvents, true);
    },
    computed: {
        DamageCauseOptions() {
            const damageCauseAnswers = this.getCmsContent(
                'DamageCauseQuestion',
                'Answers'
            );
            const damageCauseAnswersObj = {};
            if (damageCauseAnswers) {
                for (const answer of Object.values(damageCauseAnswers)) {
                    if (answer?.Name) {
                        damageCauseAnswersObj[answer.Name] = answer.Name;
                    }
                }
            }
            return damageCauseAnswersObj;
        },
        DamageGlassOnlyOptions() {
            return this.getCmsContent('GlassOnlyQuestion', 'Answers');
        },
        DamageGlassOnlyQuestion() {
            return this.getCmsContent('GlassOnlyQuestion', 'QuestionText');
        },
        displayDamageCityQuestion() {
            return !!this.getCmsContent('DamageCityQuestion', 'QuestionText');
        },
        displayDamageStateQuestion() {
            return !!this.getCmsContent('DamageStateQuestion', 'QuestionText');
        },
        displayGlassOnlyQuestion() {
            return !!this.getCmsContent('GlassOnlyQuestion', 'QuestionText');
        },
        getStates() {
            return Object.keys(states).reduce((acc, key) => {
                acc[key] = states[key].toUpperCase();
                return acc;
            }, {});
        },
        isPolicyHolderDisabled() {
            return !!this.mainStore.issConfig.disabledFields.policyNumber;
        },
        isPolicyZipDisabled() {
            return !!this.mainStore.issConfig.disabledFields.policyZipCode;
        },
        isDateOfLossDisabled() {
            return !!this.mainStore.issConfig.disabledFields.dateOfLoss;
        },
        phoneMask() {
            return MaskaFormattedMasks.PHONE_NUMBER;
        },
        isPolicyNumberQuestionHidden() {
            return !!this.mainStore.issConfig.hiddenFields?.policyNumber;
        },
        isPhoneNumberQuestionHidden() {
            return !!this.mainStore.issConfig.hiddenFields?.phoneNumber;
        }
    },
    methods: {
        async forwardButtonAction() {
            this.mainStore.resetVehicleState();
            this.mainStore.updatePolicyData(this.welcomePageModel);

            // We want to await this separately. It's quick and if this has an invalid zip we don't want to be waiting on the slower API calls
            await this.configureZip();
            if (this.displayInvalidZipAlert) {
                showIssLoadingModal(false);
                return;
            }

            // Clear duplicate orders if navigating away from the welcome page after visiting duplicate check page.
            if (this.mainStore.order.visitedDuplicateCheckPage) {
                this.mainStore.clearDuplicateOrders();
            }

            await this.mainStore.getBillToInfo();

            // Skip duplicate check if loaded from cookie or already visited duplicate check page.
            // NOTE: Do not create a new referral or call policy lookup if launched from cookie (this is by design).
            if (!this.mainStore.order.loadedFromCookie && !this.mainStore.order.visitedDuplicateCheckPage) {
                // getDuplicateReferrals handles exception / error internally. We do not care if it fails, user continues with creating new referral.
                await this.mainStore.getDuplicateReferrals();

                // If we do not have any duplicates.
                // Call SaveSession to create referral.
                // Then call getCoveragePolicyInfo to get the policy info.
                if (this.mainStore.applicationUser.duplicateOrders?.length === 0) {
                    try {
                        // SaveSession will bailout on error.
                        await saveSession({ shouldAwaitSaveSessionQueue: true, bailoutOnError: true });
                    }
                    catch (error) {
                        // No error handling here needed. Error is already logged.
                        // Return here to stop current navigation.
                        return;
                    }

                    // Call getCoveragePolicyInfo to get the policy info.
                    // GetCoveragePolicyInfo handles exception / error internally. We do not care if it fails, user continues in unverified path.
                    await this.mainStore.getCoveragePolicyInfo();
                    
                    this.pushEventToGA("policy_search", "policy_found", this.mainStore.isPolicyLookupSuccessful ? "Yes" : "No", true);

                    if (this.mainStore.isPolicyLookupSuccessful) {
                        this.pushEventToGA("zip_validation", "success", "N/A", true);
                    }
                    else {
                        if (this.mainStore.order.policy.policyLookupErrorCode === 2) {
                            this.pushEventToGA("zip_validation", "fail", "N/A", true);
                        }
                    }
                }
            }

            this.navigateForward();
        },
        async configureZip() {
            try {
                this.displayInvalidZipAlert = false;
                await this.mainStore.validateZip({ zip: this.welcomePageModel.policyZipCode });
            } catch (e) {
                if (e.isAxiosError) {
                    throw e;
                }
                this.displayInvalidZipAlert = true;
            }
        },
        navigateForward() {
            if ((this.mainStore.applicationUser.duplicateOrders?.length > 0 ?? false)
                && !this.mainStore.order.loadedFromCookie
                && !this.mainStore.order.visitedDuplicateCheckPage) {
                // NOTE: Only navigate to duplicate check page if the user has not already loaded an
                // existing referral from cookie (continue option from cookie popup) and they have not visited the duplicate check page already.
                // Duplicate orders found; navigating to duplicate check page and skipping save session.
                this.$router.navigate(
                    this.navigationScenarios.CLICKED_FORWARD_WITH_DUPLICATES,
                    this.$route,
                    {},
                    { [routerParams.SKIP_SAVE_SESSION]: true }
                );
            } else if (this.mainStore.isPolicyLookupSuccessful) {
                if (this.mainStore.order.policy.vehicles?.length > 0 ?? false) {
                    // navigate to policy-vehicles page
                    this.$router.navigate(
                        this.navigationScenarios
                            .CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
                        this.$route,
                        {},
                        { [routerParams.SKIP_SAVE_SESSION]: true }
                    );
                } else {
                    // navigate to vehicle-selection page (manual entry)
                    this.$router.navigate(
                        this.navigationScenarios
                            .CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
                        this.$route,
                        {},
                        { [routerParams.SKIP_SAVE_SESSION]: true }
                    );
                }
            } else {
                // if policy lookup is unsuccessful, navigate to policy-holder-details page
                this.$router.navigate(
                    this.navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
                    this.$route,
                    {},
                    { [routerParams.SKIP_SAVE_SESSION]: true }
                );
            }
        },
        getWelcomePageModelFromStore() {
            return {
                policyNumber: this.mainStore.order.policy.policyNumber,
                policyZipCode: this.mainStore.order.policy.policyZipCode,
                dateOfLoss: this.mainStore.order.policy.dateOfLoss,
                damageCause: this.mainStore.order.policy.damageCause,
                damageState: this.mainStore.order.policy.damageState,
                damageCity: this.mainStore.order.policy.damageCity,
                isDamageGlassOnly: this.mainStore.order.policy.isDamageGlassOnly,
                phoneNumber: this.mainStore.order.contactInfo.homePhone,
                extension: this.mainStore.order.contactInfo.extension,
                isPolicyNumberDisabled: this.mainStore.order.policy.isPolicyNumberDisabled
            };
        },
        updateWelcomePageModel(response) {
            const getDamageCause = this.findDamageCause(response.policy.damageCause);
            this.mainStore.order.policy.damageCause = getDamageCause;

            this.welcomePageModel.policyNumber = response.policy.policyNumber;
            this.welcomePageModel.policyZipCode = response.policy.policyZipCode;
            this.welcomePageModel.dateOfLoss = response.policy.dateOfLoss;
            this.welcomePageModel.damageCause = getDamageCause;
            this.welcomePageModel.damageState = response.policy.damageState;
            this.welcomePageModel.damageCity = response.policy.damageCity;
            this.welcomePageModel.isDamageGlassOnly = response.policy.isDamageGlassOnly;
            this.welcomePageModel.phoneNumber = response.customer.homePhone;
            this.welcomePageModel.extension = response.customer.extension;
        },
        findDamageCause(damageCause) {
            const damageCauseOptions = this.DamageCauseOptions;
            return getPropertyCaseInsensitive(damageCauseOptions, damageCause);
        },
        checkContinueFromCookie() {
            if (this.mainStore.issConfig.enableContinueFromCookie) {
                this.showCookieDrawer();
            } else {
                this.answeredContinueModal = this.mainStore.order.loadedFromCookie;
            }
        },
        showCookieDrawer() {
            this.$refs.continueModal.openModal();
        },
        async loadReferralFromCookie() {
            const issCookie = getISSCookie();
            if (issCookie) {
                this.$refs.continueModal.closeModal();
                showIssLoadingModal(true);
                const cookieReferral = {
                    referralNumber: issCookie.ReferralNumber,
                    responseDate: issCookie.ReferralDate,
                    parentAccountNumber: issCookie.ReferralParentAccountNumber,
                    correlationId: issCookie.ReferralCorrelationId
                };

                try {
                    await this.mainStore.loadSessionFromCookie(cookieReferral)
                        .then((response) => {
                            this.answeredContinueModal = true;
                            if (response && !response.provider?.isSafeliteProvider) {
                                this.$router.navigateBailout(bailoutMessage.SafeliteNotTheProvider());
                            } else {
                                this.updateWelcomePageModel(response);
                            }
                        });
                } catch (error) {
                    console.error(`Error on loading session from cookie ${error}`);
                    this.startNewReferral();
                } finally {
                    showIssLoadingModal(false);
                }
            }
        },
        startNewReferral() {
            this.mainStore.issConfig.enableContinueFromCookie = false;
            this.answeredContinueModal = true;
            this.$refs.continueModal.closeModal();
        }
    },
    watch: {
        'welcomePageModel.policyZipCode': {
            handler: async function (newZip) {
                if (newZip.length === 5) {
                    this.pushEventToGA("policy_info", "policy_zip", newZip, true);
                }
            }
        },
        'welcomePageModel.damageCause': function (newCause) {
            if (newCause) {
                this.pushEventToGA("policy_info", "cause_of_loss", newCause, true);
            }
        }
    }
};
</script>

<style lang="scss" scoped>
@import '@/styles/ux-variables-svg-strings.scss';
form {
    .container-fluid {
        display: flex;
        flex-direction: column;
        height: 100%;
    }
}

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

        .form-group {
            margin-top: 1.25rem;

            :deep(.input-wrapper) {
                input[type="date"] {
                    max-height: 3rem;
                }
            }

            &.has-error {
                :deep(.input-wrapper) {
                    input[type="date"]::-webkit-calendar-picker-indicator {
                        background-color: $svg-calendar-error-fill-color;
                        background-image: url($svg-error-calendar-graphic);
                    }
                }
            }
        }
    }
}

// Remove underline from help text links
:deep(.text-block a) {
    text-decoration: none;

    &:hover {
        text-decoration: underline;
    }
}

@-moz-document url-prefix() {
    // Temporary solution that prevents the Continue button from being hidden in Firefox
    #welcomeFooter {
        position: static !important;
    }
    // Fixes Firefox styling defect for placeholder text in dropdown fields
    #welcomeDropdown {
        .form-select {
            padding: 0.75rem 1rem;
        }
    }
}
</style>
