document.addEventListener('DOMContentLoaded', function() {
    console.log('[DatePicker] DOMContentLoaded: Initializing datepicker...');
    // DOM Elements - Cache all frequently accessed elements
    const elements = {
        dateInput: document.getElementById('selected_date'),
        calendarDays: document.getElementById('calendarDays'),
        currentMonthElement: document.getElementById('currentMonth'),
        selectedDateText: document.getElementById('selectedDateText'),
        submitButton: document.getElementById('submitButton'),
        quotaWarning: document.getElementById('quotaWarning'),
        timeSlotContainer: document.getElementById('timeSlotContainer'),
        calendarContainer: document.querySelector('.calendar-container')
    };

    // Set timezone and locale
    moment.locale('id');
    moment.tz.setDefault('Asia/Jakarta');

    // Initialize variables
    let currentDate = moment().tz('Asia/Jakarta');
    let selectedDate = elements.dateInput.value ? moment(elements.dateInput.value).tz('Asia/Jakarta') : null;
    const today = moment().tz('Asia/Jakarta').startOf('day');

    // Store available and unavailable dates
    let availableDates = new Set();
    let unavailableDates = new Set();
    let isLoadingCalendar = false;
    let checkingNextMonth = false;
    let isQuotaCheckScheduled = false;
    let isTimeSlotsReady = false; // Start as false, rely on event
    let isCalendarDataReady = false; // Start as false, rely on load completion
    let retryAttempt = 0;
    let initialQuotaCheckPending = false; // Flag to indicate if initial check is waiting

    // Form Validation State
    let formValidationState = {
        hasDate: !!elements.dateInput.value, // Initialize based on pre-filled value
        hasAvailableTimeSlot: false // Initialize to false
    };

    // Cache settings
    const CACHE_EXPIRY = 60 * 15; // 15 minutes in seconds
    const CACHE_PREFIX = 'date_availability_';
    let cacheVersion = 0; // Current cache version, will be fetched from server
    console.log('[DatePicker] Initial cache version:', cacheVersion);

    // Check server for cache version on page load
    async function fetchCacheVersion() {
        console.log('[DatePicker] fetchCacheVersion: Fetching cache version from server...');
        try {
            const response = await fetch('/api/cache-version');
            if (response.ok) {
                try {
                    const data = await response.json();
                    cacheVersion = data.version || 0;
                    console.log('[DatePicker] fetchCacheVersion: Received cache version:', cacheVersion);
                    // Clear all caches if version changes
                    checkAndClearCachesIfVersionChanged(cacheVersion);
                } catch (jsonError) {
                    // Silently use fallback version without logging to console
                    cacheVersion = Math.floor(Date.now() / 1000); // Use current timestamp as fallback
                    console.warn('[DatePicker] fetchCacheVersion: Failed to parse JSON, using fallback version:', cacheVersion);
                }
            } else {
                // Silently use fallback version without logging to console
                cacheVersion = Math.floor(Date.now() / 1000);
                console.warn(`[DatePicker] fetchCacheVersion: Server responded with status ${response.status}, using fallback version:`, cacheVersion);
            }
        } catch (error) {
            // Silently use fallback version without logging to console
            cacheVersion = Math.floor(Date.now() / 1000);
            console.error('[DatePicker] fetchCacheVersion: Error fetching cache version, using fallback:', cacheVersion, error);
            // Still clear caches on error for safety
            clearAllCaches();
        }
    }

    // Call this immediately
    fetchCacheVersion();

    // Check and clear all caches if version changed
    function checkAndClearCachesIfVersionChanged(newVersion) {
        const storedVersion = localStorage.getItem('cache_version');
        console.log('[DatePicker] checkAndClearCachesIfVersionChanged: Stored version:', storedVersion, 'New version:', newVersion);
        if (storedVersion !== newVersion.toString()) {
            console.log('[DatePicker] checkAndClearCachesIfVersionChanged: Cache version mismatch, clearing caches.');
            clearAllCaches();
            localStorage.setItem('cache_version', newVersion.toString());
        }
    }

    // Clear all caches
    function clearAllCaches() {
        console.log('[DatePicker] clearAllCaches: Clearing all date and quota caches...');
        // Get all keys in localStorage
        for (let i = 0; i < localStorage.length; i++) {
            const key = localStorage.key(i);
            // Clear date availability and quota caches
            if (key && (key.startsWith(CACHE_PREFIX) || key.startsWith('quota_'))) {
                localStorage.removeItem(key);
            }
        }
    }

    // Helper function to get formatted cache key
    function getCacheKey(year, month) {
        const key = `${CACHE_PREFIX}${year}_${month}`;
        // console.log('[DatePicker] getCacheKey: Generated key:', key); // Optional: Can be noisy
        return key;
    }

    // Helper functions for localStorage cache
    function getFromCache(key) {
        console.log('[DatePicker] getFromCache: Attempting to get data for key:', key);
        try {
            const cachedData = localStorage.getItem(key);
            if (!cachedData) return null;

            const data = JSON.parse(cachedData);

            // Check if cache is expired or version mismatch
            if (data.timestamp &&
                (Math.floor(Date.now() / 1000) - data.timestamp) < CACHE_EXPIRY &&
                data.version === cacheVersion) {
                console.log('[DatePicker] getFromCache: Cache hit and valid for key:', key);
                return data.value;
            } else {
                console.log('[DatePicker] getFromCache: Cache expired or version mismatch for key:', key, 'Removing.');
                localStorage.removeItem(key);
                return null;
            }
        } catch (error) {
            console.error('[DatePicker] getFromCache: Error reading cache for key:', key, error);
            return null;
        }
    }

    function saveToCache(key, value) {
        console.log('[DatePicker] saveToCache: Saving data for key:', key);
        try {
            const dataToCache = {
                timestamp: Math.floor(Date.now() / 1000),
                version: cacheVersion,
                value: value
            };
            localStorage.setItem(key, JSON.stringify(dataToCache));
        } catch (error) {
            console.error('[DatePicker] saveToCache: Error saving cache for key:', key, error);
        }
    }

    // Function to preload the next month's data in the background
    async function preloadNextMonth() {
        const nextMonth = currentDate.clone().add(1, 'month');
        const year = nextMonth.year();
        const month = nextMonth.month() + 1; // JavaScript months are 0-indexed

        // Check if already in cache
        const cacheKey = getCacheKey(year, month);
        if (getFromCache(cacheKey)) {
            return;
        }

        console.log(`[DatePicker] preloadNextMonth: Preloading data for ${year}-${month}`);
        try {
            const response = await fetch(`/get-date-availability/${year}/${month}`);
            const data = await response.json();

            if (data.success) {
                console.log(`[DatePicker] preloadNextMonth: Successfully preloaded and cached data for ${year}-${month}`);
                saveToCache(cacheKey, {
                    available_dates: data.available_dates,
                    unavailable_dates: data.unavailable_dates
                });
            }
        } catch (error) {
            // Silently fail
        }
    }

    // Add CSS for calendar styling
    function addCalendarStyles() {
        const style = document.createElement('style');
        style.textContent = `
            .calendar-day.full-quota {
                background-color: #f8f9fa;
                color: #6c757d;
                position: relative;
                cursor: not-allowed !important;
            }

            .calendar-day.available {
                background-color: white;
                color: #212529;
                position: relative;
                cursor: pointer !important;
            }

            .calendar-day.unknown {
                background-color: #f8f9fa;
                color: #6c757d;
                cursor: wait !important;
            }

            .calendar-container {
                position: relative;
                min-height: 300px;
            }

            /* Add refresh button */
            .calendar-header {
                position: relative;
            }

            #refreshCalendar {
                position: absolute;
                right: 10px;
                top: 50%;
                transform: translateY(-50%);
                font-size: 1rem;
                cursor: pointer;
                color: #0d6efd;
            }
        `;
        document.head.appendChild(style);
    }

    // Add refresh button to clear cache and reload
    function addRefreshButton() {
        const calendarHeader = document.querySelector('.calendar-header');
        if (calendarHeader) {
            const refreshButton = document.createElement('span');
            refreshButton.id = 'refreshCalendar';
            refreshButton.innerHTML = '<i class="bi bi-arrow-clockwise"></i>';
            refreshButton.title = 'Muat ulang ketersediaan tanggal';
            refreshButton.addEventListener('click', function() {
                // Clear cache for current month
                const year = currentDate.year();
                const month = currentDate.month() + 1;
                const cacheKey = getCacheKey(year, month);
                localStorage.removeItem(cacheKey);

                // Reload data
                loadMonthAvailability(false);
            });
            calendarHeader.appendChild(refreshButton);
        }
    }

    // Add a safety timeout to ensure the calendar is always displayed
    // This prevents the calendar from being stuck in a loading state
    function setupCalendarSafetyTimeout() {
        setTimeout(() => {
            const loadingIndicator = document.getElementById('calendar-loading');
            if (loadingIndicator) {
                loadingIndicator.remove();
                isLoadingCalendar = false;
                
                // If we have no data at all, try one more time immediately
                if (availableDates.size === 0 && unavailableDates.size === 0) {
                    loadMonthAvailability(true);
                } else {
                    updateCalendar();
                }
            }
        }, 2000);
    }

    function updateCalendar() {
        console.log('[DatePicker] updateCalendar: Rendering calendar for', currentDate.format('YYYY-MM'));
        const year = currentDate.year();
        const month = currentDate.month(); // JavaScript months are 0-indexed (0-11)

        // Update the month/year display at the top of the calendar
        elements.currentMonthElement.textContent = currentDate.format('MMMM YYYY');
        elements.calendarDays.innerHTML = '';

        const firstDay = moment([year, month, 1]).tz('Asia/Jakarta');
        const daysInMonth = firstDay.daysInMonth();
        const startingDay = firstDay.day();

        // Add empty cells for padding
        for (let i = 0; i < startingDay; i++) {
            const emptyCell = document.createElement('div');
            emptyCell.classList.add('calendar-day', 'empty');
            elements.calendarDays.appendChild(emptyCell);
        }

        // Add days
        for (let day = 1; day <= daysInMonth; day++) {
            const date = moment([year, month, day]).tz('Asia/Jakarta');
            const dayElement = document.createElement('div');
            dayElement.classList.add('calendar-day');
            dayElement.textContent = day;

            const dateString = date.format('YYYY-MM-DD');

            // Check if date is disabled (weekend, past date, or known to be unavailable)
            if (date.isBefore(today, 'day') || date.day() === 0 || date.day() === 6) {
                dayElement.classList.add('disabled');
            } else if (unavailableDates.has(dateString)) {
                dayElement.classList.add('disabled');
                dayElement.classList.add('full-quota');
                dayElement.setAttribute('title', 'Kuota penuh untuk semua sesi');
            } else if (availableDates.has(dateString)) {
                // Date is known to be available
                dayElement.classList.add('available');
                dayElement.setAttribute('title', 'Tersedia sesi untuk tanggal ini');
                dayElement.addEventListener('click', () => selectDate(date));
            } else {
                // Date availability unknown (shouldn't happen with server-side loading)
                dayElement.classList.add('unknown');
                dayElement.setAttribute('title', 'Memuat ketersediaan...');
            }

            if (selectedDate && date.isSame(selectedDate, 'day')) {
                dayElement.classList.add('selected');
            }

            if (date.isSame(today, 'day')) {
                dayElement.classList.add('today');
            }

            elements.calendarDays.appendChild(dayElement);
        }

        // After rendering current month, preload next month's data
        setTimeout(() => preloadNextMonth(), 1000);
    }

    function selectDate(date) {
        const jakartaDate = moment(date).tz('Asia/Jakarta');
        const dateStr = jakartaDate.format('YYYY-MM-DD');
        console.log('[DatePicker] selectDate: Date selected:', dateStr);

        if (jakartaDate.day() === 0 || jakartaDate.day() === 6) {
            alert('Mohon maaf, pendaftaran hanya tersedia untuk hari kerja (Senin-Jumat)');
            return;
        }

        // Check if date is unavailable
        if (unavailableDates.has(dateStr)) {
            alert('Mohon maaf, semua sesi pada tanggal ini sudah penuh. Silakan pilih tanggal lain.');
            return;
        }

        selectedDate = jakartaDate;
        elements.dateInput.value = dateStr;
        elements.selectedDateText.textContent = jakartaDate.format('dddd, D MMMM YYYY');
        updateCalendar();

        // Trigger a custom event for quota-manager.js
        console.log('[DatePicker] selectDate: Dispatching dateSelected event for', dateStr);
        const event = new CustomEvent('dateSelected', {
            detail: { date: dateStr }
        });
        document.dispatchEvent(event);

        // Update form state
        formValidationState.hasDate = true;
        // Reset time slot selection when date changes
        formValidationState.hasAvailableTimeSlot = false;
        clearTimeSelection(); // Function to uncheck radio buttons
        updateSubmitButtonState(); // Update button state immediately

        // Run the quota check
        console.log('[DatePicker] selectDate: Triggering quota check.');
        checkQuotaInternal();
    }

    // Function to clear selected time slot radio button
    function clearTimeSelection() {
        const checkedTimeInput = document.querySelector('input[name="visit_time"]:checked');
        if (checkedTimeInput) {
            checkedTimeInput.checked = false;
        }
    }

    // Function to update submit button state
    function updateSubmitButtonState() {
        const isFormValid = formValidationState.hasDate && formValidationState.hasAvailableTimeSlot;
        if (elements.submitButton) {
            elements.submitButton.disabled = !isFormValid;
        }
        if (elements.quotaWarning) {
            elements.quotaWarning.style.display = isFormValid ? 'none' : 'block';
        }
    }

    // Internal function to check quota, uses readiness flags
    function checkQuotaInternal() {
        const currentSelectedDate = elements.dateInput.value;
        console.log('[DatePicker] checkQuotaInternal: Starting quota check for date:', currentSelectedDate);
        if (!currentSelectedDate) {
            console.log('[DatePicker] checkQuotaInternal: No date selected, exiting.');
            isQuotaCheckScheduled = false; // Reset flag if no date
            return;
        }

        // Prerequisites check: Ensure calendar data is loaded AND time slots are ready.
        console.log(`[DatePicker] checkQuotaInternal: Readiness check - isCalendarDataReady: ${isCalendarDataReady}, isTimeSlotsReady: ${isTimeSlotsReady}`);
        if (!isCalendarDataReady || !isTimeSlotsReady) {
            initialQuotaCheckPending = true; // Mark that a check is pending
            console.log('[DatePicker] checkQuotaInternal: Prerequisites not met, scheduling check. Pending:', initialQuotaCheckPending);
            return; // Exit function until prerequisites are met
        }
        console.log('[DatePicker] checkQuotaInternal: Prerequisites met. Proceeding with check.');
        initialQuotaCheckPending = false; // Reset pending flag as we are proceeding
        isQuotaCheckScheduled = false;

        // Get all time slot inputs (re-query in case they were added after initial load)
        const timeInputs = document.querySelectorAll('input[name="visit_time"]');
        if (timeInputs.length === 0) {
            return; // No slots to check
        }

        // Cache key for time slots
        const quotaCacheKey = `quota_${currentSelectedDate}`;
        const cachedQuotaData = getFromCache(quotaCacheKey);

        // If we have cached quota data, use it
        if (cachedQuotaData) {
            console.log('[DatePicker] checkQuotaInternal: Found cached quota data for', currentSelectedDate);
            updateTimeSlotsFromCache(cachedQuotaData);
            return;
        }
        console.log('[DatePicker] checkQuotaInternal: No cached quota data found for', currentSelectedDate, 'Fetching from server.');

        // Set loading state for all time slots
        timeInputs.forEach(input => {
            const label = document.querySelector(`label[for="${input.id}"]`);
            if (!label) return;
            
            const quotaInfo = label.querySelector('.quota-info');
            if (!quotaInfo) return;
            
            const quotaText = quotaInfo.querySelector('.quota-text');
            const quotaAvailable = quotaInfo.querySelector('.quota-available');
            const quotaTotal = quotaInfo.querySelector('.quota-total');
            const quotaBadge = quotaInfo.querySelector('.quota-badge');

            // Set loading state
            if (quotaText) quotaText.textContent = 'Memeriksa kuota...';
            if (quotaAvailable) quotaAvailable.textContent = '?';
            if (quotaTotal) quotaTotal.textContent = '?';
            if (quotaBadge) quotaBadge.className = 'quota-badge badge bg-secondary';
        });        // Collect all time values for batch request
        const timeValues = Array.from(timeInputs).map(input => input.value);
        
        // Make a single batch request for all time slots using GET
        console.log('[DatePicker] checkQuotaInternal: Fetching batch quotas for times:', timeValues.join(','));
        fetch(`/check-quotas/${currentSelectedDate}?times=${timeValues.join(',')}`)
        .then(response => {
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json();
        })
        .then(data => {
            // Handle successful batch response
            if (data.success && data.quotas) {
                console.log('[DatePicker] checkQuotaInternal: Batch quota check successful. Caching and updating slots.');
                // Cache the quota data
                saveToCache(quotaCacheKey, data.quotas);
                
                // Update all time slots with the batch data
                timeInputs.forEach(input => {
                    const timeValue = input.value;
                    const slotData = data.quotas[timeValue];
                    if (slotData) {
                        updateTimeSlot(input, slotData);
                    }
                });
            } else {
                console.warn('[DatePicker] checkQuotaInternal: Batch quota check failed or returned no quotas. Falling back to individual checks.');
                // Fallback to individual requests if batch fails but returns a 200 OK
                // This helps with backwards compatibility
                fallbackToIndividualQuotaChecks(currentSelectedDate, timeInputs);
            }
        })
        .catch(error => {
            console.error('[DatePicker] checkQuotaInternal: Error in batch quota check. Falling back to individual checks.', error);
            // Fallback to individual requests on network error
            fallbackToIndividualQuotaChecks(currentSelectedDate, timeInputs);
        });
    }

    // Fallback function for backward compatibility with existing API
    function fallbackToIndividualQuotaChecks(currentSelectedDate, timeInputs) {
        console.log('[DatePicker] fallbackToIndividualQuotaChecks: Performing individual quota checks for date:', currentSelectedDate);
        // Create an object to store quota data for caching
        const quotaDataCache = {};
        let completedRequests = 0;
        const totalRequests = timeInputs.length;
        const quotaCacheKey = `quota_${currentSelectedDate}`;

        timeInputs.forEach(input => {
            const selectedTime = input.value;
            console.log(`[DatePicker] fallbackToIndividualQuotaChecks: Fetching quota for time: ${selectedTime}`);
            fetch(`/check-quota/${currentSelectedDate}/${selectedTime}`)
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP error! status: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    console.log(`[DatePicker] fallbackToIndividualQuotaChecks: Received quota data for time ${selectedTime}:`, data);
                    // Store data for caching
                    quotaDataCache[selectedTime] = data;
                    updateTimeSlot(input, data);
                    
                    // Check if all requests are done
                    completedRequests++;
                    if (completedRequests === totalRequests && totalRequests > 0) {
                        saveToCache(quotaCacheKey, quotaDataCache);
                    }
                })
                .catch(error => {
                    console.error(`[DatePicker] fallbackToIndividualQuotaChecks: Error fetching quota for time ${selectedTime}:`, error);
                    handleQuotaRequestError(input);
                    completedRequests++;
                    if (completedRequests === totalRequests && totalRequests > 0) {
                        // We don't cache on error
                    }
                });
        });
    }

    // Centralized error handling for quota requests
    function handleQuotaRequestError(input) {
        console.error('[DatePicker] handleQuotaRequestError: Failed to load quota for input ID:', input.id);
        const label = document.querySelector(`label[for="${input.id}"]`);
        if (!label) return;
        
        const quotaInfo = label.querySelector('.quota-info');
        if (!quotaInfo) return;
        
        const quotaText = quotaInfo.querySelector('.quota-text');
        const quotaAvailable = quotaInfo.querySelector('.quota-available');
        const quotaTotal = quotaInfo.querySelector('.quota-total');
        const quotaBadge = quotaInfo.querySelector('.quota-badge');
        
        if (quotaText) {
            quotaText.textContent = 'Gagal memuat kuota';
            quotaText.className = 'quota-text text-danger';
        }
        
        // Ensure the slot appears disabled on error
        input.disabled = true;
        if (label) label.classList.add('disabled-time-slot');
        if (quotaBadge) quotaBadge.className = 'quota-badge badge bg-danger';
        if (quotaAvailable) quotaAvailable.textContent = 'X';
        if (quotaTotal) quotaTotal.textContent = 'X';
    }

    // Helper function to update time slots from cached data
    function updateTimeSlotsFromCache(cachedData) {
        console.log('[DatePicker] updateTimeSlotsFromCache: Updating slots from cache.');
        const timeInputs = document.querySelectorAll('input[name="visit_time"]');

        timeInputs.forEach(input => {
            const selectedTime = input.value;
            const slotData = cachedData[selectedTime];

            if (!slotData) {
                return;
            }

            updateTimeSlot(input, slotData);
        });
    }

    // Helper function to update a single time slot
    function updateTimeSlot(input, data) {
        // console.log(`[DatePicker] updateTimeSlot: Updating slot ID ${input.id} with data:`, data); // Optional: Can be noisy
        const selectedTime = input.value;
        const label = document.querySelector(`label[for="${input.id}"]`);

        if (!label) {
            return;
        }

        const quotaInfo = label.querySelector('.quota-info');
        if (!quotaInfo) {
            return;
        }

        const quotaText = quotaInfo.querySelector('.quota-text');
        const quotaAvailable = quotaInfo.querySelector('.quota-available');
        const quotaTotal = quotaInfo.querySelector('.quota-total');
        const quotaBadge = quotaInfo.querySelector('.quota-badge');

        if (data.disabled) {
            // Slot is disabled (quota is 0)
            input.disabled = true;
            label.classList.add('disabled-time-slot');
            if (quotaText) {
                quotaText.textContent = 'Tidak tersedia';
                quotaText.className = 'quota-text text-danger fw-bold';
            }
            if (quotaBadge) quotaBadge.className = 'quota-badge badge bg-danger';
            if (quotaAvailable) quotaAvailable.textContent = '0';
            if (quotaTotal) quotaTotal.textContent = '0';
        } else if (!data.available) {
            // Slot is full
            input.disabled = true;
            label.classList.add('disabled-time-slot');
            if (quotaText) {
                quotaText.textContent = 'Kuota Penuh';
                quotaText.className = 'quota-text text-danger fw-bold';
            }
            if (quotaBadge) quotaBadge.className = 'quota-badge badge bg-danger';
            if (quotaAvailable) quotaAvailable.textContent = '0';
            if (quotaTotal) quotaTotal.textContent = data.quota;
        } else {
            // Slot is available
            input.disabled = false;
            label.classList.remove('disabled-time-slot');
            const available = data.quota - data.used;
            if (quotaText) {
                quotaText.textContent = 'Kuota Tersedia';
                quotaText.className = 'quota-text text-success';
            }
            if (quotaBadge) quotaBadge.className = 'quota-badge badge bg-success';
            if (quotaAvailable) quotaAvailable.textContent = available;
            if (quotaTotal) quotaTotal.textContent = data.quota;
        }

        // Trigger a change event in case this is the selected radio button
        if (input.checked) {
            const event = new Event('change');
            input.dispatchEvent(event);
        }
    }

    // Function to fetch and load date availability from the server
    async function loadMonthAvailability(checkNextMonthIfNeeded = true) {
        if (isLoadingCalendar) {
            console.log('[DatePicker] loadMonthAvailability: Already loading, skipping.');
            return;
        }
        console.log('[DatePicker] loadMonthAvailability: Starting to load availability for', currentDate.format('YYYY-MM'), 'CheckNextMonth:', checkNextMonthIfNeeded);
        isLoadingCalendar = true;
        retryAttempt = 0;

        // Get the current month and year
        const year = currentDate.year();
        const month = currentDate.month() + 1; // JavaScript months are 0-indexed
        const cacheKey = getCacheKey(year, month);

        // First update the calendar with empty data to prevent blank state
        updateCalendar();

        // Add loading indicator to the calendar
        const loadingIndicator = document.createElement('div');
        loadingIndicator.id = 'calendar-loading';
        loadingIndicator.innerHTML = '<div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span></div><div class="mt-2">Memuat ketersediaan tanggal...</div>';
        loadingIndicator.style.cssText = 'position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255,255,255,0.7); display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 100;';
        
        if (elements.calendarContainer) {
            elements.calendarContainer.style.position = 'relative';
            elements.calendarContainer.appendChild(loadingIndicator);
        }

        // Setup safety timeout to prevent stuck loading
        setupCalendarSafetyTimeout();

        try {
            // Try to get data from cache first
            const cachedData = getFromCache(cacheKey);

            if (cachedData) {
                console.log('[DatePicker] loadMonthAvailability: Using cached availability data for', currentDate.format('YYYY-MM'));
                // Use cached data
                availableDates = new Set(cachedData.available_dates);
                unavailableDates = new Set(cachedData.unavailable_dates);

                // Update the calendar with the cached data
                updateCalendar();

                // If there are no available dates in this month and we should check next month
                if (cachedData.available_dates.length === 0 && checkNextMonthIfNeeded && !checkingNextMonth) {
                    console.log('[DatePicker] loadMonthAvailability: No available dates in cached data for current month, checking next month.');
                    // Always remove loading indicator before moving to next month
                    const loadingIndicator = document.getElementById('calendar-loading');
                    if (loadingIndicator) {
                        loadingIndicator.remove();
                    }

                     // Advance to next month
                     goToNextAvailableMonth();
                     return; // Stop execution here, as goToNextAvailableMonth will handle loading
                 }
             } else {
                 console.log('[DatePicker] loadMonthAvailability: No cached availability data, fetching from server for', currentDate.format('YYYY-MM'));
                 // Fetch fresh data from server with retry mechanism
                await fetchMonthAvailability(year, month, checkNextMonthIfNeeded);
            }
        } catch (error) {
            console.error('[DatePicker] loadMonthAvailability: Error loading availability data for', currentDate.format('YYYY-MM'), error);
            // Even if there's an error, update the calendar with whatever data we have
            updateCalendar();
        } finally {
            // Always remove loading indicator and reset loading state
            const loadingIndicator = document.getElementById('calendar-loading');
            if (loadingIndicator) {
                loadingIndicator.remove();
             }
             isLoadingCalendar = false;
             // Only finalize readiness and check quota if we are NOT currently switching months
             if (!checkingNextMonth) {
                 console.log('[DatePicker] loadMonthAvailability: Finalizing. isCalendarDataReady set to true.');
                 isCalendarDataReady = true; // Mark calendar data as ready ONLY when not switching months
                 // Trigger quota check if pending or date selected
                 console.log(`[DatePicker] loadMonthAvailability: Checking if quota check needed. Pending: ${initialQuotaCheckPending}, Date selected: ${!!elements.dateInput.value}`);
                 if (initialQuotaCheckPending || elements.dateInput.value) {
                     checkQuotaInternal();
                 }
             } else {
                 console.log('[DatePicker] loadMonthAvailability: Finalizing, but currently checking next month. Readiness flags not updated yet.');
             }
         }
     }

    // Helper function to fetch month availability with optimized retry mechanism
    async function fetchMonthAvailability(year, month, checkNextMonthIfNeeded, maxRetries = 2) {
        const cacheKey = getCacheKey(year, month);
        console.log(`[DatePicker] fetchMonthAvailability: Fetching for ${year}-${month}, Attempt: ${retryAttempt + 1}`);
        try {
            const response = await fetch(`/get-date-availability/${year}/${month}`);
            const data = await response.json();

            if (data.success) {
                console.log(`[DatePicker] fetchMonthAvailability: Successfully fetched data for ${year}-${month}. Available: ${data.available_dates.length}, Unavailable: ${data.unavailable_dates.length}`);
                // Clear existing sets
                availableDates = new Set(data.available_dates || []);
                unavailableDates = new Set(data.unavailable_dates || []);

                // Save valid data to cache
                saveToCache(cacheKey, {
                    available_dates: data.available_dates,
                    unavailable_dates: data.unavailable_dates
                });

                // If there are no available dates in this month and we should check next month
                if (data.available_dates.length === 0 && checkNextMonthIfNeeded && !checkingNextMonth) {
                    console.log(`[DatePicker] fetchMonthAvailability: No available dates found for ${year}-${month}, checking next month.`);
                    // Clear loading indicator before changing month
                    const loadingIndicator = document.getElementById('calendar-loading');
                    if (loadingIndicator) loadingIndicator.remove();
                    
                    // Advance to next month
                    goToNextAvailableMonth();
                    return;
                }

                // Update calendar with the loaded data
                updateCalendar();
            } else {
                console.error(`[DatePicker] fetchMonthAvailability: Server indicated failure for ${year}-${month}:`, data.message);
                throw new Error(data.message || 'Failed to load date availability');
            }
        } catch (error) {
            console.error(`[DatePicker] fetchMonthAvailability: Error fetching data for ${year}-${month}, Attempt: ${retryAttempt + 1}`, error);
            if (retryAttempt < maxRetries) {
                retryAttempt++;
                // Implement exponential backoff for retries
                const backoffTime = retryAttempt * 500;
                await new Promise(resolve => setTimeout(resolve, backoffTime));
                await fetchMonthAvailability(year, month, checkNextMonthIfNeeded, maxRetries);
            } else {
                console.error(`[DatePicker] fetchMonthAvailability: Max retries reached for ${year}-${month}. Updating calendar with potentially empty data.`);
                // Update calendar even if we failed to get data after all retries
                updateCalendar();
            }
        }
    }

    // This function will check and advance to the next month with available slots
    async function goToNextAvailableMonth(monthsToCheck = 3) {
        if (checkingNextMonth) return;
        console.log('[DatePicker] goToNextAvailableMonth: Starting search for next available month.');
        checkingNextMonth = true;

        try {
            let foundAvailableMonth = false; // Flag to track if we found one
            for (let i = 0; i < monthsToCheck; i++) {
                // Move to next month
                currentDate = currentDate.clone().add(1, 'month');
                const year = currentDate.year();
                const month = currentDate.month() + 1; // JavaScript months are 0-indexed

                // Try to get data from cache first
                const cacheKey = getCacheKey(year, month);
                let cachedData = getFromCache(cacheKey);

                // If not in cache, fetch it
                if (!cachedData) {
                    try {
                        const response = await fetch(`/get-date-availability/${year}/${month}`);
                        const data = await response.json();

                        if (data.success) {
                            cachedData = {
                                available_dates: data.available_dates,
                                unavailable_dates: data.unavailable_dates
                            };

                            saveToCache(cacheKey, cachedData);
                        }
                    } catch (error) {
                        continue; // Skip to next month if this one fails
                    }
                }

                // If we have available dates in this month, load it and stop
                if (cachedData && cachedData.available_dates && cachedData.available_dates.length > 0) {
                    console.log(`[DatePicker] goToNextAvailableMonth: Found available dates in ${year}-${month}. Loading this month.`);
                    foundAvailableMonth = true;
                    break; // Exit loop
                } else {
                    console.log(`[DatePicker] goToNextAvailableMonth: No available dates found in ${year}-${month}. Checking next.`);
                }
            }
            // If we finished the loop and didn't find an available month
            if (!foundAvailableMonth) {
                console.log('[DatePicker] goToNextAvailableMonth: No available month found within check range. Loading last checked month:', currentDate.format('YYYY-MM'));
            }
            // Update UI to show this month first
            updateCalendar();
            // Reset flags before calling loadMonthAvailability again
            checkingNextMonth = false;
            isLoadingCalendar = false;
            // Load this month's data properly, setting isCalendarDataReady in its finally block
            loadMonthAvailability(false); // Load the final month's data
        } catch (error) {
            console.error('[DatePicker] goToNextAvailableMonth: Error during search:', error);
            checkingNextMonth = false; // Ensure flag is reset on error
            isLoadingCalendar = false; // Reset loading state
            updateCalendar(); // Update with current (potentially last checked) month
        }
    }

    // Event Listeners
    document.getElementById('prevMonth').addEventListener('click', () => {
        console.log('[DatePicker] prevMonth clicked.');
        currentDate = currentDate.clone().subtract(1, 'month');
        // Load availability data for the new month without auto-advancing
        loadMonthAvailability(false);
    });

    document.getElementById('nextMonth').addEventListener('click', () => {
        console.log('[DatePicker] nextMonth clicked.');
        currentDate = currentDate.clone().add(1, 'month');
        // Load availability data for the new month without auto-advancing
        loadMonthAvailability(false);
    });

    // Listen for the custom event from Blade when time slots are rendered
    document.addEventListener('timeSlotsRendered', function() {
        console.log('[DatePicker] timeSlotsRendered event received. Setting isTimeSlotsReady to true.');
        isTimeSlotsReady = true;
        // Trigger quota check if it was pending due to slots not being ready
        console.log(`[DatePicker] timeSlotsRendered: Checking if quota check needed. Pending: ${initialQuotaCheckPending}`);
        if (initialQuotaCheckPending) {
            checkQuotaInternal();
        }
    });

    // Initialize UI elements once
    addCalendarStyles();
    addRefreshButton();

    // Initialize calendar (with a short delay to make sure DOM is ready)
    setTimeout(() => {
        console.log('[DatePicker] Initializing calendar load.');
        loadMonthAvailability(); // Initial load, allow checking next month if needed
    }, 100);

    // If a date was pre-selected (e.g., from form validation error), ensure selectedDate is set
    if (elements.dateInput.value) {
        console.log('[DatePicker] Pre-selected date found:', elements.dateInput.value);
        selectedDate = moment(elements.dateInput.value).tz('Asia/Jakarta');
        // No need to call selectDate here, just ensure the state is correct
        formValidationState.hasDate = true;
        console.log('[DatePicker] Initial form state based on pre-selected date:', formValidationState);
    }

    // Initial check for submit button state based on pre-filled values
    // Check if a time was pre-selected and is valid
    const preSelectedTimeInput = document.querySelector('input[name="visit_time"]:checked');
    if (preSelectedTimeInput && !preSelectedTimeInput.disabled) {
        formValidationState.hasAvailableTimeSlot = true;
    }
    updateSubmitButtonState(); // Update button state on initial load

    // Add event listener for time slot changes using event delegation
    if (elements.timeSlotContainer) {
        elements.timeSlotContainer.addEventListener('change', function(event) {
            if (event.target.type === 'radio' && event.target.name === 'visit_time') {
                console.log('[DatePicker] Time slot selection changed:', event.target.value, 'Enabled:', !event.target.disabled);
                formValidationState.hasAvailableTimeSlot = !event.target.disabled;
                console.log('[DatePicker] Form state updated after time change:', formValidationState);
                updateSubmitButtonState();
            }
        });
    }
});
