<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 {
    shouldFrontWipersBeAvailable,
    shouldRearWipersBeAvailable,
    shouldRainDefenseBeAvailable,
    getAvailablePackages,
    getHighestRequiredTier,
    getPackageContents,
    containsLineItemWithPartType,
    findLineItemsWithPartType,
    getPackageNameByType,
    getDiscountedPackageName,
} 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";

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,
    },
    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) {
            const VapsProductsInSelectedPackage = this.getVapsLineItemsForSelectedPackage(newValue);
            this.$emit("vapsItemsSelected", VapsProductsInSelectedPackage);
            const servicePackageDiscountPartInSelectedPackage =
                this.getServicePackageDiscountPartForSelectedPackage(newValue);
            let supportingItems = this.supportingLineItems;
            if (
                containsLineItemWithPartType(
                    partTypeStrings.SERVICE_PACKAGE_DISCOUNT,
                    supportingItems
                )
            ) {
                supportingItems = supportingItems.filter(
                    (item) => item.partType !== partTypeStrings.SERVICE_PACKAGE_DISCOUNT
                );
            }
            if (
                servicePackageDiscountPartInSelectedPackage?.length > 0 &&
                supportingItems != null
            ) {
                supportingItems.push(servicePackageDiscountPartInSelectedPackage[0]);
            }

            this.$emit("servicePackageDiscountSelected", 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.isServicePackageDiscountOnOrder &&
                              this.discountPackageNames == answer.Name
                      ),
                buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName),
                additionalButtonData: {
                    strikeThroughPrice: this.getPackagePriceString(answer.Name),
                    servicePackageDiscount:
                        this.isServicePackageDiscountOnOrder &&
                        this.discountPackageNames == answer.Name,
                    Text: this.isInsuranceSelected
                        ? false
                        : "Special: Save $" + this.getServicePackageDiscountPrice(),
                    isInsuranceSelected: this.isInsuranceSelected,
                },
            }));
            this.$emit("currentNumberOfPackages", modifiedAnswers.length);
            return modifiedAnswers;
        },
        isServicePackageDiscountOnOrder() {
            return containsLineItemWithPartType(
                partTypeStrings.SERVICE_PACKAGE_DISCOUNT,
                this.nullSafeAvailableLineItems
            );
        },
        discountPackageNames() {
            const discountServicePackage = experimentMixin.methods.getSettingValue(
                experimentSettings.PROMO_ON_PACKAGE
            );
            return getDiscountedPackageName(discountServicePackage);
        },
        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
            );
        },
        rainDefenseApplicableForTierThree() {
            return shouldRainDefenseBeAvailable(
                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;
        },
        servicePackageDiscountParts() {
            return findLineItemsWithPartType(
                partTypeStrings.SERVICE_PACKAGE_DISCOUNT,
                this.nullSafeAvailableLineItems
            );
        },
        showRecalInServicePackages() {
            return this.isRecalibrationOnOrder && !this.shouldHideRecalibration;
        },
    },
    methods: {
        processIfStatements,
        hasPricingByDay() {
            return experimentMixin.methods.hasSettingEqualTo(
                experimentSettings.PRICING_BY_DAY,
                "true"
            );
        },
        isAfterpayBreakoutDisplay() {
            return (
                (!this.shouldHideRecalibration || !this.isRecalibrationOnOrder) &&
                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,
                    servicePackageDiscount: false,
                })
            ).toFixed(2);
            return "$" + formattedPriceFloat;
        },
        getDiscountedPackagePriceString(packageName, servicePackageDiscount) {
            const formattedPriceFloat = parseFloat(
                this.getPackagePrice(packageName, {
                    discountedPrice: true,
                    servicePackageDiscount,
                })
            ).toFixed(2);

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

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

            //remove service package discount part
            if (this.isServicePackageDiscountOnOrder) {
                lineItemsToPrice = lineItemsToPrice.filter((item) => {
                    return item.partType != this.servicePackageDiscountParts[0].partType;
                });
            }

            if (discountedPrice) {
                lineItemsToPrice.push(...removeVapsPromosFromPromoArray(this.activePromos));
            }
            if (servicePackageDiscount) {
                lineItemsToPrice.push(...this.servicePackageDiscountParts);
            }
            let priceFloat = this.isInsuranceSelected
                ? 0
                : baseMixin.methods.getTierOnePackagePrice(
                      baseMixin.methods.filterOutFees(lineItemsToPrice)
                  );

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

            return priceFloat;
        },
        getServicePackageDiscountPrice() {
            if (this.isServicePackageDiscountOnOrder) {
                let price = 0;
                price += baseMixin.methods.getTotalLineItemPrice(
                    this.servicePackageDiscountParts[0]
                );
                return Math.abs(price);
            }
        },
        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;
        },
        getServicePackageDiscountPartForSelectedPackage(packageName) {
            const selectedPackage = this.servicePackageAnswers.filter(
                (item) => item.value === packageName
            );
            if (selectedPackage?.[0]?.additionalButtonData?.servicePackageDiscount) {
                return this.servicePackageDiscountParts;
            } else return [];
        },
        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 "rainDefenseApplicableForTierThree":
                    return this.rainDefenseApplicableForTierThree;
                default:
                    return null;
            }
        },
    },
    components: {
        buttonQuestion,
    },
};
</script>
