<template>
    <div class="promo-modal-question">
        <textLink
            id="promoLinkPromptId"
            linkType="text"
            :text="promoLinkText"
            href="#!"
            @click-event="openModal" />
        <modal
            :ref="modalName"
            :headerText="modalHeaderText"
            :onModalClosedCallback="onModalClosed"
            :onModalOpenedCallback="focusOnPromoInput"
            @keypress.enter="onEnter"
            :footerButtonText="modalFooterText"
            @footer-button-event="addPromoCode">
            <promoQuestion
                ref="promoQuestion"
                customInputId="promoCode"
                v-model="promoCode"
                v-on="{ 'textboxQuestionEvent.inputIdAssigned': onInputIdAssigned }"
                cmsWidgetName="PromoQuestionWidget" />
            <alert
                ref="alertInvalidPromo"
                v-if="displayInvalidPromoAlert"
                v-html="errorMessage"
                class="mt-4 alert"
                cmsWidgetName="AlertInvalidPromoWidget"
                alertClass="alert-danger"
                v-bind:isDismissible="false" />
            <alert
                ref="AlertSimilarPromo"
                v-if="displaySimilarPromoAlert"
                class="mt-4 alert"
                cmsWidgetName="AlertSimilarPromoWidget"
                alertClass="alert-danger"
                v-bind:isDismissible="false" />
            <alert
                ref="alertInvalidStackingPromo"
                v-if="displayStackingPromoAlert"
                v-html="errorMessage"
                class="mt-4 alert"
                cmsWidgetName="AlertStackingPromoWidget"
                alertClass="alert-danger"
                v-bind:isDismissible="false" />
            <alert
                ref="AlertInShopPromo"
                v-if="displayInShopPromoAlert"
                v-html="errorMessage"
                class="mt-4 alert"
                cmsWidgetName="AlertInshopPromoWidget"
                alertClass="alert-danger"
                v-bind:isDismissible="false" />
            <div class="mt-4" v-for="(promoCode, i) in this.getPromoCodeList()" :key="i">
                <span class="applied-promo">Promo code "{{ promoCode }}" applied </span>
                <textLink
                    ref="removeLink"
                    linkType="text"
                    :text="removeLinkText"
                    href="#!"
                    @click-event="removeItem(promoCode)" />
            </div>
        </modal>
    </div>
</template>
<script>
import textLink from "@/ux-components/text-link/text-link";
import promoQuestion from "@/layouts/payment-method/promo-modal-question/promo-question/promo-question";
import modal from "@/digital-components/modal/modal";
import alert from "@/ux-components/alert/alert";
import { storeActions } from "@/constants/store-actions.js";
import {
    getVapsThatNeedToBeAddedToSatisfyPromos,
    promoErrorCodes,
    getPromoCodesFromPromoObjectsWithoutDuplicates,
    getPromoCodeWithoutBundleIdentifier,
} from "@/helpers/promotions-helper";
import { deepClone } from "@/helpers/object-helper";
import baseMixin from "@/mixins/base-mixin.js";
import { cartItemCategories } from "@/constants/cart-item-categories";
import store from "@/store";
import { mapTaxedLineItemsToStoreFormat } from "@/store";
export default {
    name: "promo-modal-question",

    data() {
        return {
            promoCode: "",
            promoTextInputId: "",
            errorMessage: "",
            displayInvalidPromoAlert: false,
            displaySimilarPromoAlert: false,
            displayStackingPromoAlert: false,
            displayInShopPromoAlert: false,
            lineItems: deepClone(this.modelValue),
        };
    },
    props: {
        modelValue: Object,
        modalWidgetName: String,
        availableVaps: Object,
    },
    computed: {
        promoLinkText() {
            return this.getCmsContent(this.modalWidgetName, "HeaderText");
        },
        modalHeaderText() {
            return this.getCmsContent("PromoQuestionWidget", "QuestionText");
        },
        modalFooterText() {
            return this.getCmsContent(this.modalWidgetName, "FooterText");
        },
        modalName() {
            return this.modalWidgetName;
        },
        modal() {
            return this.$refs[this.modalName];
        },
        StackPromoText() {
            return this.getCmsContent("AlertStackingPromoWidget", "HeadlineText");
        },
        PromoText() {
            return this.getCmsContent("AlertInvalidPromoWidget", "HeadlineText");
        },
        InShopPromoText() {
            return this.getCmsContent("AlertInshopPromoWidget", "HeadlineText");
        },
        removeLinkText() {
            return this.getCmsContent("RemoveCartItemTextWidget", "Text");
        },
    },
    methods: {
        resetAlerts() {
            this.displayStackingPromoAlert = false;
            this.displayInvalidPromoAlert = false;
            this.displaySimilarPromoAlert = false;
            this.displayInShopPromoAlert = false;
            this.errorMessage = "";
        },
        resetsOnPromoInput() {
            this.resetAlerts();
        },
        getPromoCodeList() {
            const promosToDisplay = getPromoCodesFromPromoObjectsWithoutDuplicates(
                this.lineItems.promos
            );
            return promosToDisplay;
        },
        getConflictingPromoCode(additionalInfo) {
            var conflictingCodes = additionalInfo?.[0];
            if (additionalInfo?.length > 1) {
                if (additionalInfo?.length > 2) conflictingCodes += ",";
                for (let i = 1; i < additionalInfo?.length - 1; i++) {
                    conflictingCodes += ` "${additionalInfo[i]},`;
                }
                conflictingCodes += `" and "${additionalInfo?.slice(-1)[0]}`;
            }
            return conflictingCodes;
        },
        onInputIdAssigned(inputId) {
            this.promoTextInputId = inputId;
        },
        openModal() {
            this.modal.openModal();
        },
        onEnter(e) {
            e.preventDefault();
            this.modal.validateAndEmit();
        },
        closeModal() {
            this.modal.closeModal();
        },
        onModalClosed() {
            this.resetAlerts();
            this.$emit("update:modelValue", this.lineItems);
            this.promoCode = "";
            this.modal.resetForm();
        },
        focusOnPromoInput() {
            const input = document.getElementById(this.promoTextInputId);
            input?.focus();
        },
        resetModalButtonStyle() {
            this.modal.resetButtonStyle();
        },
        async getPromoCodeData(promoCode, lineItems, availableVaps, pageNameToLog = null) {
            const pageName = pageNameToLog ?? this.$options?.name;
            const promoValidationResponse = await baseMixin.methods.dispatchStoreActionWithLogging(
                storeActions.VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA,
                {
                    promoCode: promoCode,
                    lineItemsToUse: lineItems,
                    addableVaps: availableVaps,
                },
                pageName,
                false
            );

            return {
                isValid: !("errorCode" in promoValidationResponse),
                promoCode: promoValidationResponse?.orderPromos,
                errorCode: promoValidationResponse?.errorCode,
                additionalInfo: promoValidationResponse?.additionalInfo,
            };
        },
        removeItem(promo) {
            this.lineItems[cartItemCategories.PROMOS] = this.lineItems[
                cartItemCategories.PROMOS
            ].filter(
                (lineItemsToKeep) =>
                    getPromoCodeWithoutBundleIdentifier(lineItemsToKeep.promoCode) != promo
            );
        },
        getErrorMessage(error, additionalInfo) {
            switch (error) {
                case promoErrorCodes.PROMO_STACKING_NOT_ALLOWED:
                case promoErrorCodes.SIMILAR_PROMO_ALREADY_ON_ORDER:
                    return additionalInfo.length === 1 &&
                        additionalInfo[0] === this.promoCode.toUpperCase()
                        ? (this.displaySimilarPromoAlert = true)
                        : ((this.errorMessage = this.StackPromoText?.replace(
                              /\{custom:(NEW|OLD)PROMOCODE\}/g,
                              (match, group) =>
                                  group === "NEW"
                                      ? this.promoCode.toUpperCase()
                                      : this.getConflictingPromoCode(additionalInfo)
                          )),
                          (this.displayStackingPromoAlert = true));
                case promoErrorCodes.INVALID_PROMO_ON_ORDER:
                    if (additionalInfo.some((x) => x.toUpperCase() === "APPOINTMENT_TYPE")) {
                        this.errorMessage = this.InShopPromoText?.replaceAll(
                            "{custom:INSHOPPROMOCODE}",
                            this.promoCode.toUpperCase()
                        );
                        return (this.displayInShopPromoAlert = true);
                    } else {
                        this.errorMessage = this.PromoText?.replaceAll(
                            "{custom:PROMOCODE}",
                            this.promoCode.toUpperCase()
                        );
                        return (this.displayInvalidPromoAlert = true);
                    }
                default:
                    this.errorMessage = this.PromoText?.replaceAll(
                        "{custom:PROMOCODE}",
                        this.promoCode.toUpperCase()
                    );
                    return (this.displayInvalidPromoAlert = true);
            }
        },
        async addPromoCode() {
            if (this.promoCode) {
                this.resetAlerts();

                const promoCodeData = await this.getPromoCodeData(
                    this.promoCode,
                    this.lineItems,
                    this.availableVaps,
                    "payment-method"
                );

                if (promoCodeData.isValid) {
                    const pricedLineItemsToTax = [];
                    pricedLineItemsToTax.push(...promoCodeData.promoCode);
                    const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
                        storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
                        {
                            billToAccountNumber: "87291",
                            providerNumber:
                                store.getters.order.serviceLocation.provider.providerNumber,
                            appointmentType: store.getters.order.serviceLocation.appointmentType,
                            serviceLocationCity: store.getters.order.serviceLocation.city,
                            serviceLocationState: store.getters.order.serviceLocation.state,
                            serviceLocationZipCode: store.getters.order.serviceLocation.zipCode,
                            pricedLineItems: pricedLineItemsToTax,
                        },
                        "payment-method",
                        false
                    );
                    // Match all line items to the line items as they are in the store
                    // and rebuild the original structure.
                    this.lineItems = mapTaxedLineItemsToStoreFormat(taxedLineItems, this.lineItems);
                    const taxedVaps = mapTaxedLineItemsToStoreFormat(
                        taxedLineItems,
                        this.availableVaps
                    );

                    const getVaps = getVapsThatNeedToBeAddedToSatisfyPromos(
                        promoCodeData.promoCode,
                        taxedVaps,
                        this.lineItems
                    );
                    this.lineItems?.promos.push(...promoCodeData.promoCode);
                    this.lineItems.vaps?.push(...getVaps);
                    this.closeModal();
                } else {
                    this.getErrorMessage(promoCodeData.errorCode, promoCodeData.additionalInfo);
                    this.focusOnPromoInput();
                    this.resetModalButtonStyle();
                }
            }
        },
    },
    watch: {
        promoCode() {
            this.displayInvalidPromoAlert = false;
            this.displayStackingPromoAlert = false;
            this.displaySimilarPromoAlert = false;
            this.displayInShopPromoAlert = false;
        },
        modelValue: {
            handler(newValue) {
                this.lineItems = deepClone(newValue);
            },
            deep: true,
        },
    },

    components: {
        textLink,
        promoQuestion,
        modal,
        alert,
    },
};
</script>
<style lang="scss" scoped>
.applied-promo {
    padding-right: 4rem;
    font-size: 14px;
    font-weight: 500;
    line-height: 24px;
    color: #0c7e47;
}
.alert {
    color: #d4281c;
    font-size: 14px;
    font-weight: 500;
    line-height: 24px;
}
</style>
