<template>
    <transition name="fade" mode="out-in">
        <div class="shop-question" aria-live="polite">
            <div class="modal-link">
                <text-link
                    linkType="text"
                    :text="shopQuestionLinkText"
                    href="#!"
                    @click-event="openModal"></text-link>
            </div>
        </div>
    </transition>
    <modal
        ref="shopQuestionModal"
        class="shop-question-popup"
        :headerText="modalHeaderText"
        :onModalOpenedCallback="updateSelectedAnswer"
        :onModalClosedCallback="resetZipCodeData"
        :footerButtonText="modalFooterText"
        :footerButtonDisabled="isModalFooterButtonDisabled"
        @footer-button-event="setZipCodeAndShop">
        <form @submit.prevent>
            <serviceZipQuestion
                ref="serviceZipQuestion"
                class="shop-question-zipcode"
                customInputId="serviceZipCode"
                v-model="localZipCode"
                cmsWidgetName="ServiceZipQuestionWidget"
                @search-icon-click="onSearchZip"
                @keydown.enter="onSearchZip"
                includeSearchIcon
                :isRequired="false"
                :validationRules="''" />
        </form>
        <div v-show="isLoading" class="loader-wrapper">
            <loader loaderColor="blue" loaderPosition="center" />
        </div>
        <div v-show="!isLoading">
            <alert
                ref="alertInvalidZip"
                v-if="displayInvalidZipAlert"
                class="mb-4"
                cmsWidgetName="AlertInvalidZipWidget"
                alertClass="alert-danger"
                v-bind:isDismissible="false" />
            <alert
                ref="alertNoShops"
                class="my-5"
                cmsWidgetName="AlertNoShopsWidget"
                v-if="displayNoShopsAlert"
                alertClass="alert-warning" />
            <alert
                ref="alertNoShops"
                class="my-5"
                cmsWidgetName="AlertNoServiceWidget"
                v-if="displayNoServiceAlert"
                alertClass="alert-danger" />
            <div v-if="displayShopsList">
                <buttonQuestion
                    ref="buttonQuestion"
                    buttonTypeString="shopListButton"
                    :buttonTypeObject="shopListButton"
                    class="radioQuestion"
                    :questionText="questionText"
                    :answers="answers"
                    groupName="chooseShop"
                    textPosition="text-start"
                    v-model="localSelectedProviderNumber"
                    isRequired
                    :validationRules="this.localSelectedProviderNumber ? '' : 'option-required'" />
                <div class="show-more-shops-link">
                    <textLink
                        v-if="displaySeeMoreLocationsLink"
                        ref="showMoreShopsLink"
                        id="showMoreShopsId2"
                        cmsWidgetName="ShowMoreShopsLinkWidget"
                        linkType="text"
                        :text="showMoreShopsLinkText"
                        href="#!"
                        @click-event="updateShopListWithNextShops()"
                        :aria-label="showMoreShopsLinkText" />
                </div>
            </div>
        </div>
    </modal>
</template>

<script>
// Components
import modal from "@/digital-components/modal/modal";
import textLink from "@/ux-components/text-link/text-link.vue";
import serviceZipQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue";
import buttonQuestion from "@/digital-components/button-question/button-question.vue";
import alert from "@/ux-components/alert/alert.vue";
import shopListButton from "./shop-list-button/shop-list-button";

// Supporting files
import { defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import baseMixin from "@/mixins/base-mixin.js";
import loader from "@/ux-components/loader/loader";

import { AppointmentTypeStrings } from "@/constants/schedule-constants";

import {
    getServiceabilityDetails,
    getClosestApplicableShops,
    getShopProviderData,
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";

defineRule("option-required", required(errorMessages.OPTION_REQUIRED));

export default {
    name: "shop-question-popup",
    mixins: [baseMixin],
    data() {
        return {
            localZipCode: this.zipCodeFromParent,
            shopListButton: shopListButton,
            numberOfShopsToDisplay: 0,
            localShopProviderData: this.shopProviderDataFromParent,
            localSelectedProviderNumber: null,
            zipCodeData: null,
            isLoading: false,
            displayNoServiceAlert: false,
        };
    },
    props: {
        shopProviderDataFromParent: Object,
        zipCodeFromParent: {
            type: String,
            default: "",
        },
        selectedProviderNumberFromParent: {
            type: String,
            default: null,
        },
    },
    computed: {
        shopQuestionLinkText() {
            return this.getCmsContent("ChangeMyLocationLinkWidget", "Text");
        },
        modalHeaderText() {
            return this.getCmsContent("ShopQuestionWidget", "QuestionText");
        },
        modalFooterText() {
            return this.getCmsContent("SaveLocationWidget", "Text");
        },
        showMoreShopsLinkText() {
            return this.getCmsContent("ShowMoreShopsLinkWidget", "Text");
        },
        displayInvalidZipAlert() {
            return this.zipCodeData && !this.zipCodeData.isValid;
        },
        displayNoShopsAlert() {
            return !this.shopProviders.length && !this.displayInvalidZipAlert;
        },
        displayShopsList() {
            return !this.displayInvalidZipAlert && !this.displayNoServiceAlert;
        },
        modal() {
            return this.$refs.shopQuestionModal;
        },
        shopProviders() {
            return this.localShopProviderData?.shopProviders ?? [];
        },
        additionalButtonData() {
            return {
                // Used for availability indicators, could be refactored out of any availability indicator
                //   logic if/when we are sure we'll never have separate drop off/ in shop logic
                shopAppointmentType: AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF,
            };
        },
        displaySeeMoreLocationsLink() {
            if (!this.shopProviders.length) return false;
            return this.numberOfShopsToDisplay < this.shopProviders.length;
        },
        isModalFooterButtonDisabled() {
            return (
                this.isLoading ||
                this.displayInvalidZipAlert ||
                this.displayNoShopsAlert ||
                this.displayNoServiceAlert ||
                !this.localSelectedProviderNumber
            );
        },
        answers() {
            const updatedProvidersToDisplay = this.shopProviders.slice(
                0,
                this.numberOfShopsToDisplay
            );
            return updatedProvidersToDisplay.map((shopProvider) => {
                const streetAddress = this.toTitleCase(shopProvider.address.streetAddress);
                const city = this.toTitleCase(shopProvider.address.city);
                const state = shopProvider.address.state;
                const zipCode = shopProvider.address.zipCode;
                const distanceInMiles = Math.round(shopProvider.distanceInMiles * 2) / 2;

                return {
                    buttonLabel: city,
                    buttonLabelSubCopy: `${distanceInMiles} mi`,
                    buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`,
                    additionalButtonData: this.additionalButtonData,
                    value: shopProvider.providerNumber,
                };
            });
        },
    },
    methods: {
        openModal() {
            // Reset local state from parent
            this.zipCodeData = null;
            this.displayNoServiceAlert = false;
            this.localShopProviderData = this.shopProviderDataFromParent;
            this.localZipCode = this.zipCodeFromParent;
            // This will be set once the modal is open (updateSelectedAnswer()) to ensure that the
            //   correct answer is selected
            this.localSelectedProviderNumber = null;

            const selectedProviderNumberFromParentIndex = this.shopProviders.findIndex(
                (provider) => provider.providerNumber == this.selectedProviderNumberFromParent
            );

            if (selectedProviderNumberFromParentIndex > -1) {
                this.numberOfShopsToDisplay =
                    Math.ceil((selectedProviderNumberFromParentIndex + 1) / 3) * 3;
            } else {
                this.numberOfShopsToDisplay = 3;
            }

            this.updateShopsForZip();
            this.$refs.shopQuestionModal.openModal();
        },
        updateSelectedAnswer() {
            this.localSelectedProviderNumber = this.selectedProviderNumberFromParent;
        },
        toTitleCase(str) {
            return str.replace(/\w\S*/g, function (txt) {
                return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
            });
        },
        updateShopListWithNextShops() {
            //gaAction = this.GaActions.SHOPS_FIRST_DISPLAYED; --This needs to actually fire on initial display, can never happen here
            this.numberOfShopsToDisplay += 3;
            this.pushShopsDisplayedGAEvent(this.answers);
        },
        pushShopsDisplayedGAEvent(nextShopListAnswers) {
            var shops = nextShopListAnswers.map((shop) => {
                if (shop.value.length > 5 && shop.value.startsWith("00")) {
                    return shop.value.substring(1);
                } else {
                    return shop.value;
                }
            });

            var joinedShops = shops.join(",");
            if (!joinedShops) {
                joinedShops = "no-shops";
            }

            this.pushEventToGA(
                this.GaCategories.SERVICE_LOCATION,
                this.GaActions.MORE_LOCATIONS_CLICKED,
                joinedShops,
                true
            );
        },
        closeModal() {
            this.modal.closeModal();
        },
        async onSearchZip(event) {
            event.preventDefault();
            this.displayNoServiceAlert = false;
            if (!this.localZipCode) {
                this.zipCodeData = {
                    isValid: false,
                };
                return;
            }
            this.isLoading = true;

            this.zipCodeData = await this.getZipCodeData(this.localZipCode, this.pageName);
            // Add zipCode to zipCodeData as it does not come back from endpoint
            this.zipCodeData.zipCode = this.localZipCode;
            if (this.zipCodeData.isValid) {
                if (this.$store.getters.order.vehicle?.isBigTruck) {
                    // check the location endpoint to verify this zip can service a heavy truck
                    const closestShops = await getClosestApplicableShops(
                        this.localZipCode,
                        this.$store.getters.order.vehicle.carId,
                        this.pageName
                    );
                    if (!closestShops || closestShops.inShopProviders?.length === 0) {
                        this.isLoading = false;
                        this.displayNoServiceAlert = true;
                        return null;
                    }
                }

                getShopProviderData(this.localZipCode).then(async (result) => {
                    this.localShopProviderData = result.data;
                    this.numberOfShopsToDisplay = 3;
                    this.updateShopsForZip();
                    this.isLoading = false;
                });
            } else {
                this.isLoading = false;
            }
        },
        updateShopsForZip() {
            if (!this.shopProviders.length) {
                return;
            }
            if (
                !this.answers.some(
                    (a) => String(a.value) === String(this.localSelectedProviderNumber)
                )
            ) {
                this.localSelectedProviderNumber = null;
            }
            // I think we should call our new pushGA Event here with new mapped data
        },
        async setZipCodeAndShop() {
            const shopQuestionPopUpData = {
                zipCodeData: this.zipCodeData,
                shopProviderData: this.localShopProviderData,
                selectedProviderNumber: this.localSelectedProviderNumber,
            };
            this.$emit("shop-selected", shopQuestionPopUpData);

            if (this.zipCodeData) {
                // retrieve serviceability details
                const serviceabilityDetails = await getServiceabilityDetails(
                    this.zipCodeData.zipCode,
                    null,
                    this.pageName
                );

                this.$emit("updated-serviceability", serviceabilityDetails.data);
            }

            this.closeModal();
        },
    },
    components: {
        modal,
        textLink,
        serviceZipQuestion,
        buttonQuestion,
        alert,
        loader,
    },
};
</script>

<style lang="scss">
.shop-question {
    margin-top: 1rem;
    text-align: center;

    a {
        @include responsive-font-size-md(0.875rem, 1rem);
    }

    .button-question {
        .question-text {
            margin-top: 0.5rem;
        }
    }
}

.drop-off-alert {
    background: url("data:image/svg+xml,%3Csvg viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23clip0_13957_112512)'%3E%3Cpath d='M5.99865 0C4.81147 4.82643e-07 3.65095 0.352111 2.66392 1.01179C1.67688 1.67146 0.907678 2.60907 0.45361 3.70599C-0.000459241 4.80291 -0.11899 6.00986 0.113013 7.17415C0.345015 8.33845 0.917126 9.40778 1.75697 10.2469C2.59682 11.086 3.66666 11.6571 4.83117 11.8881C5.99567 12.119 7.20251 11.9994 8.29902 11.5443C9.39553 11.0893 10.3324 10.3192 10.9912 9.33159C11.65 8.34396 12.0011 7.18313 12 5.99594C11.9971 4.40566 11.3638 2.88142 10.2388 1.75742C9.11375 0.633431 7.58894 0.00143011 5.99865 0V0ZM5.99865 11.2478C4.96135 11.2473 3.94748 10.9392 3.08518 10.3627C2.22288 9.7861 1.55085 8.96685 1.15401 8.00846C0.75718 7.05006 0.653353 5.99554 0.855656 4.97815C1.05796 3.96077 1.55731 3.02618 2.29061 2.29251C3.0239 1.55884 3.95823 1.059 4.97551 0.856176C5.99279 0.653349 7.04737 0.756633 8.00597 1.15297C8.96457 1.54931 9.78416 2.22092 10.3612 3.08293C10.9382 3.94493 11.2467 4.95864 11.2478 5.99594C11.2478 7.38835 10.6949 8.72377 9.71053 9.70861C8.7262 10.6934 7.39106 11.2471 5.99865 11.2478V11.2478Z' fill='%2306577C'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M6.22736 8.84695C6.30613 8.76818 6.35038 8.66135 6.35038 8.54996V5.30996C6.35038 5.19857 6.30613 5.09174 6.22736 5.01298C6.1486 4.93421 6.04177 4.88996 5.93038 4.88996C5.81899 4.88996 5.71216 4.93421 5.63339 5.01298C5.55463 5.09174 5.51038 5.19857 5.51038 5.30996V8.54996C5.51038 8.66135 5.55463 8.76818 5.63339 8.84695C5.71216 8.92571 5.81899 8.96996 5.93038 8.96996C6.04177 8.96996 6.1486 8.92571 6.22736 8.84695ZM5.69704 3.97918C5.76611 4.02533 5.84731 4.04996 5.93038 4.04996C5.98558 4.05012 6.04026 4.03936 6.09129 4.01831C6.14232 3.99726 6.18868 3.96633 6.22771 3.9273C6.26675 3.88827 6.29768 3.8419 6.31873 3.79088C6.33978 3.73985 6.35053 3.68516 6.35038 3.62996C6.35038 3.54689 6.32574 3.46569 6.27959 3.39662C6.23344 3.32755 6.16785 3.27372 6.0911 3.24193C6.01436 3.21014 5.92991 3.20183 5.84844 3.21803C5.76697 3.23424 5.69213 3.27424 5.63339 3.33298C5.57465 3.39171 5.53465 3.46655 5.51845 3.54802C5.50224 3.6295 5.51056 3.71394 5.54235 3.79069C5.57414 3.86743 5.62797 3.93303 5.69704 3.97918Z' fill='%2306577C'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_13957_112512'%3E%3Crect width='12' height='12' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A");
    background-repeat: no-repeat;
    background-size: 0.75rem;
    background-position: 0.5rem 0.75rem;
    border-radius: 0.5rem;
    display: flex;
    flex-direction: row;
    padding: 0.5rem 0.5rem 0.5rem 1.5rem;
    gap: 0.25rem;

    .alert-heading {
        text-align: left;
        font-size: 0.75rem;
        line-height: 1.25rem;
    }
}
.modal-link {
    text-align: center;
}
.modal.modal-component .modal-dialog .modal-content .modal-body .textbox-question {
    padding: 0;
}
.modal.shop-question-popup .btn.btn-primary {
    background: $blue;

    &:focus,
    &:focus-visible {
        box-shadow:
            0 0 0 3px,
            0 0 0 5.5px $blue;
    }

    &.form-test-invalid {
        background: #d4d6d8;

        &:focus,
        &:focus-visible {
            box-shadow: none;
        }
    }
}
.shop-question-zipcode {
    display: flex;
    flex-direction: row;
    align-items: stretch;
    width: 100%;
    height: 48px;
    border-radius: 48px;
    padding-left: 16px;
    border: 1px solid #ccc;
    background: #fff;
    margin-bottom: 20px;
    @include media-breakpoint-up(md) {
        height: auto;
        padding-left: 0;
    }
    .input-wrapper.has-search-icon {
        display: flex;
        align-items: stretch;
        flex: 1 1 0;
        height: 100%;
        margin-bottom: 0;
        input,
        .form-control {
            width: 100%;
            height: 48px;
            min-height: 48px;
            max-height: 48px;
            border: none;
            padding: 0 1.5rem 0 1.5rem;
            outline: none;
            font-size: 1rem;
            background: transparent;
            box-sizing: border-box;
            border-radius: 2.5rem 0 0 2.5rem;
        }
    }
    .search-icon-button {
        display: flex;
        align-items: center;
        justify-content: center;
        background-color: #e5f1fa !important;
        width: 2.5rem;
        height: 48px;
        border: none;
        max-height: 48px;
        border-radius: 0 2.5rem 2.5rem 0;
        cursor: pointer;
    }
}
.show-more-shops-link a {
    text-align: center;
    display: block;
    margin-left: auto;
    margin-right: auto;
}
.shop-question-zipcode .search-icon-button {
    background-color: #e5f1fa !important;
    border-radius: 0 2.5rem 2.5rem 0;
}
.shop-question-zipcode .search-icon-button:hover,
.shop-question-zipcode .search-icon-button:focus {
    border: 1px solid $gray-500;
    box-shadow: 0 0 0 4px $blue-300;
    background-color: #e5f1fa;
    outline: none;
}
.shop-question-zipcode .input-wrapper.has-search-icon .form-control {
    border-radius: 2.5rem;
    padding-left: 1.5rem;
}

.shop-question-zipcode .form-test-error {
    display: block;
    width: 100%;
    margin-top: 0.25rem;
    margin-left: 0;
    color: #d32f2f; // or your error color
    position: static !important;
    font-size: 0.875rem;
    clear: both;
    float: none;
    display: block;
    width: 100%;
}
.loader-wrapper {
    display: flex;
    justify-content: center;
    align-items: center;
    max-width: 100%;
}
</style>
