<template>
    <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
        <loadingModal notFullScreen ref="loadingModal" />
        <funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
        <div class="container page-container-grouped-styles">
            <div class="row">
                <div class="col-12 col-md-10 col-lg-8 col-xl-7">
                    <h5 class="fw-normal mb-0 dark-header" :class="headerColor">
                        <span>
                            {{ serviceLocationText }}
                        </span>
                    </h5>
                    <funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" alignLeft />
                    <datePicker
                        class="mt-5"
                        v-model="selectedDate"
                        :startDate="datePickerStartDate"
                        :endDate="datePickerEndDate"
                        :availableDates="availableDates"
                        :isLoadingDates="isLoadingDates"
                        @requestMoreDates="handleRequestMoreDates" />
                    <mobileSchedulingCard
                        v-if="showMobileSchedulingCard"
                        class="mt-4"
                        v-model="selectedMobileScheduling"
                        :timeSlots="mobileTimeSlotsForSelectedDate"
                        :premiumTimeSlotPrice="premiumTimeSlotPrice"
                        :zipCode="serviceZipCode"
                        :showFreeFlag="showMobileFreeFlag"
                        @zip-code-clicked="onMobileZipCodeClicked" />
                    <inshopSchedulingCard
                        v-for="{ provider } in inShopProvidersAndTimeslots"
                        v-show="selectedDate"
                        :key="provider.providerNumber"
                        class="mt-4"
                        v-model="selectedInshopSchedulingByProvider[provider.providerNumber]"
                        :provider="provider"
                        :timeSlots="getInshopTimeSlotsForSelectedDate(provider.providerNumber)"
                        :radioGroupName="`inshopSchedulingTimeSlot-${provider.providerNumber}`"
                        @address-clicked="onInshopAddressClicked(provider)" />
                    <navbar
                        cmsWidgetName="FunnelFooterWidget"
                        ref="navbar"
                        @back-clicked="backButtonAction"
                        @ForwardClicked="forwardButtonAction" />
                </div>
            </div>
        </div>
    </Form>
</template>

<script>
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import navbar from "@/fmg-components/nav-bar/nav-bar";
import { Form } from "vee-validate";
import datePicker from "@/layouts/scheduling/date-picker/date-picker";
import mobileSchedulingCard from "@/layouts/scheduling/mobile-scheduling-card/mobile-scheduling-card";
import inshopSchedulingCard from "@/layouts/scheduling/inshop-scheduling-card/inshop-scheduling-card";
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
import store from "@/store";
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import {
    flushPagePrereqsLogs,
    hasServiceZipInfo,
    hasGlassPartsOrRepairInfo,
    hasInsuranceInfo,
} from "@/helpers/page-prerequisites-helper.js";
import { debugLog } from "@/helpers/debug-log-helper";

/**
 * Returns a YYYY-MM-DD date string offset by the given number of days from a base date.
 * @param {number} offsetDays - Number of days to offset (positive or negative).
 * @param {Date} base - The starting date (defaults to today).
 */
function toDateString(offsetDays, base = new Date()) {
    const d = new Date(base);
    d.setDate(d.getDate() + offsetDays);
    return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
}

const SCHEDULE_FETCH_DAYS = 15;

export default {
    name: "scheduling",
    async beforeRouteEnter(to, from, next) {
        const serviceZipCode = store.getters.order.serviceLocation.zipCode;

        const shopProviderData = await store.dispatch("getProviders", {
            payload: { serviceZipCode },
            pageNameToLog: to.name,
        });
        // Get the first 3 providers from the shopProviderData
        const providers = shopProviderData?.data?.shopProviders?.slice(0, 3) ?? [];
        const mobileProviderNumber = shopProviderData?.data?.mobileProviderNumber ?? null;

        const startDate = toDateString(0);
        const endDate = toDateString(SCHEDULE_FETCH_DAYS - 1);

        const promiseResultMap = [
            {
                resultKey: "cmsContent",
                promise: fetchCmsContentForPage(to.name),
            },
            {
                resultKey: "mobilePremiumFee",
                promise: store.dispatch("getMobilePremiumFee", {
                    pageNameToLog: to.name,
                }),
            },
            ...providers.map((provider, i) => ({
                resultKey: `inshopTimeSlots_${i}`,
                promise: store.dispatch("getShopTimeSlots", {
                    payload: {
                        startDate,
                        endDate,
                        shopAppointmentType: "InshopOrDropoff",
                        providerNumber: provider.providerNumber,
                    },
                    pageNameToLog: to.name,
                }),
            })),
            // Get the mobile time slots if a mobile provider number is available
            ...(mobileProviderNumber
                ? [
                      {
                          resultKey: "mobileTimeSlots",
                          promise: store.dispatch("getMobileTimeSlots", {
                              payload: { startDate, endDate, zipCode: serviceZipCode },
                              pageNameToLog: to.name,
                          }),
                      },
                  ]
                : []),
        ];
        const resultMap = await settleAllPromises(promiseResultMap);
        next((vm) => {
            vm.setCmsContent(resultMap.cmsContent);
            vm.inShopProvidersAndTimeslots = providers.map((provider, i) => ({
                provider,
                timeSlots: resultMap[`inshopTimeSlots_${i}`] ?? null,
            }));
            vm.mobileProviderAndTimeSlot = mobileProviderNumber
                ? {
                      providerNumber: mobileProviderNumber,
                      timeSlots: resultMap.mobileTimeSlots ?? null,
                  }
                : null;
            vm.datesLoaded = true;
            vm.mobilePremiumAppointmentFee = resultMap.mobilePremiumFee ?? null;
        });
    },
    watch: {
        selectedDate() {
            this.selectedMobileScheduling = null;
            this.selectedInshopSchedulingByProvider = {};
        },
    },
    computed: {
        serviceLocationText() {
            return this.getCmsContent("ServiceLocationText", "Text");
        },
        serviceZipCode() {
            return store.getters.order.serviceLocation.zipCode;
        },
        showMobileSchedulingCard() {
            return Boolean(this.mobileProviderAndTimeSlot && this.selectedDate);
        },
        mobileTimeSlotsForSelectedDate() {
            if (!this.selectedDate) {
                return [];
            }
            const day = this.mobileProviderAndTimeSlot?.timeSlots?.days?.find(
                (d) => d.date === this.selectedDate
            );
            return day?.timeSlots ?? [];
        },
        premiumTimeSlotPrice() {
            if (this.mobilePremiumAppointmentFee?.partType !== PREMIUM_FEE_PART_TYPE) {
                return null;
            }
            return this.getTotalLineItemPrice(this.mobilePremiumAppointmentFee);
        },
        showMobileFreeFlag() {
            return true;
        },
        availableDates() {
            if (!this.datesLoaded) return null;
            const inshopDates = this.inShopProvidersAndTimeslots.flatMap(({ timeSlots }) =>
                (timeSlots?.days ?? []).map((d) => d.date)
            );
            const mobileDates = (this.mobileProviderAndTimeSlot?.timeSlots?.days ?? []).map(
                (d) => d.date
            );
            return [...new Set([...inshopDates, ...mobileDates])].sort();
        },
    },
    data() {
        return {
            selectedDate: null,
            isLoadingDates: false,
            datesLoaded: false,
            datePickerStartDate: toDateString(0),
            datePickerEndDate: toDateString(SCHEDULE_FETCH_DAYS - 1),
            inShopProvidersAndTimeslots: [],
            mobileProviderAndTimeSlot: null,
            mobilePremiumAppointmentFee: null,
            selectedMobileScheduling: null,
            selectedInshopSchedulingByProvider: {},
        };
    },
    methods: {
        getInshopTimeSlotsForSelectedDate(providerNumber) {
            if (!this.selectedDate) {
                return [];
            }
            const providerEntry = this.inShopProvidersAndTimeslots.find(
                ({ provider }) => provider.providerNumber === providerNumber
            );
            const day = providerEntry?.timeSlots?.days?.find((d) => d.date === this.selectedDate);
            return day?.timeSlots ?? [];
        },
        onInshopAddressClicked(provider) {
            // TODO: open Google Maps when address link functionality is implemented
            console.log("onInshopAddressClicked", provider?.providerNumber);
        },
        onMobileZipCodeClicked() {
            // TODO: open service zip modal when zip edit is implemented for scheduling page
        },
        arePagePrerequisitesValid() {
            const order = store.getters.order;
            const logQueue = [];

            const serviceZip = hasServiceZipInfo(order, logQueue);
            const glassPartsOrRepair = hasGlassPartsOrRepairInfo(order, logQueue);
            const insuranceInfo = hasInsuranceInfo(order, logQueue);

            const preReqResult = serviceZip && insuranceInfo && glassPartsOrRepair;

            return preReqResult;
        },
        backButtonAction() {
            const payment = store.getters.order.payment;
            if (
                payment?.isInsurance &&
                (payment?.insuranceCoverage?.isVerified ||
                    store.getters.order.referralNumber.length === 6)
            ) {
                navigateToHeritageFunnel({
                    shouldSaveSession: false,
                    pageNameToLog: this.pageName,
                    navType: "back",
                });
            } else {
                this.$router.navigateWithoutSaving(
                    this.navigationScenarios.CLICKED_BACK,
                    this.pageName
                );
            }
        },
        async handleRequestMoreDates() {
            this.isLoadingDates = true;
            this.$refs.loadingModal.showModal();

            // TODO: call getShopTimeSlots with the next date range and append results
            // to this.availableDates and advance this.datePickerEndDate
            console.log("handleRequestMoreDates");

            this.isLoadingDates = false;
            this.$refs.loadingModal.hideModal();
        },
        forwardButtonAction() {
            const appointmentType = store.getters.order.serviceLocation.appointmentType; // TODO: remove this once we have a proper appointment type
            if (appointmentType === AppointmentTypeStrings.MOBILE) {
                this.$router.navigateWithSaving(
                    this.navigationScenarios.CLICKED_FORWARD_WITH_MOBILE_SERVICE,
                    this.pageName
                );
            } else {
                this.$router.navigateWithSaving(
                    this.navigationScenarios.CLICKED_FORWARD,
                    this.pageName
                );
            }
        },
    },
    components: {
        funnelHeader,
        funnelSubHeader,
        navbar,
        Form,
        datePicker,
        mobileSchedulingCard,
        inshopSchedulingCard,
        loadingModal,
    },
};
</script>
<style lang="scss" scoped>
.dark-header {
    color: $black;
}
h5 {
    line-height: 32px;
    font-size: 1.25rem;
}
</style>
