<template>
    <Form
        ref="theForm"
        v-slot="{ meta }"
        @submit="onSubmit"
        @invalidSubmit="onInvalidSubmit">
        <div class="container-fluid fade-on-route-transition">
            <div class="row justify-content-center">
                <div class="col-md-6 px-0 px-md-2">
                    <siteHeader cmsWidgetName="SiteHeaderWidget" />
                </div>
            </div>
            <div class="row justify-content-center">
                <div class="col-md-6 col-xl-4">
                    <div class="select-car-form rounded">
                        <vehicleBanner
                            class="mt-2 mb-4"
                            cmsWidgetName="VehicleBannerWidget"
                            :displayGenericVehicleImage="!carIdIsValid" />
                        <siteSubHeader
                            cmsWidgetName="SiteSubHeaderWidget"
                            subHeaderMarginClasses="mt-1" />
                        <vinLookupAlerts
                            class="mt-5"
                            :activeAlertType="activeVehicleLookupAlertType" />
                        <vinQuestion
                            v-model="vin"
                            :mask="vinMask"
                            :isDisabled="vinPopulatedOnPageLoad"
                            textPosition="left" />
                        <vinLocationInformation />
                        <siteFooter
                            ref="siteFooter"
                            cmsWidgetName="SiteFooterWidget"
                            :isForwardActionDisabled="!meta.valid"
                            class="mt-5"
                            @backClicked="navigateBack"
                            @forwardClicked="forwardButtonAction" />
                    </div>
                </div>
            </div>
        </div>
    </Form>
</template>
<script>
// Import Supporting Files
import { computed } from 'vue';
import vehicleLookupAlertTypes from '@/constants/vehicle-lookup-alert-types';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import { isGlassAvailableForCarId } from '@/helpers/damage-helper';
import settleAllPromises from '@/helpers/layout-helper';
import routerParams from '@/router/router-constants/router-params';
import { useMainStore } from '@/store';

// Import Component
import baseFormMixin from '@/mixins/base-form-mixin';
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
import { Form } 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 vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
import vinLocationInformation from '@/layouts/vin-lookup/vin-location-information/vin-location-information.vue';
import vinLookupAlerts from '@/layouts/vin-lookup/vin-lookup-alerts/vin-lookup-alerts.vue';
import vinQuestion from '@/layouts/vin-lookup/vin-question/vin-question.vue';
import bailoutMessage from '@/constants/bailoutMessage';

export default {
    name: 'vin-lookup',
    components: {
        siteFooter,
        siteHeader,
        siteSubHeader,
        // eslint-disable-next-line vue/no-reserved-component-names
        Form,
        vehicleBanner,
        vinLocationInformation,
        vinLookupAlerts,
        vinQuestion
    },
    mixins: [baseFormMixin, vehicleQuestionsMixin],
    provide() {
        return {
            vehicleFromLookup: computed(() => this.vehicleFromLookup)
        };
    },
    async beforeRouteEnter(to, from, next) {
        const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);

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

        const resultMap = await settleAllPromises(promiseResultMap);

        next((vm) => {
            vm.setCmsContent(resultMap.cmsContent);
        });
    },
    setup() {
        const mainStore = useMainStore();

        return { mainStore };
    },
    data() {
        const vin = this.getVinFromStore();
        return {
            activeVehicleLookupAlertType:
                vin?.length > 0 && !this.hasValidCarId()
                    ? vehicleLookupAlertTypes.NOT_FOUND
                    : null,
            needToLookupVehicle: true,
            vehicleFromLookup: null,
            vinWithNonMatchingCarId: vin?.length > 0 && !this.hasValidCarId(),
            vin,
            forwardButtonCarStyle: '',
            vinPopulatedOnPageLoad: vin?.length > 0 && this.hasValidCarId(),
            hasBailedOut: false
        };
    },
    computed: {
        isCarIdDifferentFromTheStore() {
            return (
                this.vehicleFromLookup !== null
                && this.hasValidCarId()
                && this.vehicleFromLookup.carId !== this.mainStore.vehicle.carId
            );
        },
        isTwoIdenticalYMMVehicleFound() {
            if (this.vehicleFromLookup === null) {
                return false;
            }
            const vinYmmFound = `${this.vehicleFromLookup.year} ${this.vehicleFromLookup.make} ${this.vehicleFromLookup.model}`;
            const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
            return vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase();
        },
        vinMask() {
            // TODO: Side effects in computed.
            if (this.vinPopulatedOnPageLoad) {
                // TODO: Modify to remove side effects in computed
                this.activeVehicleLookupAlertType =
                    vehicleLookupAlertTypes.PERFECT_MATCH;
                this.needToLookupVehicle = false;
                const lastSixChars = this.vin.substring(11, this.vin.length);
                return `!X!X!X!X!X!X!X!X!X!X!X${lastSixChars}`;
            }
            return '*****************';
        },
        carIdIsValid() {
            return this.hasValidCarId();
        }
    },
    watch: {
        vin() {
            this.resetActiveAlert();
            this.$refs.siteFooter.enableForwardAction();
            this.needToLookupVehicle = true;
            this.$refs.siteFooter.updateButtonText(this.getCmsContent('SiteFooterWidget', 'ForwardButtonText'));
        }
    },
    methods: {
        arePagePrerequisiteValid() {
            return true;
        },
        getVinFromStore() {
            return this.mainStore.vehicle.vin;
        },
        hasValidCarId() {
            return (
                this.mainStore.vehicle.carId
                && this.mainStore.vehicle.carId !== '0'
            );
        },
        // NOTE: If form is not valid, this method is not called when 'Continue' button is clicked
        async forwardButtonAction() {
            this.resetActiveAlert();
            // Temp solution to reset the 'disabled' style on the Continue button
            this.$refs.siteFooter.enableForwardAction();

            if (this.needToLookupVehicle) {
                const vehicleLookupResponse = await this.lookupVehicleByVin(this.vin);

                if (vehicleLookupResponse.error) {
                    this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_FOUND;
                    this.mainStore.setBailout(bailoutMessage.vehicleNotFound(this.vin));
                    this.resetVehicleFromLookup();
                    this.$refs.siteFooter.removeLoader();
                    // Temp solution to turn on 'disabled' style on the Continue button
                    //  because the form itself actually passes its client-side validation.
                    //  SSR-189 Scenario #4.
                    this.$refs.siteFooter.enableForwardAction();
                    return;
                }

                if (!vehicleLookupResponse.data.canSafeliteService) {
                    this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NO_SERVICE;
                    this.resetVehicleFromLookup();
                    this.$refs.siteFooter.disableForwardButton();
                    this.$refs.siteFooter.removeLoader();
                    return;
                }

                // Add vin bcs the response from the service doesn't contain vin
                this.vehicleFromLookup = Object.assign(
                    vehicleLookupResponse.data,
                    {
                        vin: this.vin
                    }
                );
            }

            if (this.needToLookupVehicle && this.isCarIdDifferentFromTheStore) {
                if (this.isTwoIdenticalYMMVehicleFound) {
                    this.activeVehicleLookupAlertType =
                        vehicleLookupAlertTypes.TWO_IDENTICAL_YMM_MATCHED;
                    this.forwardButtonCarStyle = this.vehicleFromLookup.style;
                } else {
                    this.activeVehicleLookupAlertType =
                        vehicleLookupAlertTypes.NOT_MATCHED;
                }

                const vehicleYearMakeModelStyle =
                    // eslint-disable-next-line max-len
                    `${this.vehicleFromLookup.year} ${this.vehicleFromLookup.make} ${this.vehicleFromLookup.model} ${this.forwardButtonCarStyle}`;
                this.$refs.siteFooter.updateButtonText(`Continue with ${vehicleYearMakeModelStyle}`);
                this.$refs.siteFooter.removeLoader();

                this.needToLookupVehicle = false;

                return null;
            }

            let isSelectedGlassAvailableForVehicle = true;
            if (this.isCarIdDifferentFromTheStore) {
                isSelectedGlassAvailableForVehicle =
                    await isGlassAvailableForCarId(this.vehicleFromLookup.carId);
            }

            // navigate back to vehicle-damage
            if (
                this.isCarIdDifferentFromTheStore
                && !isSelectedGlassAvailableForVehicle
            ) {
                this.mainStore.updateVehicle(this.vehicleFromLookup);
                this.mainStore.resetDamageState();
                this.$router.navigate(
                    this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
                    this.$route,
                    {},
                    { [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
                );

                // navigate() doesn't stop the processing flow
                return null;
            }

            // save vehicle to store if it hasn't already been saved
            if (!this.vinPopulatedOnPageLoad) {
                this.mainStore.updateVehicle(this.vehicleFromLookup);
            }

            if (this.vinWithNonMatchingCarId) {
                this.$router.navigate(
                    this.navigationScenarios.CORRECTED_VIN_FROM_POLICY_VEHICLE,
                    this.$route
                );
                return null;
            }

            const partsOrQuestionsResponse = await this.getPartsOrQuestions();
            if (partsOrQuestionsResponse.error) {
                this.mainStore.setBailout(bailoutMessage.PartsServiceError(partsOrQuestionsResponse.error.data));
                window.console.error('Error on retrieving PartsOrQuestions');
                this.hasBailedOut = true;
                this.$router.navigate(
                    this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
                    this.$route
                );
            }

            // Comes from vehicleQuestionsMixin.navigateForward()
            if (!this.hasBailedOut) {
                await this.navigateForward(
                    partsOrQuestionsResponse.data.partsOrQuestions,
                    this
                );
            }
        },
        async lookupVehicleByVin(vin) {
            try {
                return await this.mainStore.lookupVehicleByVin(vin);
            } catch (responseError) {
                return {
                    error: {
                        status: responseError.status
                    }
                };
            }
        },
        resetActiveAlert() {
            this.activeVehicleLookupAlertType = null;
        },
        resetVehicleFromLookup() {
            this.vehicleFromLookup = null;
        },
        resetDependentState() {}
    }
};
</script>
