<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="text-center fs-5 mt-5 mb-0 text-black w-100">
                            {{ tpaSearchQuestionLabel }}
                        </label>
                        <label
                            id="searchInstructions"
                            for="tpaSearchQuestionField"
                            class="text-center small darker-gray w-100 mb-4">
                            {{ searchInstructionsText }}
                        </label>
                        <div class="mb-5">
                            <textboxQuestion
                                id="tpaSearchQuestionField"
                                v-model="zipCode"
                                inputId="tpaSearchQuestionFieldInput"
                                :cmsWidgetName="widget.tpaSearchQuestion"
                                :includeSearchIcon="true"
                                :displayQuestionText="false"
                                isRequired
                                :isDisabled="reloadingProviders"
                                :validationRules="rules.zipCode"
                                @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="filter"
                            :cmsWidgetName="widget.filterByQuestion"
                            inputId="searchRadiusFilterInput"
                            :options="filterOptions"
                            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="shopListButton"
                                    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>
                            <siteFooter
                                ref="siteFooter"
                                :cmsWidgetName="widget.siteFooter"
                                :isForwardActionDisabled="!meta.valid"
                                @ForwardClicked="forwardButtonAction"
                                @backClicked="navigateBack" />
                        </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 shopListButton from '@/iss-components/shop-list-button/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';

const radiusFilterPairs = [
    { radius: 15, filter: '15 miles' },
    { radius: 25, filter: '25 miles' },
    { radius: 50, filter: '50 miles' },
    { radius: 100, filter: '100 miles' }
];

function convertRadiusFilterToInteger(filter) {
    const pair = radiusFilterPairs.find((p) => p.filter === filter);
    return pair?.radius ?? 0;
}

async function getInitialSearchData() {
    const customerZipCode = useMainStore().order.customer.address.zipCode;
    const serviceLocationZipCode = useMainStore().order.serviceLocation.zipCode;
    const zipCode = serviceLocationZipCode ?? customerZipCode;

    const { searchFilter } = useMainStore().order.serviceLocation;
    let { providerNumber } = useMainStore().order.serviceLocation.provider;

    let providers = [];
    let radius = 0;
    if (searchFilter) {
        radius = convertRadiusFilterToInteger(searchFilter);
        const result = await useMainStore().getTpaProviders(zipCode, radius);
        providers = result?.data?.shopProviders ?? [];

        return { zipCode, filter: searchFilter, providers, providerNumber };
    }

    providerNumber = null;
    let pairIndex = 0;
    let filter = '';
    while (providers.length === 0 && pairIndex < radiusFilterPairs.length) {
        const pair = radiusFilterPairs[pairIndex];
        radius = pair.radius;
        filter = pair.filter;
        // eslint-disable-next-line no-await-in-loop
        const result = await useMainStore().getTpaProviders(zipCode, radius);
        providers = result?.data?.shopProviders ?? [];

        pairIndex += 1;
    }

    return { zipCode, filter, providers, providerNumber };
}

export default {
    name: 'tpa-search',
    components: {
        siteHeader,
        textboxQuestion,
        dropdownQuestion,
        buttonQuestion,
        textLink,
        alert,
        loader,
        googleMap,
        siteFooter,
        // eslint-disable-next-line vue/no-reserved-component-names
        Form
    },
    mixins: [BaseFormMixin],
    async beforeRouteEnter(to, from, next) {
        const { zipCode, filter, providers, providerNumber } =
            await getInitialSearchData();
        const cmsContent = await fetchCmsContentForPage(to.query.issPage);

        next(async (vm) => {
            vm.setCmsContent(cmsContent);
            vm.setInitialSearchData(zipCode, filter, providers, providerNumber);
        });
    },
    data() {
        return {
            dataLoaded: false,
            zipCode: null,
            mapZipCode: null,
            filter: '',
            providers: [],
            selectedProviderNumber: '',
            reloadingProviders: false,
            additionalButtonData: {
                displayAvailabilityIndicators: false
            },
            widget: {
                siteHeader: 'SiteHeaderWidget',
                tpaSearchQuestion: 'TPASearchQuestion',
                searchInstructions: 'SearchInstructions',
                filterByQuestion: 'FilterByQuestion',
                noNetworkShopsAlert: 'NoNetworkShopsAlertWidget',
                shopNotListedLink: 'ShopNotListedLink',
                siteFooter: 'SiteFooterWidget'
            },
            rules: {
                zipCode: `${globalRules.ZIP_CODE_REQUIRED}|${globalRules.ZIP_CODE_SEARCH_FORMAT}`,
                filter: globalRules.OPTION_REQUIRED, // TODO do we even need this?
                provider: globalRules.OPTION_REQUIRED
            },
            shopListButton: shallowRef(shopListButton)
        };
    },
    computed: {
        filterOptions() {
            const filterByAnswers =
                this.getCmsContent(
                    this.widget.filterByQuestion,
                    widgetFields.INPUT_QUESTION_WIDGET.ANSWERS
                ) ?? [];
            const filterByAnswersObj = {};
            [...filterByAnswers].forEach((answer) => {
                filterByAnswersObj[answer.Name] = answer.Name;
            });
            return filterByAnswersObj;
        },
        tpaSearchQuestionLabel() {
            return this.getCmsContent(
                this.widget.tpaSearchQuestion,
                widgetFields.INPUT_QUESTION_WIDGET.QUESTION_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
            );
        },
        radiusInMiles() {
            return convertRadiusFilterToInteger(this.filter);
        },
        noNetworkShopsAlertHeaderText() {
            return this.getCmsContent(
                this.widget.noNetworkShopsAlert,
                widgetFields.ALERT_WIDGET.HEADLINE_TEXT
            )?.replaceAll('{custom:radiusInMiles}', this.radiusInMiles);
        },
        providerAddresses() {
            return this.providers?.map((provider) => ({
                title: provider.companyName,
                fullAddress: this.getFullProviderAddress(provider),
                addressLines: [this.getProviderAddress(provider), this.getProviderCityZipState(provider)]
            })) ?? [];
        },
        providerButtonData() {
            return (
                this.providers?.map((provider) =>
                    this.getShopButtonDataFromProvider(provider)) ?? []
            );
        },
        selectedProviderIsSafeliteShop() {
            return (
                this.providers?.find((p) => p.providerNumber === this.selectedProviderNumber)?.isSafeliteShop ?? false
            );
        }
    },
    watch: {
        async filter() {
            if (this.dataLoaded) {
                await this.getProviderButtonData().then((providers) => {
                    this.providers = providers;
                });
                this.mapZipCode = this.zipCode;
            }
        },
        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({
                    searchFilter: this.filter,
                    zipCode: this.zipCode,
                    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: {
        setInitialSearchData(zipCode, filter, providers, providerNumber) {
            this.zipCode = zipCode;
            this.mapZipCode = zipCode;
            this.filter = filter;
            this.providers = providers;
            this.selectedProviderNumber = providerNumber;
        },
        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() {
            this.reloadingProviders = true;
            const getTpaProvidersResult = await useMainStore().getTpaProviders(
                this.zipCode,
                this.radiusInMiles
            );
            this.reloadingProviders = false;
            return getTpaProvidersResult?.data?.shopProviders ?? [];
        },
        doNotSeeMyShopLinkClick() {
            this.mainStore.setBailout(bailoutMessage.doNotSeeMyShop());
            this.$router.navigate(
                this.navigationScenarios.CLICKED_DO_NOT_SEE_MY_SHOP_LINK,
                this.$route
            );
        },
        async searchClick() {
            this.providers = await this.getProviderButtonData();
            this.mapZipCode = this.zipCode;
        },
        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;
            this.$router.navigate(scenario, this.$route);
        },
        getCustomValueFromString(str) {
            switch (str) {
                case 'radiusInMiles':
                    return this.radiusInMiles;
                default:
                    return null;
            }
        },
        getShopButtonDataFromProvider(provider) {
            const cellNumber = toDisplayPhoneNumber(provider?.phoneNumber);
            const distance =
                provider?.distanceInMiles !== null
                && !Number.isNaN(parseFloat(provider?.distanceInMiles))
                    ? +provider.distanceInMiles.toFixed(1)
                    : null;

            return {
                buttonLabel: 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');
}
</style>
