<template>
  <Form
    @submit="onSubmit"
    @invalid-submit="onInvalidSubmit"
    ref="theForm"
    v-slot="{ meta }"
  >
    <div class="page-container-grouped-styles">
      <loadingModal ref="loadingModal"/>
      <funnelHeader cmsWidgetName="FunnelHeaderWidget" />
      <vehicleBanner  
        cmsWidgetName="VehicleBannerWidget"
        :displayGenericVehicleImage="false"
      />
      <funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
      <div class="fade-on-route-transition sub-container make-tall">
        <div class="row mt-2">
          <div class="col">
            <textboxQuestion
              cmsWidgetName="VinNumber"
              v-model="vin"
              inputId="vin"
              isRequired
              disableAutoFill
              validationRules="vin-required|vin-format"
              :isDisabled="vinPopulatedOnPageLoad"
              maxLength="17"
              :mask="vinMask"
            />
          </div>
        </div>
        <div class="row mb-2">
          <div class="col">
            <vinInformation />
          </div>
        </div>
        <div class="row my-2">
          <div class="col">
            <textboxQuestion
              cmsWidgetName="ServiceZIP"
              v-model="zip"
              inputId="zip"
              mask="#####"
              isRequired
              disableAutoFill
              validationRules="zip-required|zip-format"
            />
          </div>
        </div>
        <div class="row my-2">
          <div class="col">
            <textboxQuestion
              cmsWidgetName="EmailAddress"
              v-model="email"
              inputId="email"
              isRequired
              disableAutoFill
              validationRules="email-address-required|email-address-format"
            />
          </div>
        </div>
        <alert
          class="my-4"
          :manualHeadline="PerfectMatchInsuranceVerifiedAlertHeader"
          :manualCopy="PerfectMatchInsuranceVerifiedAlertBody"
          v-model="customAlertData"
          v-if="vinPopulatedOnPageLoad && isInsuranceVerified" 
          alertClass="alert-success"
        />
        <alert
          class="my-4"
          :manualHeadline="MatchedDifferentVehicleAlertHeader"
          :manualCopy="MatchedDifferentVehicleAlertBody"
          v-model="customAlertData"
          v-if="isCarIdDifferent && !vinNotFound && !perfectMatchNewVinAlert"
          alertClass="alert-warning"
        />
        <alert
          class="my-4"
          :manualHeadline="NoServiceZipHeader"
          :manualCopy="NoServiceZipBody"
          v-model="customAlertData"
          v-if="noServiceZip"
          alertClass="alert-danger"
        />
        <alert
          class="my-4"
          v-model="customAlertData"
          v-if="vinNotFound"
          alertClass="alert-danger"
          cmsWidgetName="VinNotFound"
        />
        <alert
          class="my-4"
          :manualHeadline="PerfectMatchInsuranceNotVerifiedAlertHeader"
          :manualCopy="PerfectMatchInsuranceNotVerifiedAlertBody"
          v-model="customAlertData"
          v-if="vinPopulatedOnPageLoad && !isInsuranceVerified"
          alertClass="alert-success"
        />
        <funnelFooter
          cmsWidgetName="FunnelFooterWidget"
          ref="funnelFooter"
          :isForwardActionDisabled="!meta.valid"
          @back-clicked="backButtonAction"
          @ForwardClicked="forwardButtonAction"
        />
      </div>
    </div>
  </Form>
</template>

<script>
// Components
import funnelHeader from "@/common-components/funnel-header/funnel-header";
import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
import alert from "@/ux-components/alert/alert";
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
import vinInformation from "@/layouts/vin-lookup/vin-information/vin-information";
import loadingModal from '@/common-components/loading-modal/loading-modal.vue';

// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions";
import { errorMessages } from "@/constants/error-messages";
import { getDamageString, getIsWindshieldOnly, isGlassAvailableForCarId } from "@/helpers/damage-helper";
import { required, regex } from "@/helpers/validation-rules";
import { Form, defineRule } from "vee-validate";
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
import { routerParams } from "@/router/router-constants/router-params";

import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin";

// 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-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
defineRule("email-address-format", regex(/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+)\.([a-zA-Z]{2,})$/, errorMessages.EMAIL_ADDRESS_FORMAT));
defineRule("vin-required", required(errorMessages.VIN_REQUIRED));
defineRule("vin-format", regex(/^[a-hA-Hj-nJ-NpPr-zR-Z0-9]{17}$/, errorMessages.VIN_FORMAT));

export default {
  name: "vin-lookup",
  mixins: [vinPagesMixin],
  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);

    // Call the "next" function to complete the transition to this page.
    next((vm) => {
      vm.setCmsContent(resultMap.cmsContent);
    });
  },
  data() {
    return {
      isCarIdDifferent: false,
      noServiceZip: false,
      vinNotFound: false,
      vin: this.getVinFromStore(),
      zip: this.getZipFromStore(),
      email: this.getEmailFromStore(),
      customAlertData: {},
      previouslyEnteredCarId: '',
      invalidZip: '',
      vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0,
    };
  },
  mounted() {
    this.attachCustomEvents();
  },
  watch: {
    vin() {
      this.vinNotFound = false;
      this.$refs.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText"));
    },
    zip() {
      this.noServiceZip = false;
    },
  },
  computed: {
    MatchedDifferentVehicleAlertHeader(){
      const text = this.getCmsContent("MatchedDifferentVehicle",
      "HeadlineText").replaceAll("{custom:damage}", getDamageString());

      return text;
    },
    MatchedDifferentVehicleAlertBody(){
      const text = this.getCmsContent("MatchedDifferentVehicle",
        "BodyText").replaceAll("{custom:damage}", getDamageString()).replaceAll("{custom:vinlookupYear}", this.customAlertData?.vehicleInfo?.year).replaceAll("{custom:vinlookupMake}", this.customAlertData?.vehicleInfo?.make).replaceAll("{custom:vinlookupModel}",
        this.customAlertData?.vehicleInfo?.model);

      return text;
    },
    NoServiceZipHeader(){
      const text = this.getCmsContent("NoServiceZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", this.invalidZip);
      return text;
    },
    NoServiceZipBody(){
      return this.getCmsContent("NoServiceZipWidget", "BodyText");
    },
    PerfectMatchInsuranceNotVerifiedAlertHeader() {
      return this.getCmsContent("PerfectMatchInsuranceNotVerifiedAlert", "HeadlineText");
    },
    PerfectMatchInsuranceNotVerifiedAlertBody() {
      return this.getCmsContent("PerfectMatchInsuranceNotVerifiedAlert", "BodyText").replaceAll("{custom:damage}",
      getDamageString())
    },
    PerfectMatchInsuranceVerifiedAlertHeader () {
      return this.getCmsContent("PerfectMatchInsuranceVerifiedAlert", "HeadlineText");
    },
    PerfectMatchInsuranceVerifiedAlertBody () {
      return this.getCmsContent("PerfectMatchInsuranceVerifiedAlert", "BodyText").replaceAll("{custom:damage}",
      getIsWindshieldOnly())
    },
    isInsuranceVerified() {
      return store.getters.payment.insuranceCoverage.isVerified || getFunnelCookie().HasDelayedClaimRegistration;
    },
    vinMask() {
      if (this.vinPopulatedOnPageLoad) {
        const lastSixChars = this.vin.substring(11, this.vin.length);
        return `!X!X!X!X!X!X!X!X!X!X!X${lastSixChars}`;
      }
      else {
        return 'XXXXXXXXXXXXXXXXX';
      }    
    }, 
  },
  methods: {
    arePagePrerequisitesValid() {
      return store.getters.vehicle.carId !== null;
    },
    getEmailFromStore(){
      return this.$store.getters.order.customer.emailAddress;
    },
    getVinFromStore(){
      return this.$store.getters.vehicle.vin;
    },
    getZipFromStore(){
      return this.$store.getters.order.serviceLocation.zipCode;
    },
    attachCustomEvents() { 
      this.prependActionToMethod(this, this.forwardButtonAction, () => {
        this.pushEventToGA(
          this.$route.query[this.queryStrings.FMG_PAGE],
          this.GaActions.SUBMITTED,
          this.GaLabels.VIN_LOOKUP,
          true
        );
      });
    },
    updateIsCarIdDifferent(isVinPerfectMatch){
      if (isVinPerfectMatch) {
        this.isCarIdDifferent = false;
      }
    },
    backButtonAction() {
      if (this.$store.getters.vehicle.vin) {
        this.$router.navigate(this.navigationScenarios.CLICKED_BACK_WITH_VIN, this.$route);
      }
      else {
        this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
      }
    },
    async forwardButtonAction() {
      // If this is a new VIN Lookup, do both a Vehicle Lookup and a Zip Validation
      if (!this.vinPopulatedOnPageLoad) {
        const validateZipResponse = this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.zip});
        const vehicleLookupResponse = this.dispatchStoreAction(storeActions.LOOKUP_VEHICLE_BY_VIN, { vin: this.vin });

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

        const resultMap = await settleAllPromises(promiseResultMap);
        
        // If either lookup fails, remove the loader and stop processing the page.
        if (!resultMap.vehicleLookupResponse || !resultMap.validateZipResponse.isServiceable) {

            // If the vehicle result is undefined, the vin entered was invalid.
            if(!resultMap.vehicleLookupResponse) {
              this.vinNotFound = true;
            }

            // Check if Service Zip entered is serviceable, if not display an alert
            if (!resultMap.validateZipResponse.isServiceable) {
              this.setupUiForNonServiceableZip(this.zip);
            }

            // Remove loader and stop processing the page.
            return this.$refs.funnelFooter.removeLoader();
        }


        // Check if the CarId is different from the lookup vs what is in state currently.
        this.isCarIdDifferent = resultMap.vehicleLookupResponse.carId !== this.$store.getters.vehicle.carId;

        if (this.isCarIdDifferent && (resultMap.vehicleLookupResponse.carId !== this.previouslyEnteredCarId)) {

          this.previouslyEnteredCarId = resultMap.vehicleLookupResponse.carId;
          this.customAlertData.vehicleInfo = resultMap.vehicleLookupResponse;
          this.$refs.funnelFooter.updateButtonText(`Continue with ${resultMap.vehicleLookupResponse.year} ${resultMap.vehicleLookupResponse.make} ${resultMap.vehicleLookupResponse.model}`);
          this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(resultMap.vehicleLookupResponse.carId);

          this.noServiceZip = false;
          this.isVinValid = true;
          return this.$refs.funnelFooter.removeLoader();
        }

        // Save vin, vehicle, customer and service information
        await this.dispatchStoreAction(storeActions.SAVE_VIN_LOOKUP, {
          isCarIdDifferent: this.isCarIdDifferent,
          isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
          vehicleInfo: Object.assign(resultMap.vehicleLookupResponse, { vin: this.vin }),
          serviceLocationInfo: {
            zipCode: this.zip,
            state: resultMap.validateZipResponse.state,
          },
          customerEmail: this.email,
        }, false);

        return await this.navigateForward();
      }

      // If a VIN has already been found. Validate the Service Zip (in case of changes)
      const zipValidationResponse = await this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.zip});
      
      // Check if Service Zip entered is serviceable
      if (zipValidationResponse.data.isServiceable) {

        // If the Service Zip entered is serviceable then save the Zip Info and Email Address and navigate forward
        await this.dispatchStoreAction(storeActions.SAVE_SERVICE_LOCATION, {
          zipCode: this.zip,
          state: zipValidationResponse.data.state
        }, false);

        await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.email, false);

        return await this.navigateForward();
      }

      // If the Service Zip is NOT serviceable then show an alert
      this.setupUiForNonServiceableZip(this.zip);

      return this.$refs.funnelFooter.removeLoader();
    },
    async navigateForward(){
        if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
            this.$router.navigate(this.navigationScenarios.SELECTED_VIN_HAS_MISMATCHED_GLASS, this.$route, {}, { [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true });
        } else {
            await this.navigateForwardWithSingleCarMatch();
        }
    },
    setupUiForNonServiceableZip(zip) {
      this.customAlertData.zip = zip; 
      this.invalidZip = zip;      
      this.noServiceZip = true;     
    },
  },
  components: {
    Form,
    funnelHeader,
    vehicleBanner,
    funnelSubHeader,
    textboxQuestion,
    alert,
    funnelFooter,
    vinInformation,
    loadingModal,
  },
};
</script>
