<template>
    <div
        class="date-picker text-center"
        :class="[calendarViewDirection, { 'has-error': errors.length > 0 }]">
        <fieldset id="date-picker-fieldset">
            <legend class="sr-only">
                When would you like service?
            </legend>
            <div class="appointment-date-picker-header">
                When would you like service?
            </div>
            <div class="appointment-estimate-header">
                Your service will take approximately <span>{{ appointmentEstimate }}</span>
            </div>
            <div
                class="appointment-date-picker-container"
                :class="isMobileView ? 'mobile' : 'desktop'">
                <div class="header-cell header-start">
                    <button
                        v-if="activePageIndex !== 0"
                        type="button"
                        class="span-block-flex"
                        @click="gotoPreviousPage()">
                        <img
                            class="arrow-icon"
                            src="~@/assets/img/icons/icon-ablue-previous.png"
                            alt="Left arrow icon" />
                        Previous
                    </button>
                </div>
                <div class="header-cell header-middle">
                    {{ headerDateString }}
                </div>
                <div class="header-cell header-end">
                    <button
                        type="button"
                        class="span-block-flex"
                        @click="gotoNextPage()">
                        More
                        <img
                            class="arrow-icon"
                            src="~@/assets/img/icons/icon-ablue-next.png"
                            alt="Right arrow icon" />
                    </button>
                </div>
                <div class="week-row-container date-picker-row">
                    <template
                        v-for="n in daysToAdd"
                        :key="n">
                        <div class="day-of-week-header">
                            <span class="span-block day-of-week-caption">{{ showDayOfWeekForIndex(n - 1) }}</span>
                            <span class="span-block month-day-caption">{{ showMonthAndDayForIndex(n - 1) }}</span>
                        </div>
                    </template>
                </div>
                <div class="morning-row-container date-picker-row">
                    <template
                        v-for="n in daysToAdd"
                        :key="n">
                        <div
                            tabindex="0"
                            class="morning-row-cell"
                            :class="[showMorningAvailabilityForIndex(n - 1) > 0 ? 'has-appointments' : 'no-appointments'
                            , checkIsSelectedDay(n - 1, 'morning') ? 'selected-date' : '']"
                            @click="showMorningTimes(n - 1)"
                            @keydown.enter="showMorningTimes(n - 1)">
                            <span class="span-block top-caption">Morning</span>
                            <span class="span-block bottom-caption">
                                {{ showMorningAvailabilityForIndex(n - 1) }} available
                            </span>
                        </div>
                    </template>
                </div>
                <div class="afternoon-row-container date-picker-row">
                    <template
                        v-for="n in daysToAdd"
                        :key="n">
                        <div
                            tabindex="0"
                            class="afternoon-row-cell"
                            :class="[showAfternoonAvailabilityForIndex(n - 1) > 0 ? 'has-appointments' : 'no-appointments'
                            , checkIsSelectedDay(n - 1, 'afternoon') ? 'selected-date' : '']"
                            @click="showAfternoonTimes(n - 1)"
                            @keydown.enter="showAfternoonTimes(n - 1)">
                            <span class="span-block top-caption">Afternoon</span>
                            <span class="span-block bottom-caption">
                                {{ showAfternoonAvailabilityForIndex(n - 1) }} available
                            </span>
                        </div>
                    </template>
                </div>
            </div>
            <div
                v-if="selectedDate"
                class="appointment-time-picker-container"
                :class="isMobileView ? 'mobile' : 'desktop'">
                <div class="appointment-time-picker-header">
                    Available times:
                </div>
                <template
                    v-for="timeSlot in selectableTimeSlotsData"
                    :key="timeSlot.startTime">
                    <input
                        :id="`timeslot${timeSlot.startTime}`"
                        v-model="selectedTime"
                        type="radio"
                        name="time-slot"
                        class="sr-only"
                        :value="timeSlot.startTime"
                        @focus="timeSlotFocused(timeSlot)"
                        @change="timeSlotInputChanged(timeSlot)" />
                    <label
                        :for="`timeslot${timeSlot.startTime}`"
                        class="time-slot-button"
                        :class="[checkIsSelectedTimeSlot(timeSlot) ? 'selected-time-slot' : ''
                        , {'has-date-error': showTimeSlotError}]"
                        @click="selectTimeSlotForDay(timeSlot)">
                        {{ displayTimeSlotTime(timeSlot) }}
                    </label>
                </template>
            </div>
            <div class="row form-test-error">
                <div v-if="showTimeSlotError">
                    {{ displayErrorMessage }}
                </div>
            </div>
        </fieldset>
    </div>
</template>

<script>
// Supporting files
import { useMainStore } from '@/store';
import { useField } from 'vee-validate';
import { deepClone } from '@/helpers/object-helper';
import {
    convertDateToDateString,
    convertDateToShortMonth,
    convertDateToTwoDigitDay,
    convertDateToTwoDigitMonth,
    getDisplayTextForDurationLength,
    isAfternoon,
    militaryToTwelveHourTime
} from '@/helpers/date-helper';
import {
    AppointmentTypeStrings,
    PREMIUM_TIME_SLOT_ID_FLAG
} from '@/constants/schedule-constants';
import showIssLoadingModal from '@/helpers/loading-modal-helper.js';
import errorMessages from '@/constants/error-messages.js';
import { selectableDaysOptions } from './mixins/helpers';

export default {
    name: 'date-picker',
    props: {
        activeAppointmentType: {
            type: String,
            default: null
        },
        customComponentId: String,
        selectableDatesSetting: {
            type: String,
            validator(value) {
                return Object.values(selectableDaysOptions).includes(value);
            },
            default: selectableDaysOptions.PAST
        },
        isMobileView: {
            type: Boolean,
            default: false
        },
        modelValue: {
            type: Object
        },
        todayOverrideDateString: {
            // keep for use in unit tests to override today's date
            type: String,
            default: null
        },
        customSelectableDatesCallback: {
            type: Function,
            default() {
                return [];
            }
        },
        showTimeSlotError: {
            type: Boolean,
            default: false
        },
        validationRules: {
            type: String,
            default: ''
        }
    },
    emits: ['dateSelected', 'timeSlotSelected'],
    setup(props) {
        const uuid = crypto.randomUUID();
        const componentId = !props.customComponentId
            ? `component-${uuid}`
            : props.customComponentId;

        const mainStore = useMainStore();

        const { modelValue } = deepClone(props);
        const initialValue = modelValue;

        const fieldOptions = {
            value: modelValue,
            initialValue
        };

        const {
            errorMessage,
            handleBlur,
            handleChange,
            meta,
            validate,
            errors,
            resetField
        } = useField(componentId, props.validationRules, fieldOptions);

        return {
            componentId,
            mainStore,
            errorMessage,
            handleBlur,
            handleChange,
            validate,
            meta,
            errors,
            resetField
        };
    },
    data() {
        return {
            isLoading: true,
            selectableDatesData: [], // NOTE: uses monthNum (1-based), NOT monthIndex (0-based)
            selectableTimeSlotsData: [],
            selectedTimeOfDayGrouping: null,
            selectedDate: null,
            selectedTime: null,
            selectedTimeSlot: null,
            activeDate: new Date(),
            activePageIndex: 0,
            todaysDate: new Date(),
            mql: null,
            daysInViewMobile: 3,
            daysInViewStandard: 5,
            daysLoaded: 0,
            appointmentDurationMinutesMinimum: 90,
            appointmentDurationMinutesMaximum: 120,
            initialDaysToLoad: 15
        };
    },
    computed: {
        appointmentEstimate() {
            return getDisplayTextForDurationLength(this.appointmentDurationMinutesMinimum, this.appointmentDurationMinutesMaximum);
        },
        daysToAdd() {
            return this.isMobileView ? this.daysInViewMobile : this.daysInViewStandard;
        },
        displayErrorMessage() {
            return errorMessages.TIME_REQUIRED;
        },
        headerDateString() {
            const dayOffset = this.activePageIndex * this.daysToAdd;
            const startDateToShow = new Date(this.activeDate);
            startDateToShow.setDate(startDateToShow.getDate() + dayOffset);
            const startMonthDisplay = convertDateToShortMonth(startDateToShow);
            const endDateToShow = new Date(startDateToShow);
            endDateToShow.setDate(endDateToShow.getDate() + (this.daysToAdd - 1));
            const endMonthDisplay = convertDateToShortMonth(endDateToShow);

            if (startMonthDisplay !== endMonthDisplay) {
                return `${startMonthDisplay}. ${startDateToShow.getDate()} - ${endMonthDisplay}. ${endDateToShow.getDate()}`;
            }
            return `${startMonthDisplay}. ${startDateToShow.getDate()}-${endDateToShow.getDate()}`;
        },
        shortMonth() {
            return this.todaysDate.toLocaleString('en-US', { month: 'short' });
        },
        todayString() {
            return (
                this.todayOverrideDateString
                || convertDateToDateString(new Date())
            );
        },
        calendarViewDirection() {
            if (this.selectableDatesSetting === 'custom') return 'future';
            return 'past';
        }
    },
    watch: {
        isMobileView(newValue, oldValue) {
            if (newValue !== oldValue) {
                this.activePageIndex = 0;
                this.selectedDate = null;
                this.selectedTimeOfDayGrouping = null;
                this.selectedTime = null;
                this.selectedTimeSlot = null;
                this.findFirstAvailableDateInView();
            }
        },
        selectedTimeSlot(newValue, oldValue) {
            if (newValue !== oldValue) {
                const testObj = this.getSelectedTimeSlotInfoObject(newValue);
                this.$emit('timeSlotSelected', testObj);
            }
        },
        selectedDate(newValue, oldValue) {
            if (newValue !== oldValue) {
                this.$emit('dateSelected', newValue);
            }
        }
    },
    methods: {
        initializeComponent(initialData) {
            this.resetComponent();
            this.setCalendarData(initialData);
        },
        resetComponent() {
            this.isLoading = true;
            this.selectableDatesData = []; // NOTE: uses monthNum (1-based), NOT monthIndex (0-based)
            this.selectableTimeSlotsData = [];
            this.selectedTimeOfDayGrouping = null;
            this.selectedDate = null;
            this.selectedTime = null;
            this.selectedTimeSlot = null;
            this.activeDate = new Date();
            this.activePageIndex = 0;
            this.todaysDate = new Date();
            this.mql = null;
            this.daysInViewMobile = 3;
            this.daysInViewStandard = 5;
            this.daysLoaded = 0;
            this.appointmentDurationMinutesMinimum = 90;
            this.appointmentDurationMinutesMaximum = 120;
            this.initialDaysToLoad = 15;
        },
        addPremiumFlagToInput(routeCode) {
            return (`${routeCode}${PREMIUM_TIME_SLOT_ID_FLAG}`);
        },
        removePremiumFlagFromInput(routeCode) {
            return routeCode.replace(PREMIUM_TIME_SLOT_ID_FLAG, '');
        },
        getSelectedTimeSlotInfoObject(timeSlot) {
            const routeCode = timeSlot?.id;
            let routeCodeToUse = routeCode;
            const routeCodeIncludesPremium = routeCode?.includes(PREMIUM_TIME_SLOT_ID_FLAG);
            if (routeCodeIncludesPremium) {
                routeCodeToUse = this.removePremiumFlagFromInput(routeCode);
            }

            const fullTimeSlot = this.selectableTimeSlotsData?.find((ts) => ts.id === routeCodeToUse);

            if (fullTimeSlot) {
                return {
                    timeSlot: {
                        date: this.selectedDate,
                        routeCode: fullTimeSlot.id,
                        startTime: fullTimeSlot.startTime,
                        endTime: fullTimeSlot.endTime,
                        jobMaxMinutes: this.appointmentDurationMinutesMaximum.toString(),
                        jobMinMinutes: this.appointmentDurationMinutesMinimum.toString()
                    },
                    isPremiumAppointment: !!routeCodeIncludesPremium
                };
            }

            return {
                timeSlot: {
                    date: null,
                    startTime: null,
                    endTime: null,
                    routeCode: null,
                    jobMaxMinutes: null,
                    jobMinMinutes: null
                },
                isPremiumAppointment: null
            };
        },
        displayTimeSlotTime(timeSlot) {
            const appointmentType = this.activeAppointmentType || AppointmentTypeStrings.IN_SHOP;
            if (appointmentType === AppointmentTypeStrings.MOBILE || appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP) {
                return `${militaryToTwelveHourTime(timeSlot.startTime)} - ${militaryToTwelveHourTime(timeSlot.endTime)}`;
            }
            return militaryToTwelveHourTime(timeSlot.startTime);
        },
        findFirstAvailableDateInView() {
            for (let i = 0; i < this.daysToAdd; i += 1) {
                const dateInView = this.getDateToShow(i);
                const dateInViewString = convertDateToDateString(dateInView);
                const selectableDateObj = this.selectableDatesData.find((dateObj) => dateObj.date === dateInViewString);
                if (selectableDateObj && selectableDateObj.timeSlots && selectableDateObj.timeSlots.length > 0) {
                    if (selectableDateObj.morningTimeSlots && selectableDateObj.morningTimeSlots.length > 0) {
                        this.showMorningTimes(i);
                    } else {
                        this.showAfternoonTimes(i);
                    }
                    break;
                }
            }
        },
        findInitialPageIndex(daysFromStart) {
            if (daysFromStart !== null && daysFromStart !== undefined) {
                return {
                    initialPageIndex: Math.floor(daysFromStart / this.daysToAdd),
                    initialDayIndex: daysFromStart % this.daysToAdd
                };
            }
            return {
                initialPageIndex: 0,
                initialDayIndex: null
            };
        },
        findInitialDate(myDateString, initialDayIndex) {
            const dateInView = this.getDateToShow(initialDayIndex);
            const dateInViewString = convertDateToDateString(dateInView);
            if (dateInViewString === myDateString) {
                const selectableDateObj = this.selectableDatesData.find((dateObj) => dateObj.date === dateInViewString);
                if (selectableDateObj) {
                    const initialTimeSlot = this.mainStore.order.schedule;
                    const isAfternoonSlot = isAfternoon(initialTimeSlot?.startTime);
                    if (isAfternoonSlot) {
                        this.showAfternoonTimes(initialDayIndex);
                        this.findInitialTimeByStore(selectableDateObj.afternoonTimeSlots);
                    } else {
                        this.showMorningTimes(initialDayIndex);
                        this.findInitialTimeByStore(selectableDateObj.morningTimeSlots);
                    }
                }
            }
        },
        findInitialTimeByStore(timeSlots) {
            const initialTimeSlot = this.mainStore.order.schedule;
            if (!initialTimeSlot || !initialTimeSlot.startTime) {
                return;
            }
            const initialStartTime = initialTimeSlot.startTime;
            const foundTimeSlot = timeSlots.find((ts) => ts.startTime === initialStartTime);
            if (foundTimeSlot) {
                this.selectTimeSlotForDay(foundTimeSlot);
            }
        },
        getDateToShow(index) {
            const dayOffset = this.activePageIndex * this.daysToAdd;
            const dateToShow = new Date(this.activeDate);
            dateToShow.setDate(dateToShow.getDate() + index + dayOffset);
            return dateToShow;
        },
        getDateToShowString(index) {
            const dateToShow = this.getDateToShow(index);
            return convertDateToDateString(dateToShow);
        },
        async gotoNextPage() {
            const maxPageIndex = Math.floor((this.daysLoaded - 1) / this.daysToAdd);
            if (this.activePageIndex >= maxPageIndex) {
                // do not go to next page right away if at end of loaded days
                await this.loadMoreDays(maxPageIndex, this.daysToAdd, this.initialDaysToLoad).then(() => {
                    this.daysLoaded += this.initialDaysToLoad;
                    this.activePageIndex += 1;
                    this.selectedDate = null;
                    this.selectedTime = null;
                    this.selectedTimeSlot = null;
                    this.findFirstAvailableDateInView();
                });
                return;
            }
            this.activePageIndex += 1;
            this.selectedDate = null;
            this.selectedTime = null;
            this.selectedTimeSlot = null;
            this.findFirstAvailableDateInView();
        },
        gotoPreviousPage() {
            this.activePageIndex -= 1;
            this.selectedDate = null;
            this.selectedTime = null;
            this.selectedTimeSlot = null;
            this.findFirstAvailableDateInView();
        },
        checkIsSelectedDay(index, timeOfDayGrouping) {
            const dateToShowString = this.getDateToShowString(index);
            return this.selectedDate === dateToShowString && this.selectedTimeOfDayGrouping === timeOfDayGrouping;
        },
        checkIsSelectedTimeSlot(timeSlot) {
            if (!this.selectedTimeSlot) {
                return false;
            }
            return this.selectedTimeSlot.startTime === timeSlot.startTime;
        },
        selectTimeSlotForDay(timeSlot) {
            if (timeSlot) {
                this.selectedTime = timeSlot.startTime;
                this.selectedTimeSlot = timeSlot;
            }
        },
        showDayOfWeekForIndex(index) {
            const dateToShow = this.getDateToShow(index);
            return dateToShow.toLocaleDateString('en-US', { weekday: 'short' });
        },
        showMonthAndDayForIndex(index) {
            const dateToShow = this.getDateToShow(index);
            return `${convertDateToTwoDigitMonth(dateToShow)}/${convertDateToTwoDigitDay(dateToShow)}`;
        },
        showMorningAvailabilityForIndex(index) {
            const morningDateString = this.getDateToShowString(index);
            const selectableDateObj = this.selectableDatesData.find((dateObj) => dateObj.date === morningDateString);
            if (selectableDateObj && selectableDateObj.morningTimeSlots && selectableDateObj.morningTimeSlots.length > 0) {
                return selectableDateObj.morningTimeSlots.length;
            }
            return 0;
        },
        showMorningTimes(index) {
            const morningDateString = this.getDateToShowString(index);
            const selectableDateObj = this.selectableDatesData.find((dateObj) => dateObj.date === morningDateString);
            if (selectableDateObj && selectableDateObj.morningTimeSlots && selectableDateObj.morningTimeSlots.length > 0) {
                if (this.selectedDate === morningDateString && this.selectedTimeOfDayGrouping === 'morning') {
                    // already selected, do nothing
                    return;
                }
                this.selectedDate = morningDateString;
                this.selectedTimeOfDayGrouping = 'morning';
                this.selectableTimeSlotsData = selectableDateObj.morningTimeSlots;
                this.selectedTime = null;
                this.selectedTimeSlot = null;
            }
        },
        showAfternoonAvailabilityForIndex(index) {
            const afternoonDateString = this.getDateToShowString(index);
            const selectableDateObj = this.selectableDatesData.find((dateObj) => dateObj.date === afternoonDateString);
            if (selectableDateObj && selectableDateObj.afternoonTimeSlots && selectableDateObj.afternoonTimeSlots.length > 0) {
                return selectableDateObj.afternoonTimeSlots.length;
            }
            return 0;
        },
        showAfternoonTimes(index) {
            const afternoonDateString = this.getDateToShowString(index);
            const selectableDateObj = this.selectableDatesData.find((dateObj) => dateObj.date === afternoonDateString);
            if (selectableDateObj && selectableDateObj.afternoonTimeSlots && selectableDateObj.afternoonTimeSlots.length > 0) {
                if (this.selectedDate === afternoonDateString
                    && this.selectedTimeOfDayGrouping === 'afternoon') {
                    // already selected, do nothing
                    return;
                }
                this.selectedDate = afternoonDateString;
                this.selectedTimeOfDayGrouping = 'afternoon';
                this.selectableTimeSlotsData = selectableDateObj.afternoonTimeSlots;
                this.selectedTimeSlot = null;
                this.selectedTime = null;
            }
        },
        timeSlotFocused(timeSlot) {
            if (timeSlot && this.selectedTime === null) {
                this.selectTimeSlotForDay(timeSlot);
            }
        },
        timeSlotInputChanged(timeSlot) {
            this.selectTimeSlotForDay(timeSlot);
        },
        async setCalendarData(config = {}) {
            // set selectable dates data
            config.initialShopTimeSlotsResponse.days.forEach((selectableDate) => {
                const dateObjectToPush = {
                    date: selectableDate.date,
                    timeSlots: selectableDate.timeSlots,
                    morningTimeSlots: selectableDate.timeSlots.filter((timeSlot) => {
                        const timeHour = parseInt(timeSlot.startTime.split(':')[0], 10);
                        return timeHour < 12;
                    }),
                    afternoonTimeSlots: selectableDate.timeSlots.filter((timeSlot) => {
                        const timeHour = parseInt(timeSlot.startTime.split(':')[0], 10);
                        return timeHour >= 12;
                    }),
                    isSelected: false
                };
                this.selectableDatesData.push(dateObjectToPush);
            });

            this.daysLoaded = config.initialDaysLoaded || this.initialDaysToLoad;
            this.appointmentDurationMinutesMaximum = config.initialShopTimeSlotsResponse.estimatedServiceMinutesMaximum;
            this.appointmentDurationMinutesMinimum = config.initialShopTimeSlotsResponse.estimatedServiceMinutesMinimum;

            let pageIndexObj = { initialPageIndex: 0, initialDayIndex: null };
            if (config.daysFromStart !== null && config.daysFromStart !== undefined) {
                pageIndexObj = this.findInitialPageIndex(config.daysFromStart);
                this.activePageIndex = pageIndexObj.initialPageIndex;
            }

            if (config.preSelectedDate) {
                this.findInitialDate(config.preSelectedDate, pageIndexObj.initialDayIndex);
            } else {
                this.findFirstAvailableDateInView();
                let attempts = 0;
                while (!this.selectedDate && attempts < 5) {
                    // eslint-disable-next-line no-await-in-loop
                    await this.gotoNextPage();
                    attempts += 1;
                }
            }

            this.isLoading = false;
        },
        async loadMoreDays(maxPageIndex, daysInView, daysToFetch) {
            showIssLoadingModal(true);

            const startDateForFetch = new Date(this.activeDate);
            startDateForFetch.setDate(startDateForFetch.getDate() + (maxPageIndex + 1) * daysInView);
            const startDateToFetchString = convertDateToDateString(startDateForFetch);
            const endDateForFetch = new Date(startDateForFetch);
            endDateForFetch.setDate(endDateForFetch.getDate() + (daysToFetch - 1));
            const endDateToFetchString = convertDateToDateString(endDateForFetch);
            // make new API call with this month's start and end dates
            await this.updateSelectableDates(
                startDateToFetchString,
                endDateToFetchString
            ).catch(() => {
                showIssLoadingModal(false);
            });

            showIssLoadingModal(false);
        },
        async updateSelectableDates(dateStart, dateEnd) {
            const moreSelectableDates =
                await this.customSelectableDatesCallback(
                    dateStart,
                    dateEnd
                );

            moreSelectableDates.days.forEach((selectableDate) => {
                const index = this.selectableDatesData.findIndex((dateObj) => dateObj.date === selectableDate.date);
                if (index === -1) {
                    const dateObjectToPush = {
                        date: selectableDate.date,
                        timeSlots: selectableDate.timeSlots,
                        morningTimeSlots: selectableDate.timeSlots.filter((timeSlot) => {
                            const timeHour = parseInt(timeSlot.startTime.split(':')[0], 10);
                            return timeHour < 12;
                        }),
                        afternoonTimeSlots: selectableDate.timeSlots.filter((timeSlot) => {
                            const timeHour = parseInt(timeSlot.startTime.split(':')[0], 10);
                            return timeHour >= 12;
                        }),
                        isSelected: false
                    };

                    this.selectableDatesData.push(dateObjectToPush);
                }
            });
        }
    }
};
</script>

<style lang="scss" scoped>
@import '@/styles/ux-variables-svg-strings.scss';

.date-picker-hidden {
    opacity: 0;
    max-height: 0;
}
.date-picker {
    position: relative;

    .appointment-date-picker-header {
        font-weight: 600;
        color: #000;
        font-size: 1rem;
        text-align: left;
        margin-top: 1.25rem;
    }

    .appointment-estimate-header {
        font-weight: 400;
        color: #525656;
        font-size: 1rem;
        text-align: left;
        margin-top: 0.25rem;

        span {
            font-weight: 600;
            color:#000;
        }
    }

    .appointment-date-picker-container {
        display: grid;
        grid-column-gap: 0px;
        grid-row-gap: 0px;

        margin-top: 1.25rem;
        border-radius: .3125rem;
        box-shadow: 0 0 .625rem 0 rgba(0, 0, 0, 0.2);

        @include media-breakpoint-up(xs) {
            grid-template-columns: repeat(3, 33.33%);
        }
        @include media-breakpoint-up(xl) {
            grid-template-columns: repeat(5, 20%);
        }
        .date-picker-row {
            display: contents;
        }
        .header-cell {
            font-size: 1rem;
            padding: .3125rem;

            .span-block-flex {
                display: flex;
                align-items: center;
                border: none;
                background-color: #fff;
                color: #525656;
                cursor: pointer;

                &:hover {
                    text-decoration: underline;
                }
            }
        }
        .header-end {
            text-align: end;

            .span-block-flex {
                justify-self: flex-end;
                justify-content: flex-end;

                img {
                    margin-left: 0.25rem;
                }
            }
        }
        .header-middle {
            font-weight: 600;
            color: #000;
            @include media-breakpoint-up(xs) {
                grid-column: 2 / span 1;
            }
            @include media-breakpoint-up(xl) {
                grid-column: 2 / span 3;
            }

            text-align: center;
        }
        .header-start {
            text-align: start;

            .span-block-flex {
                justify-self: flex-start;
                justify-content: flex-start;

                img {
                    margin-right: 0.25rem;
                }
            }
        }
        .day-of-week-header {
            background-color: #0070d1;
            color: $white;
            padding: 0.5rem 0.25rem;
            line-height: 1.5rem;

            .day-of-week-caption {
                font-weight: 600;
                font-size: 1rem;
            }
            .month-day-caption {
                font-weight: 300;
                font-size: 0.8125rem;
            }
        }
        .morning-row-cell, .afternoon-row-cell {
            padding: 0.8125rem 0.25rem;
            line-height: 1.5rem;
            border: solid 1px #cacbcc;

            .top-caption {
                font-weight: 400;
                font-size: 1rem;
                color: #000;
            }
            .bottom-caption {
                font-weight: 400;
                font-size: 0.75rem;
            }

            &.has-appointments {
                &:hover {
                    border: solid 1px #0070d1;
                    cursor: pointer;
                }

                .bottom-caption {
                    color: #1574a1;
                    font-weight: 500;
                }
            }

            &.selected-date {
                background-color: $background-color-selected;
                border: solid 1px #0070d1;
            }

            &:focus, &:focus-visible {
                outline: none;
                border: solid 2px #0070d1;
            }
        }
        .span-block {
            display: block;
        }
    }

    .appointment-time-picker-container {
        margin-top: 1rem;
        margin-bottom: 0.5rem;

        .appointment-time-picker-header {
            font-weight: 600;
            color: #000;
            font-size: 1rem;
            text-align: left;
        }

        .time-slot-button {
            width: 100%;
            border: 1px solid #b3b4b5;
            border-radius: $border-radius-list-button;
            box-shadow: 0 1px 5px 0 rgba(0, 0, 0, .2);
            color: #525656;
            padding: 0.625rem 0;
            margin-top: 0.625rem;
            text-align: center;
            cursor: pointer;

            &.selected-time-slot {
                background-color: $background-color-selected;
                border: solid 1px #0070d1;
                color:#000;
                font-weight: 500;
            }

            &.has-date-error {
                border: 1px solid #d93025;
            }
        }
    }

    fieldset {
        flex-grow: 1;
        position: relative;
    }

    .btn-link {
        font-weight: 500;
        text-underline-offset: 4px;
        flex-grow: 0;
        &:focus {
            box-shadow: none;
        }
    }
}
.btn-link {
    display: block;
    position: relative;
    height: 2rem;
    width: 100%;
    justify-content: center;
    background: transparent;
    border: none;
    font-weight: 500;
    letter-spacing: inherit;
    text-underline-offset: 4px;
    z-index: 2;
}

.form-test-error {
    text-align: left;
    margin-top: 0;
    color: #db0020;
    font-weight: 400;
    font-size: 1rem;
}
</style>
