<template>
    <div class="fade-on-route-transition">
        <div class="justify-content-center">
            <siteHeader
                ref="siteHeader"
                :cmsWidgetName="widget.siteHeader" />
        </div>
        <div class="iss-heritage-container-width">
            <div class="tpa-search-container iss-heritage-content-container-width">
                <div class="zip-code-container">
                    <Form
                        id="searchProvidersForm"
                        @submit="onSubmit"
                        @invalidSubmit="onInvalidSubmit">
                        <label
                            id="tpaSearchQuestionLabel"
                            for="tpaSearchQuestionField"
                            class="fs-5 mt-5 text-black w-100">
                            {{ tpaSearchQuestionLabel }}
                        </label>
                        <label
                            id="searchInstructions"
                            for="tpaSearchQuestionField"
                            class="darker-gray w-100 mb-4">
                            {{ searchInstructionsText }}
                        </label>
                        <div class="mb-5">
                            <textboxQuestion
                                id="tpaSearchQuestionField"
                                v-model="tpaSearchValue"
                                inputId="tpaSearchQuestionFieldInput"
                                :cmsWidgetName="widget.tpaSearchQuestion"
                                :includeSearchIcon="true"
                                :displayQuestionText="false"
                                isRequired
                                :isDisabled="reloadingProviders"
                                :validationRules="rules.tpaSearch"
                                @clickEvent="searchClick" />
                        </div>
                    </Form>
                </div>
                <div class="map-selection-container">
                    <googleMap
                        id="map"
                        class="mb-4"
                        :markers="providerAddresses"
                        :zipCode="mapZipCode" />
                    <Form
                        id="providerSelectionForm"
                        v-slot="{ meta }"
                        @submit="onSubmit"
                        @invalidSubmit="onInvalidSubmit">
                        <dropdownQuestion
                            id="searchRadiusFilter"
                            v-model="radiusFilter"
                            :cmsWidgetName="widget.filterByQuestion"
                            inputId="searchRadiusFilterInput"
                            :options="radiusFilterOptions"
                            disableAutoFill
                            :isDisabled="reloadingProviders"
                            :validationRules="rules.filter" />
                        <loader
                            v-if="reloadingProviders"
                            id="providersLoader"
                            loaderPosition="center"
                            loaderColor="blue"
                            :width="2"
                            :height="2"
                            class="my-4" />
                        <div v-else>
                            <div class="my-4">
                                <buttonQuestion
                                    id="selectProviderQuestion"
                                    v-model="selectedProviderNumber"
                                    buttonTypeString="shopListButton"
                                    :buttonTypeObject="tpaShopListButton"
                                    class="radioQuestion"
                                    :answers="providerButtonData"
                                    groupName="chooseShop"
                                    textPosition="text-start"
                                    isRequired
                                    :validationRules="rules.provider"
                                    :additionalButtonData="additionalButtonData" />
                                <alert
                                    v-if="providers?.length === 0 ?? true"
                                    id="alertNoNetworkProviders"
                                    :cmsWidgetName="widget.noNetworkShopsAlert"
                                    alertClass="alert-warning"
                                    :isDismissible="false"
                                    :manualHeadline="
                                        noNetworkShopsAlertHeaderText
                                    " />
                            </div>
                            <div class="text-center">
                                <textLink
                                    id="preferredShopNotListedLink"
                                    linkType="navigation"
                                    href="javascript:void(0)"
                                    :text="shopNotListedModalLink"
                                    @clickEvent="doNotSeeMyShopLinkClick" />
                            </div>
                            <hr>
                            <siteFooter
                                class="mt-6"
                                ref="siteFooter"
                                :cmsWidgetName="widget.siteFooter"
                                :isForwardActionDisabled="!meta.valid"
                                @ForwardClicked="forwardButtonAction"
                                @backClicked="navigateBack" />
                                <div class="need-help-link-container">
                            <textLink
                                id="needHelpLink"
                                v-if="needHelpLinkText"
                                linkType="navigation"
                                :text="needHelpLinkText"
                                href="#"
                                @clickEvent="needHelpLinkClick" />
                        </div>
                        </div>
                    </Form>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
// Components
import { Form } from 'vee-validate';
import siteHeader from '@/iss-components/site-header/site-header.vue';
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
import textLink from '@/ux-components/text-link/text-link.vue';
import alert from '@/ux-components/alert/alert.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
import googleMap from '@/iss-components/google-map/google-map.vue';
import tpaShopListButton from '@/iss-components/tpa-shop-list-button/tpa-shop-list-button.vue';
import loader from '@/ux-components/loader/loader.vue';

// Supporting files
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import { useMainStore } from '@/store';
import BaseFormMixin from '@/mixins/base-form-mixin.js';
import globalRules from '@/constants/global-rules.js';
import widgetFields from '@/constants/cms-widget-fields.js';
import { shallowRef } from 'vue';
import { toTitleCase, toDisplayPhoneNumber } from '@/helpers/text-helper.js';
import bailoutMessage from '@/constants/bailoutMessage';
import settleAllPromises from '@/helpers/layout-helper';
import issPageValues from '@/router/router-constants/issPage-values';

export default {
    name: 'tpa-search',
    components: {
        siteHeader,
        textboxQuestion,
        dropdownQuestion,
        buttonQuestion,
        textLink,
        alert,
        loader,
        googleMap,
        siteFooter,
        Form
    },
    mixins: [BaseFormMixin],
    async beforeRouteEnter(to, from, next) {
        const serviceZipCode = useMainStore().order.serviceLocation.zipCode;
        const customerZipCode = useMainStore().order.customer.address.zipCode;
        const zipCode = serviceZipCode || customerZipCode;
        const pageData = useMainStore().pageData(to.query.issPage);
        const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
        const providersPromise = useMainStore().getTpaAndSafeliteProviders(zipCode, pageData?.tpaSearchValue ?? '');
        const promiseResultMap = [
            {
                resultKey: 'cmsContent',
                promise: cmsContentPromise
            },
            {
                resultKey: 'providers',
                promise: providersPromise
            }
        ];
        const resultMap = await settleAllPromises(promiseResultMap);
        next(async (vm) => {
            vm.setCmsContent(resultMap.cmsContent);
            vm.mapZipCode = zipCode;
            vm.providers = resultMap.providers;
            if (pageData) {
                vm.tpaSearchValue = pageData?.tpaSearchValue ?? vm.mapZipCode;
                vm.radiusFilter = pageData?.radiusFilter ?? 25;
            }
        });
    },
    data() {
        return {
            dataLoaded: false,
            pageData: null,
            tpaSearchValue: null,
            mapZipCode: null,
            radiusFilter: null,
            providers: [],
            selectedProviderNumber: useMainStore().order.serviceLocation.provider.providerNumber,
            reloadingProviders: false,
            additionalButtonData: {
                displayAvailabilityIndicators: false
            },
            widget: {
                siteHeader: 'SiteHeaderWidget',
                tpaSearchQuestion: 'TPASearchQuestion',
                searchInstructions: 'SearchInstructions',
                filterByQuestion: 'FilterByQuestion',
                noNetworkShopsAlert: 'NoNetworkShopsAlertWidget',
                shopNotListedLink: 'ShopNotListedLink',
                siteFooter: 'SiteFooterWidget',
                needHelpLink: 'NeedHelpLink'
            },
            rules: {
                tpaSearch: globalRules.TPA_SEARCH_FORMAT,
                filter: globalRules.OPTION_REQUIRED, // TODO do we even need this?
                provider: globalRules.OPTION_REQUIRED
            },
            tpaShopListButton: shallowRef(tpaShopListButton)
        };
    },
    computed: {
        radiusFilterOptions() {
            const radiusFilterOptions = this.getCmsContent(
                    this.widget.filterByQuestion,
                    widgetFields.INPUT_QUESTION_WIDGET.ANSWERS
                ) ?? [];
            const options = {};
            for (const option of radiusFilterOptions) {
                options[option.Name] = option.Text;
            }
            return options;
        },
        tpaSearchQuestionLabel() {
            return this.getCmsContent(
                this.widget.tpaSearchQuestion,
                widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT
            );
        },
        needHelpLinkText() {
            return this.getCmsContent(this.widget.needHelpLink, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
        },
        searchInstructionsText() {
            return this.getCmsContent(
                this.widget.searchInstructions,
                widgetFields.TEXT_BLOCK_WIDGET.TEXT
            );
        },
        shopNotListedModalLink() {
            return this.getCmsContent(
                this.widget.shopNotListedLink,
                widgetFields.TEXT_BLOCK_WIDGET.TEXT
            );
        },
        noNetworkShopsAlertHeaderText() {
            return this.getCmsContent(
                this.widget.noNetworkShopsAlert,
                widgetFields.ALERT_WIDGET.HEADLINE_TEXT
            )?.replaceAll('{custom:radiusInMiles}', this.radiusFilter + " miles");
        },
        radiusFilteredAndCappedProviders() {
            return this.providers.filter((provider) => provider.distanceInMiles <= this.radiusFilter).slice(0, 5);
        },
        providerAddresses() {
            return this.radiusFilteredAndCappedProviders?.map((provider) => ({
                title: toTitleCase(provider.companyName),
                fullAddress: this.getFullProviderAddress(provider),
                addressLines: [this.getProviderAddress(provider), this.getProviderCityZipState(provider)]
            })) ?? [];
        },
        providerButtonData() {
            return (
                this.radiusFilteredAndCappedProviders?.map((provider) =>
                    this.getShopButtonDataFromProvider(provider)) ?? []
            );
        },
        selectedProviderIsSafeliteShop() {
            return (
                this.providers?.find((p) => p.providerNumber === this.selectedProviderNumber)?.isSafeliteShop ?? false
            );
        }
    },
    watch: {
        providers(newProviders) {
            if (this.dataLoaded) {
                this.selectedProviderNumber =
                    newProviders?.length === 1 ?? false
                        ? newProviders[0]?.providerNumber ?? ''
                        : '';
            }
        },
        selectedProviderNumber(newNumber) {
            const provider = this.providers?.find((p) => p.providerNumber === newNumber);
            if (provider && this.dataLoaded) {
                useMainStore().updateServiceLocation({
                    zipCode: this.mapZipCode,
                    provider: {
                        providerNumber: provider?.providerNumber,
                        address: {
                            streetAddress: provider.address?.streetAddress,
                            city: provider.address?.city,
                            state: provider.address?.state,
                            zipCode: provider.address?.zipCode,
                            zipCodeCtu: provider.address?.zipCodeCtu
                        },
                        companyName: provider?.companyName,
                        phoneNumber: provider?.phoneNumber
                    }
                });
            }
        }
    },
    beforeUpdate() {
        if (!this.dataLoaded) {
            this.dataLoaded = true;
        }
    },
    methods: {
        getFullProviderAddress(provider) {
            const addressLine1 = this.getProviderAddress(provider);
            const addressLine2 = this.getProviderCityZipState(provider);
            const joinString =
                addressLine1.length > 0 && addressLine2.length > 0 ? ', ' : '';
            return [addressLine1, addressLine2].join(joinString);
        },
        getProviderAddress(provider) {
            return toTitleCase(provider?.address?.streetAddress);
        },
        getProviderCityZipState(provider) {
            const city = toTitleCase(provider?.address?.city);
            const state = provider?.address?.state ?? '';
            const zipCode = provider?.address?.zipCode ?? '';
            let addressLine2 = '';
            if (city) {
                addressLine2 += city;
                if (state || zipCode) {
                    addressLine2 += state ? ', ' : ' ';
                }
            }
            if (state) {
                addressLine2 += state;
                addressLine2 += zipCode ? ' ' : '';
            }
            if (zipCode) {
                addressLine2 += zipCode;
            }
            return addressLine2;
        },
        async getProviderButtonData(shopName = "") {
            this.reloadingProviders = true;
            const getTpaProvidersResult = await useMainStore().getTpaAndSafeliteProviders(
                this.mapZipCode,
                shopName
            );
            this.reloadingProviders = false;
            return getTpaProvidersResult?.data ?? [];
        },
        needHelpLinkClick() {
            this.$router.navigateBailout(bailoutMessage.RequestCallback());
        },
        async searchClick() {
            if (isNaN(this.tpaSearchValue)) {
                this.providers = await this.getProviderButtonData(this.tpaSearchValue);
            } else {
                this.mapZipCode = this.tpaSearchValue;
                this.providers = await this.getProviderButtonData();
            }
        },
        forwardButtonAction() {
            if (this.selectedProviderIsSafeliteShop) {
                useMainStore().updateIsSafeliteProvider(true);
            }
            const scenario = this.selectedProviderIsSafeliteShop
                ? this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE_SHOP
                : this.navigationScenarios
                    .CLICKED_FORWARD_WITH_NON_SAFELITE_SHOP;
            // Do not save the zip code as the tpa search value, prevents an outdated zipcode from being used
            //   as the default search value if customer goes back and changes zip earlier in the flow
            const tpaSearchValueToSave = this.tpaSearchValue === this.mapZipCode ? '' : this.tpaSearchValue;
            this.savePageDataToStore(issPageValues.TPA_SEARCH, {tpaSearchValue: tpaSearchValueToSave, radiusFilter: this.radiusFilter});
            this.$router.navigate(scenario, this.$route);
        },
        getShopButtonDataFromProvider(provider) {
            const cellNumber = toDisplayPhoneNumber(provider?.phoneNumber);
            const distance =
                provider?.distanceInMiles !== null
                && !Number.isNaN(parseFloat(provider?.distanceInMiles))
                    ? +provider.distanceInMiles.toFixed(1)
                    : null;

            return {
                buttonLabel: toTitleCase(provider?.companyName) ?? '',
                buttonLabelSubCopy: distance === null ? '' : `${distance} mi`,
                buttonBodyCopy: `${this.getFullProviderAddress(provider)}<br>${
                    cellNumber ?? ''
                }`,
                value: provider?.providerNumber ?? ''
            };
        }
    }
};
</script>

<style lang="scss" scoped>
.darker-gray {
    color: map-get($colors, 'darker-gray');
}

#tpaSearchQuestionLabel {
    margin-bottom: .625rem;
}

#map {
    height: 27.1875rem;
}

#providerSelectionForm {
    #alertNoNetworkProviders {
       :deep(.alert) {
        margin-bottom: 0px;
       }
    }
}

hr {
    margin: 1.375rem 0;
}

.need-help-link-container {
    margin-top:1.875rem;
    margin-bottom: 2.1875rem;
}

</style>
