/**
 * Member Minder Pro Calendar JavaScript
 * Handles calendar initialization and event management for the Member Minder Pro WordPress plugin.
 */

(function($) {
    'use strict';

    // Calendar class to handle all calendar-related functionality
    class MMProCalendar {
        constructor() {
            this.calendarEl = document.querySelector('.mmpro-calendar__container');
            this.colorKeyEl = document.querySelector('.mmpro-calendar__color-key');
            this.config = window.mmproCalendarConfig || {};
            this.calendar = null;
            this.waitAttempts = undefined;
        }

        /**
         * Initialize the calendar
         */
        init() {
            if (!this.calendarEl) {
                console.error('Calendar element not found');
                return;
            }

            // Wait for FullCalendar to be fully loaded
            this.waitForFullCalendar();
        }

        /**
         * Wait for FullCalendar and its plugins to be loaded
         */
        waitForFullCalendar() {
            let attempts = 0;
            let interval = setInterval(() => {
                if (typeof FullCalendar !== "undefined" && FullCalendar.Calendar) {
                    console.log("FullCalendar loaded successfully!");
                    clearInterval(interval);
                    this.initializeCalendar();
                    this.loadEventCategories();
                } else {
                    attempts++;
                    console.log(`Waiting for FullCalendar to load... Attempt: ${attempts}`);
                    if (attempts > 20) {
                        clearInterval(interval);
                        console.error("FullCalendar failed to load after multiple attempts");
                        console.log("FullCalendar initialization status:", {
                            fullCalendar: typeof FullCalendar !== "undefined" ? FullCalendar : "undefined",
                            windowFullCalendar: window.FullCalendar,
                            hasCalendarClass: typeof FullCalendar !== "undefined" ? Boolean(FullCalendar.Calendar) : false
                        });
                        $(this.calendarEl).append('<div class="alert alert-danger">Failed to initialize calendar: FullCalendar library not loaded</div>');
                    }
                }
            }, 300); // Check every 300ms
        }
        

        /**
         * Check if the device is mobile
         */
        isMobile() {
            return window.matchMedia('only screen and (max-width: 760px)').matches;
        }

        /**
         * Initialize the FullCalendar instance
         */
        initializeCalendar() {
            try {
                this.calendar = new FullCalendar.Calendar(this.calendarEl, {
                    initialView: this.isMobile() ? 'listMonth' : this.config.initialView,
                    headerToolbar: {
                        left: 'prev,next today',
                        center: 'title',
                        right: this.config.views
                    },
                    views: {
                        dayGridMonth: { buttonText: 'Month' },
                        listMonth: { 
                            buttonText: 'List',
                            duration: { months: 1 }
                        }
                    },
                    timeZone: 'UTC',
                    themeSystem: 'standard',
                    height: 'auto',
                    navLinks: true,
                    editable: false,
                    selectable: true,
                    dayMaxEvents: false,
                    eventDisplay: 'block',
                    events: this.fetchEvents.bind(this),
                    eventDidMount: this.handleEventMount.bind(this),
                    eventWillUnmount: this.handleEventUnmount.bind(this), // Add this line for cleanup
                    loading: this.handleLoading.bind(this),
                    eventClick: this.handleEventClick.bind(this),
                    windowResize: this.handleWindowResize.bind(this)
                });

                this.calendar.render();
            } catch (error) {
                console.error('Error initializing calendar:', error);
                $(this.calendarEl).append('<div class="alert alert-danger">Error initializing calendar: ' + error.message + '</div>');
            }
        }

        /**
         * Fetch events from the server
         */
        async fetchEvents(fetchInfo, successCallback, failureCallback) {
            try {
                const params = new URLSearchParams({
                    baseUrl: this.config.eventBaseUrl,
                    start: fetchInfo.startStr,
                    end: fetchInfo.endStr,
                    AccountID: this.config.accountId,
                    ClubID: this.config.clubId,
                    EventCategoryIDs: this.config.eventCategoryIds
                });

                const response = await fetch(`${this.config.eventUrl}?${params.toString()}`);
                if (!response.ok) {
                    throw new Error('Network response was not ok');
                }

                const data = await response.json();
                successCallback(data);
            } catch (error) {
                console.error('Error fetching events:', error);
                failureCallback(error);
                $(this.calendarEl).append('<div class="alert alert-danger">Error loading calendar events</div>');
            }
        }

        /**
         * Handle event clicks - open in colorbox on desktop, direct link on mobile
         */
        handleEventClick(info) {
            info.jsEvent.preventDefault();
            
            if (this.isMobile()) {
                // On mobile, navigate directly to the event URL
                window.location.href = info.event.url;
            } else {
                // On desktop, open in colorbox
                if (typeof jQuery !== 'undefined' && typeof jQuery.colorbox !== 'undefined') {
                    try {
                        jQuery(info.el).colorbox({
                            href: info.event.url,
                            iframe: true,
                            width: "90%",
                            height: "90%",
                            fastIframe: false,
                            onComplete: function() {
                                // Only trigger resize for responsive behavior
                                jQuery(window).trigger('resize');
                            },
                            onError: function() {
                                console.error('ColorBox failed to load content');
                                window.location.href = info.event.url;
                            }
                        });
                    } catch (error) {
                        console.error('Error opening ColorBox:', error);
                        window.location.href = info.event.url;
                    }
                } else {
                    console.error('ColorBox not initialized. Falling back to direct link.');
                    window.location.href = info.event.url;
                }
            }
        }

        /**
         * Handle window resize - update calendar view for mobile/desktop
         */
        handleWindowResize() {
            const isMobileView = this.isMobile();
            const currentView = this.calendar.view.type;
            
            // Switch view based on screen size if needed
            if (isMobileView && currentView === 'dayGridMonth') {
                this.calendar.changeView('listMonth');
            } else if (!isMobileView && currentView === 'listMonth' && this.config.initialView === 'dayGridMonth') {
                this.calendar.changeView('dayGridMonth');
            }
        }

        /**
         * Handle event mounting - add tooltips and enhance event display
         */
        handleEventMount(info) {
            // Use requestAnimationFrame to ensure the element is painted
            requestAnimationFrame(() => {
                const eventElement = info.el;
                const eventData = info.event;

                // --- Tooltip Logic ---
                try {
                    // 1. Basic Checks: Library loaded? Element still exists?
                    if (typeof Tooltip === 'undefined') return;
                    if (!eventElement || !eventElement.isConnected || !document.body.contains(eventElement)) {
                        // console.warn('Tooltip target element invalid or detached:', eventElement);
                        return;
                    }

                    // 2. Validate Title: Ensure it's a non-empty string
                    const tooltipTitle = eventData.title ? String(eventData.title).trim() : '';
                    if (!tooltipTitle) {
                        // console.log('Skipping tooltip due to empty title for event:', eventData.id);
                        return;
                    }

                    // 3. Cleanup Previous Instance (Crucial)
                    if (eventElement._tooltip && typeof eventElement._tooltip.dispose === 'function') {
                        try {
                            // console.log('Disposing existing tooltip before creating new one for:', eventElement);
                            eventElement._tooltip.dispose();
                        } catch (disposeError) {
                            console.warn('Error disposing previous tooltip:', disposeError);
                        }
                        eventElement._tooltip = null;
                    }

                    // 4. Create Tooltip Instance (Simplified for Debugging)
                    let tooltipInstance = null;
                    try {
                        // console.log('Attempting to create tooltip for:', eventElement, 'Title:', tooltipTitle);
                        tooltipInstance = new Tooltip(eventElement, {
                            title: tooltipTitle,
                            placement: 'top',
                            trigger: 'hover focus', // Standard triggers
                            container: 'body',    // Append to body: Most stable, avoids issues with FC removing/recreating parent elements. Might affect scoped CSS.
                            boundary: 'window',   // Keep within viewport. 'clippingParents' can be complex.
                            // Use default template for now to rule out template issues
                        });
                        // console.log('Tooltip instance created:', tooltipInstance);

                    } catch (creationError) {
                        console.error('!!! Error during Tooltip constructor !!!', creationError, {
                            element: eventElement,
                            title: tooltipTitle
                        });
                        return; // Don't proceed if constructor fails
                    }

                    // 5. Store reference for cleanup
                    if (tooltipInstance) {
                        eventElement._tooltip = tooltipInstance;
                    } else {
                         console.warn('Tooltip instance creation failed silently for:', eventElement);
                    }

                    // --- Optional: Add visual indicator ---
                    // (Keep existing code for the dot indicator if needed)
                    if (eventData.extendedProps && eventData.extendedProps.description) {
                        if (!eventElement.querySelector('.mmpro-calendar__event-dot')) {
                            const dotEl = document.createElement('span');
                            dotEl.className = 'mmpro-calendar__event-dot';
                            const titleContainer = eventElement.querySelector('.fc-event-title');
                            if (titleContainer) {
                                titleContainer.appendChild(dotEl);
                            } else {
                                eventElement.appendChild(dotEl);
                            }
                        }
                    }

                } catch (mountError) {
                    console.error('Error within handleEventMount logic:', mountError, {
                        event: eventData,
                        element: eventElement
                    });
                }
            });
        }

        // Ensure handleEventUnmount is still present and correctly configured
        /**
         * Handle event unmounting - clean up tooltips
         */
        handleEventUnmount(info) {
             const eventElement = info.el;
             if (eventElement && eventElement._tooltip && typeof eventElement._tooltip.dispose === 'function') {
                 try {
                     // console.log('Disposing tooltip on unmount for:', eventElement);
                     eventElement._tooltip.dispose();
                 } catch (disposeError) {
                     console.warn('Error disposing tooltip on unmount:', disposeError);
                 }
                 eventElement._tooltip = null; // Clear reference
             }
        }

        /**
         * Handle loading state
         */
        handleLoading(isLoading) {
            const loadingIndicator = $(this.calendarEl).find('.loading-indicator');
            if (isLoading) {
                if (!loadingIndicator.length) {
                    $(this.calendarEl).append('<div class="loading-indicator">Loading events...</div>');
                }
            } else {
                loadingIndicator.remove();
            }
        }

        /**
         * Load and display event categories
         */
        async loadEventCategories() {
            if (!this.colorKeyEl) return;

            try {
                const params = new URLSearchParams({
                    baseUrl: this.config.categoryBaseUrl,
                    D: this.config.accountId
                });

                const response = await fetch(`${this.config.eventCategoryUrl}?${params.toString()}`);
                if (!response.ok) {
                    throw new Error('Network response was not ok');
                }

                const data = await response.json();
                this.renderColorKey(data);
            } catch (error) {
                console.error('Error loading event categories:', error);
            }
        }

        /**
         * Render the color key
         */
        renderColorKey(categories) {
            if (!Array.isArray(categories)) {
                console.error('Invalid category data');
                return;
            }

            const html = categories.reduce((acc, category) => {
                if (category.BGCOLOR && category.EVENTCATEGORY) {
                    return acc + `
                        <div class="mmpro-calendar__color-key-item">
                            <span class="mmpro-calendar__color-box" style="background-color: ${category.BGCOLOR};">
                                ${category.EVENTCATEGORY.trim()}
                            </span>
                        </div>`;
                }
                return acc;
            }, '<div class="mmpro-calendar__color-key-container">') + '</div>';

            this.colorKeyEl.innerHTML = html;
        }
    }

    // Initialize calendar when DOM is ready
    $(document).ready(() => {
        const calendar = new MMProCalendar();
        calendar.init();
    });

})(jQuery);