<template>
    <buttonQuestion
        ref="buttonQuestion"
        :answers="servicePackageAnswers"
        :groupName="groupName"
        buttonTypeString="servicePackageRadio"
        :buttonTypeObject="getButtonTypeObject()"
        v-model="selectedPackageName"
        :validationRules="validationRules"
        :isRequired="isRequired"
        :logDisplayedValuesEvent="true"
        :isInsuranceSelected="isInsuranceSelected" />
</template>

<script>
import buttonQuestion from "@/digital-components/button-question/button-question";
import baseMixin from "@/mixins/base-mixin.js";
import { processIfStatements } from "@/helpers/cms-content-helper";
import servicePackageRadio from "./service-package-radio/service-package-radio";
import servicePackageRadioExperiment from "@/experiment-components/service-package-radio";
import servicePackageRadioAfterpayExperiment from "@/experiment-components/service-package-radio-for-afterpay";
import { partTypeStrings } from "@/constants/part-type-strings";
import { packageNames } from "@/constants/package-names";
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
import {
    shouldFrontWipersBeAvailable,
    shouldRearWipersBeAvailable,
    shouldRainRepelBeAvailable,
    getAvailablePackages,
    getHighestRequiredTier,
    getPackageContents,
    containsLineItemWithPartType,
    findLineItemsWithPartType,
    getPackageNameByType,
    getDiscountedPackageName,
    getPackageLabel,
} from "@/helpers/service-package-helper";
import {
    getPromosThatMatchLineItemsOnOrder,
    removeVapsPromosFromPromoArray,
    getPromosWithAddableVaps,
    getLineItemsThatMatchPromos,
} from "@/helpers/promotions-helper";
import { containsRecalParts, getItemsWithoutRecalParts } from "@/helpers/recal-helper";
import experimentMixin from "@/mixins/experiment-mixin.js";
import { experimentSettings } from "@/constants/experiments";
import { savePageData } from "@/router/methods/helpers/save-page-data";
import { debugLog } from "@/helpers/debug-log-helper";

export default {
    name: "servicePackageQuestion",
    props: {
        groupName: String,
        cashCmsWidgetName: String,
        insuranceCmsWidgetName: String,
        validationRules: String,
        isRequired: Boolean,
        isInsuranceSelected: Boolean,
        availableLineItems: null,
        activePromos: null,
        servicePackage: null,
        isRecalibrationOnOrder: Boolean,
        shouldHideRecalibration: Boolean,
        availableQuotePageDiscounts: null,
    },
    data() {
        return {
            servicePackageRadio: servicePackageRadio,
            servicePackageRadioExperiment: servicePackageRadioExperiment,
            servicePackageRadioAfterpayExperiment: servicePackageRadioAfterpayExperiment,
            selectedPackageName: null,
        };
    },
    watch: {
        availableLineItems() {
            if (
                this.$store.getters.payment.isInsurance != null ||
                getPromosWithAddableVaps(this.activePromos).length ||
                this.servicePackage != null
            ) {
                this.selectDefaultPackage();
            }
        },
        activePromos() {
            if (this.activePromos?.length) this.selectDefaultPackage();
        },
        selectedPackageName(newValue) {
            debugLog("selectedPackageName:", newValue);
            const packageLabel = getPackageLabel(newValue);

            debugLog("getPackageLabel:", packageLabel);
            this.$emit("servicePackageSelected", `ServicePackage-${packageLabel}`);

            const VapsProductsInSelectedPackage = this.getVapsLineItemsForSelectedPackage(newValue);
            this.$emit("vapsItemsSelected", VapsProductsInSelectedPackage);
            const discountPartInSelectedPackage = this.getDiscountPartForSelectedPackage(newValue);
            let supportingItems = this.supportingLineItems;

            supportingItems = supportingItems.filter(
                (item) => item.partType !== partTypeStrings.QUOTE_PAGE_DISCOUNT
            );

            if (discountPartInSelectedPackage) {
                supportingItems.push(discountPartInSelectedPackage);
            }

            this.$emit("quotePageDiscountSelected", supportingItems);
        },
        servicePackage(newValue) {
            if (newValue !== null) {
                this.selectDefaultPackage();
            }
        },
    },
    computed: {
        nullSafeAvailableLineItems() {
            return this.availableLineItems ?? [];
        },
        supportingLineItems() {
            return this.$store.getters.lineItems?.supportingItems ?? [];
        },
        servicePackageAnswers() {
            const cmsWidgetName = this.isInsuranceSelected
                ? this.insuranceCmsWidgetName
                : this.cashCmsWidgetName;
            let cmsAnswersContent = this.getCmsContent(cmsWidgetName, "Answers");
            if (!cmsAnswersContent) {
                return null;
            }

            const availablePackages = getAvailablePackages(
                this.glassToReplace,
                this.nullSafeAvailableLineItems,
                this.isRepair
            );

            cmsAnswersContent = cmsAnswersContent.filter((answer) =>
                availablePackages.some((tier) => answer.Name === tier.packageName)
            );

            const modifiedAnswers = cmsAnswersContent.map((answer) => ({
                value: answer.Name,
                buttonLabel: this.getHeaderTextFromCms(answer.SubWidgetName),
                buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.SubWidgetName),
                buttonBodyCopy: this.getBodyTextFromCms(answer.SubWidgetName),
                //The package supports service-package-discount if it has the text value in CMS
                buttonAuxillaryCopy: this.isInsuranceSelected
                    ? this.getDiscountedPackagePriceString(answer.Name, false)
                    : this.getDiscountedPackagePriceString(
                          answer.Name,
                          this.hasDiscountForPackage(answer.Name)
                      ),
                buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName),
                additionalButtonData: {
                    strikeThroughPrice: this.getPackagePriceString(answer.Name),
                    hasDiscount: this.hasDiscountForPackage(answer.Name),
                    Text: this.isInsuranceSelected
                        ? false
                        : "Special: Save $" + this.getDiscountPrice(answer.Name),
                    isInsuranceSelected: this.isInsuranceSelected,
                },
            }));

            this.$emit("currentNumberOfPackages", modifiedAnswers.length);
            return modifiedAnswers;
        },
        isDiscountOnOrder() {
            return this.availableQuotePageDiscounts?.length > 0;
        },
        frontWipersApplicableForTierTwo() {
            return shouldFrontWipersBeAvailable(
                this.glassToReplace,
                this.nullSafeAvailableLineItems,
                this.isRepair,
                packageNames.TIER_TWO
            );
        },
        rearWiperApplicableForTierTwo() {
            return shouldRearWipersBeAvailable(
                this.glassToReplace,
                this.nullSafeAvailableLineItems,
                this.isRepair,
                packageNames.TIER_TWO
            );
        },
        frontWipersApplicableForTierThree() {
            return shouldFrontWipersBeAvailable(
                this.glassToReplace,
                this.nullSafeAvailableLineItems,
                this.isRepair,
                packageNames.TIER_THREE
            );
        },
        rearWiperApplicableForTierThree() {
            return shouldRearWipersBeAvailable(
                this.glassToReplace,
                this.nullSafeAvailableLineItems,
                this.isRepair,
                packageNames.TIER_THREE
            );
        },
        rainRepelApplicableForTierThree() {
            return shouldRainRepelBeAvailable(
                this.glassToReplace,
                this.nullSafeAvailableLineItems,
                this.isRepair,
                packageNames.TIER_THREE
            );
        },
        glassToReplace() {
            return this.$store.getters.order.damage.glassToReplace;
        },
        isRepair() {
            return this.$store.getters.order.damage.isRepair;
        },
        showRecalInServicePackages() {
            return this.isRecalibrationOnOrder && !this.shouldHideRecalibration;
        },
    },
    methods: {
        processIfStatements,
        hasPricingByDay() {
            return experimentMixin.methods.hasSettingEqualTo(
                experimentSettings.PRICING_BY_DAY,
                "true"
            );
        },
        isAfterpayBreakoutDisplay() {
            return (
                !this.shouldHideRecalibration &&
                experimentMixin.methods.hasSettingEqualTo(
                    experimentSettings.DISPLAY_AFTERPAY_BREAKOUT_DISPLAY,
                    "true"
                )
            );
        },
        getButtonTypeObject() {
            if (this.isAfterpayBreakoutDisplay()) {
                return this.servicePackageRadioAfterpayExperiment;
            }
            if (this.hasPricingByDay()) {
                return this.servicePackageRadioExperiment;
            }
            return this.servicePackageRadio;
        },
        getHeaderTextFromCms(cmsWidgetName) {
            return this.getCmsContent(cmsWidgetName, "HeaderText");
        },
        getSubheaderTextFromCms(cmsWidgetName) {
            return this.getCmsContent(cmsWidgetName, "SubheaderText");
        },
        getBodyTextFromCms(cmsWidgetName) {
            const bodyText = this.getCmsContent(cmsWidgetName, "BodyText");
            return this.processIfStatements(bodyText, "custom", this.getCustomValueFromString);
        },
        getFooterTextFromCms(cmsWidgetName) {
            const footerText = this.getCmsContent(cmsWidgetName, "FooterText");
            return this.processIfStatements(footerText, "custom", this.getCustomValueFromString);
        },
        getPackagePriceString(packageName) {
            const formattedPriceFloat = parseFloat(
                this.getPackagePrice(packageName, {
                    discountedPrice: false,
                    quotePageDiscount: false,
                })
            ).toFixed(2);
            return "$" + formattedPriceFloat;
        },
        getDiscountedPackagePriceString(packageName, quotePageDiscount) {
            const formattedPriceFloat = parseFloat(
                this.getPackagePrice(packageName, {
                    discountedPrice: true,
                    quotePageDiscount,
                })
            ).toFixed(2);

            if (this.hasPricingByDay() && !this.isAfterpayBreakoutDisplay()) {
                return "$" + formattedPriceFloat;
            }
            return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat;
        },
        getPackagePrice(packageName, { discountedPrice = false, quotePageDiscount = false }) {
            let lineItemsToPrice = [...this.nullSafeAvailableLineItems];

            if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
                lineItemsToPrice = getItemsWithoutRecalParts(lineItemsToPrice);
            }

            //remove service package discount part
            if (this.isDiscountOnOrder) {
                lineItemsToPrice = lineItemsToPrice.filter((item) => {
                    return item.partType != partTypeStrings.QUOTE_PAGE_DISCOUNT;
                });
            }

            if (discountedPrice) {
                lineItemsToPrice.push(...removeVapsPromosFromPromoArray(this.activePromos));
            }
            if (quotePageDiscount) {
                const part = this.getDiscountPartForSelectedPackage(packageName);
                if (part) {
                    lineItemsToPrice.push(part);
                }
            }
            let priceFloat = this.isInsuranceSelected
                ? 0
                : baseMixin.methods.getTierOnePackagePrice(
                      baseMixin.methods.filterOutFees(lineItemsToPrice)
                  );

            priceFloat += this.getVapsPrice(packageName, discountedPrice);

            return priceFloat;
        },
        getDiscountPrice(packageName) {
            const part = this.getDiscountPartForSelectedPackage(packageName);

            if (part) {
                const price = baseMixin.methods.getTotalLineItemPrice(part);

                return Math.abs(price);
            }

            return null;
        },
        getVapsPrice(packageName, applyPromoDiscounts = false) {
            const vapsItems = this.getVapsLineItemsForSelectedPackage(packageName);
            let price = 0;

            vapsItems.forEach((item) => {
                price += baseMixin.methods.getTotalLineItemPrice(item);
            });

            if (applyPromoDiscounts && this.activePromos) {
                const relevantPromos = getPromosThatMatchLineItemsOnOrder(
                    this.activePromos,
                    vapsItems
                );
                relevantPromos.forEach((promo) => {
                    price += baseMixin.methods.getTotalLineItemPrice(promo);
                });
            }

            return price;
        },
        selectDefaultPackage() {
            if (this.servicePackage != null) {
                this.selectedPackageName = getPackageNameByType(this.servicePackage);
                return;
            }
            const promosWithAddableVaps = getPromosWithAddableVaps(this.activePromos);
            const vapsThatMatchPromos = getLineItemsThatMatchPromos(
                promosWithAddableVaps,
                this.nullSafeAvailableLineItems
            );
            const vapsFromStore = this.$store.getters.lineItems.vaps ?? [];
            const vapsToUseForDefaultPackageSelection = this.combineLineItemsWithoutDuplicates(
                vapsThatMatchPromos,
                vapsFromStore
            );

            this.selectedPackageName = getHighestRequiredTier(
                this.glassToReplace,
                this.nullSafeAvailableLineItems,
                this.isRepair,
                vapsToUseForDefaultPackageSelection
            );
        },
        getVapsLineItemsForSelectedPackage(packageName) {
            const packageContentTypes = getPackageContents(
                this.glassToReplace,
                this.nullSafeAvailableLineItems,
                this.isRepair,
                packageName
            );

            let vapsLineItemsForSelectedPackage = [];

            packageContentTypes.forEach((vapType) => {
                vapsLineItemsForSelectedPackage.push(
                    ...findLineItemsWithPartType(vapType, this.nullSafeAvailableLineItems)
                );
            });

            return vapsLineItemsForSelectedPackage;
        },
        getDiscountPartForSelectedPackage(packageName) {
            if (this.availableQuotePageDiscounts?.length > 0) {
                const match = this.availableQuotePageDiscounts.find(
                    (discountInfo) => discountInfo.packageLevel === packageName
                );
                return match?.item;
            }

            return null;
        },
        hasDiscountForPackage(packageName) {
            return !!this.getDiscountPartForSelectedPackage(packageName);
        },
        combineLineItemsWithoutDuplicates(lineItemsOne, lineItemsTwo) {
            const combinedLineItemArray = [...lineItemsTwo];
            lineItemsOne.forEach((lineItemOne) => {
                if (
                    !lineItemsTwo.filter((lineItemTwo) => lineItemTwo.id === lineItemOne.id).length
                ) {
                    combinedLineItemArray.push(lineItemOne);
                }
            });
            return combinedLineItemArray;
        },
        getCustomValueFromString(str) {
            switch (str) {
                case "showRecalInServicePackages":
                    return this.showRecalInServicePackages;
                case "frontWipersApplicableForTierTwo":
                    return this.frontWipersApplicableForTierTwo;
                case "rearWiperApplicableForTierTwo":
                    return this.rearWiperApplicableForTierTwo;
                case "frontWipersApplicableForTierThree":
                    return this.frontWipersApplicableForTierThree;
                case "rearWiperApplicableForTierThree":
                    return this.rearWiperApplicableForTierThree;
                case "rainRepelApplicableForTierThree":
                    return this.rainRepelApplicableForTierThree;
                default:
                    return null;
            }
        },
        async savePackageInfoToPageData() {
            const answers = this.servicePackageAnswers;
            const toLog = answers.map((ans) => ({
                packageName: ans.buttonLabel,
                price: ans.buttonAuxillaryCopy,
            }));

            await savePageData(this.pageName, { packages: toLog }, true);
        },
    },
    components: {
        buttonQuestion,
    },
};
</script>
