/**
 * Enhanced Parks Search and Filter Management
 * Provides comprehensive UX improvements for the parks listing page
 */

class ParkSearchManager {
    constructor() {
        this.debounceTimers = new Map();
        this.filterState = new Map();
        this.requestCount = 0;
        this.lastRequestTime = 0;
        
        this.init();
    }
    
    init() {
        this.setupEventListeners();
        this.initializeLazyLoading();
        this.setupKeyboardNavigation();
        this.restoreFilterState();
        this.setupPerformanceOptimizations();
    }
    
    setupEventListeners() {
        // Enhanced HTMX request handling
        document.addEventListener('htmx:configRequest', (evt) => this.handleConfigRequest(evt));
        document.addEventListener('htmx:beforeRequest', (evt) => this.handleBeforeRequest(evt));
        document.addEventListener('htmx:afterRequest', (evt) => this.handleAfterRequest(evt));
        document.addEventListener('htmx:responseError', (evt) => this.handleResponseError(evt));
        document.addEventListener('htmx:historyRestore', (evt) => this.handleHistoryRestore(evt));
        document.addEventListener('htmx:afterSwap', (evt) => this.handleAfterSwap(evt));
        
        // Enhanced form interactions
        document.addEventListener('input', (evt) => this.handleInput(evt));
        document.addEventListener('change', (evt) => this.handleChange(evt));
        document.addEventListener('focus', (evt) => this.handleFocus(evt));
        document.addEventListener('blur', (evt) => this.handleBlur(evt));
        
        // Search suggestions
        document.addEventListener('keydown', (evt) => this.handleKeydown(evt));
        
        // Window events
        window.addEventListener('beforeunload', () => this.saveFilterState());
        window.addEventListener('resize', this.debounce(() => this.handleResize(), 250));
    }
    
    handleConfigRequest(evt) {
        // Preserve view mode
        const parkResults = document.getElementById('park-results');
        if (parkResults) {
            const viewMode = parkResults.getAttribute('data-view-mode');
            if (viewMode) {
                evt.detail.parameters['view_mode'] = viewMode;
            }
        }

        // Preserve search terms
        const searchInput = document.querySelector('input[name="search"]');
        if (searchInput && searchInput.value) {
            evt.detail.parameters['search'] = searchInput.value;
        }
        
        // Add request tracking
        evt.detail.parameters['_req_id'] = ++this.requestCount;
        this.lastRequestTime = Date.now();
    }
    
    handleBeforeRequest(evt) {
        const target = evt.detail.target;
        if (target) {
            target.classList.add('htmx-requesting');
            this.showLoadingIndicator(target);
        }
        
        // Disable form elements during request
        this.toggleFormElements(false);
        
        // Track request analytics
        this.trackFilterUsage(evt);
    }
    
    handleAfterRequest(evt) {
        const target = evt.detail.target;
        if (target) {
            target.classList.remove('htmx-requesting');
            this.hideLoadingIndicator(target);
        }
        
        // Re-enable form elements
        this.toggleFormElements(true);
        
        // Handle response timing
        const responseTime = Date.now() - this.lastRequestTime;
        if (responseTime > 3000) {
            this.showPerformanceWarning();
        }
    }
    
    handleResponseError(evt) {
        this.hideLoadingIndicator(evt.detail.target);
        this.toggleFormElements(true);
        this.showErrorMessage('Failed to load results. Please try again.');
    }
    
    handleAfterSwap(evt) {
        if (evt.detail.target.id === 'results-container') {
            this.initializeLazyLoading(evt.detail.target);
            this.updateResultsInfo(evt.detail.target);
            this.animateResults(evt.detail.target);
        }
    }
    
    handleHistoryRestore(evt) {
        const parkResults = document.getElementById('park-results');
        if (parkResults && evt.detail.path) {
            const url = new URL(evt.detail.path, window.location.origin);
            const viewMode = url.searchParams.get('view_mode');
            if (viewMode) {
                parkResults.setAttribute('data-view-mode', viewMode);
            }
        }
        
        // Restore filter state from URL
        this.restoreFiltersFromURL(evt.detail.path);
    }
    
    handleInput(evt) {
        if (evt.target.type === 'search' || evt.target.type === 'text') {
            this.debounceInput(evt.target);
        }
    }
    
    handleChange(evt) {
        if (evt.target.closest('#filter-form')) {
            this.updateFilterState();
            this.saveFilterState();
        }
    }
    
    handleFocus(evt) {
        if (evt.target.type === 'search') {
            this.highlightSearchSuggestions(evt.target);
        }
    }
    
    handleBlur(evt) {
        if (evt.target.type === 'search') {
            // Delay hiding suggestions to allow for clicks
            setTimeout(() => this.hideSearchSuggestions(), 150);
        }
    }
    
    handleKeydown(evt) {
        if (evt.target.type === 'search') {
            this.handleSearchKeyboard(evt);
        }
    }
    
    handleResize() {
        // Responsive adjustments
        this.adjustLayoutForViewport();
    }
    
    debounceInput(input) {
        const key = input.name || input.id;
        if (this.debounceTimers.has(key)) {
            clearTimeout(this.debounceTimers.get(key));
        }
        
        const delay = input.type === 'search' ? 300 : 500;
        const timer = setTimeout(() => {
            if (input.form) {
                htmx.trigger(input.form, 'change');
            }
            this.debounceTimers.delete(key);
        }, delay);
        
        this.debounceTimers.set(key, timer);
    }
    
    handleSearchKeyboard(evt) {
        const suggestions = document.getElementById('search-results');
        if (!suggestions) return;
        
        const items = suggestions.querySelectorAll('[role="option"]');
        let activeIndex = Array.from(items).findIndex(item =>
            item.classList.contains('active') || item.classList.contains('highlighted')
        );
        
        switch (evt.key) {
            case 'ArrowDown':
                evt.preventDefault();
                activeIndex = Math.min(activeIndex + 1, items.length - 1);
                this.highlightSuggestion(items, activeIndex);
                break;
                
            case 'ArrowUp':
                evt.preventDefault();
                activeIndex = Math.max(activeIndex - 1, -1);
                this.highlightSuggestion(items, activeIndex);
                break;
                
            case 'Enter':
                if (activeIndex >= 0 && items[activeIndex]) {
                    evt.preventDefault();
                    items[activeIndex].click();
                }
                break;
                
            case 'Escape':
                this.hideSearchSuggestions();
                evt.target.blur();
                break;
        }
    }
    
    highlightSuggestion(items, activeIndex) {
        items.forEach((item, index) => {
            item.classList.toggle('active', index === activeIndex);
            item.classList.toggle('highlighted', index === activeIndex);
        });
    }
    
    highlightSearchSuggestions(input) {
        const suggestions = document.getElementById('search-results');
        if (suggestions && input.value) {
            suggestions.style.display = 'block';
        }
    }
    
    hideSearchSuggestions() {
        const suggestions = document.getElementById('search-results');
        if (suggestions) {
            suggestions.style.display = 'none';
        }
    }
    
    initializeLazyLoading(container = document) {
        if (!('IntersectionObserver' in window)) return;

        const imageObserver = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    const img = entry.target;
                    if (img.dataset.src) {
                        img.src = img.dataset.src;
                        img.removeAttribute('data-src');
                        img.classList.add('loaded');
                        imageObserver.unobserve(img);
                    }
                }
            });
        }, {
            threshold: 0.1,
            rootMargin: '50px'
        });

        container.querySelectorAll('img[data-src]').forEach(img => {
            imageObserver.observe(img);
        });
    }
    
    setupKeyboardNavigation() {
        // Tab navigation for filter cards
        document.addEventListener('keydown', (evt) => {
            if (evt.key === 'Tab' && evt.target.closest('.park-card')) {
                this.handleCardNavigation(evt);
            }
        });
    }
    
    setupPerformanceOptimizations() {
        // Prefetch next page if pagination exists
        this.setupPrefetching();
        
        // Optimize scroll performance
        this.setupScrollOptimization();
    }
    
    setupPrefetching() {
        const nextPageLink = document.querySelector('a[rel="next"]');
        if (nextPageLink && 'IntersectionObserver' in window) {
            const observer = new IntersectionObserver((entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        this.prefetchPage(nextPageLink.href);
                        observer.unobserve(entry.target);
                    }
                });
            });
            
            const trigger = document.querySelector('.pagination');
            if (trigger) {
                observer.observe(trigger);
            }
        }
    }
    
    setupScrollOptimization() {
        let ticking = false;
        
        window.addEventListener('scroll', () => {
            if (!ticking) {
                requestAnimationFrame(() => {
                    this.handleScroll();
                    ticking = false;
                });
                ticking = true;
            }
        });
    }
    
    handleScroll() {
        // Show/hide back to top button
        const backToTop = document.getElementById('back-to-top');
        if (backToTop) {
            backToTop.style.display = window.scrollY > 500 ? 'block' : 'none';
        }
    }
    
    prefetchPage(url) {
        const link = document.createElement('link');
        link.rel = 'prefetch';
        link.href = url;
        document.head.appendChild(link);
    }
    
    showLoadingIndicator(target) {
        // Add subtle loading animation
        target.style.transition = 'opacity 0.3s ease-in-out';
        target.style.opacity = '0.7';
    }
    
    hideLoadingIndicator(target) {
        target.style.opacity = '1';
    }
    
    toggleFormElements(enabled) {
        const form = document.getElementById('filter-form');
        if (form) {
            const elements = form.querySelectorAll('input, select, button');
            elements.forEach(el => {
                el.disabled = !enabled;
            });
        }
    }
    
    updateFilterState() {
        const form = document.getElementById('filter-form');
        if (!form) return;
        
        const formData = new FormData(form);
        this.filterState.clear();
        
        for (const [key, value] of formData.entries()) {
            if (value && value !== '') {
                this.filterState.set(key, value);
            }
        }
    }
    
    saveFilterState() {
        try {
            const state = Object.fromEntries(this.filterState);
            localStorage.setItem('parkFilters', JSON.stringify(state));
        } catch (e) {
            console.warn('Failed to save filter state:', e);
        }
    }
    
    restoreFilterState() {
        try {
            const saved = localStorage.getItem('parkFilters');
            if (saved) {
                const state = JSON.parse(saved);
                this.applyFilterState(state);
            }
        } catch (e) {
            console.warn('Failed to restore filter state:', e);
        }
    }
    
    restoreFiltersFromURL(path) {
        const url = new URL(path, window.location.origin);
        const params = new URLSearchParams(url.search);
        
        const form = document.getElementById('filter-form');
        if (!form) return;
        
        // Clear existing values
        form.reset();
        
        // Apply URL parameters
        for (const [key, value] of params.entries()) {
            const input = form.querySelector(`[name="${key}"]`);
            if (input) {
                if (input.type === 'checkbox') {
                    input.checked = value === 'on' || value === 'true';
                } else {
                    input.value = value;
                }
            }
        }
    }
    
    applyFilterState(state) {
        const form = document.getElementById('filter-form');
        if (!form) return;
        
        Object.entries(state).forEach(([key, value]) => {
            const input = form.querySelector(`[name="${key}"]`);
            if (input) {
                if (input.type === 'checkbox') {
                    input.checked = value === 'on' || value === 'true';
                } else {
                    input.value = value;
                }
            }
        });
    }
    
    updateResultsInfo(container) {
        // Update any result count displays
        const countElements = container.querySelectorAll('[data-result-count]');
        countElements.forEach(el => {
            const count = container.querySelectorAll('.park-card').length;
            el.textContent = count;
        });
    }
    
    animateResults(container) {
        // Subtle animation for new results
        const cards = container.querySelectorAll('.park-card');
        cards.forEach((card, index) => {
            card.style.opacity = '0';
            card.style.transform = 'translateY(20px)';
            
            setTimeout(() => {
                card.style.transition = 'opacity 0.3s ease-out, transform 0.3s ease-out';
                card.style.opacity = '1';
                card.style.transform = 'translateY(0)';
            }, index * 50);
        });
    }
    
    adjustLayoutForViewport() {
        const viewport = window.innerWidth;
        
        // Adjust grid columns based on viewport
        const grid = document.querySelector('.park-card-grid');
        if (grid) {
            if (viewport < 768) {
                grid.style.gridTemplateColumns = '1fr';
            } else if (viewport < 1024) {
                grid.style.gridTemplateColumns = 'repeat(2, 1fr)';
            } else {
                grid.style.gridTemplateColumns = 'repeat(3, 1fr)';
            }
        }
    }
    
    trackFilterUsage(evt) {
        // Track which filters are being used for analytics
        if (window.gtag) {
            const formData = new FormData(evt.detail.elt);
            const activeFilters = [];
            
            for (const [key, value] of formData.entries()) {
                if (value && value !== '' && key !== 'csrfmiddlewaretoken') {
                    activeFilters.push(key);
                }
            }
            
            window.gtag('event', 'filter_usage', {
                'filters_used': activeFilters.join(','),
                'filter_count': activeFilters.length
            });
        }
    }
    
    showPerformanceWarning() {
        // Show a subtle warning for slow responses
        const warning = document.createElement('div');
        warning.className = 'fixed top-4 right-4 bg-yellow-100 border border-yellow-400 text-yellow-700 px-4 py-3 rounded z-50';
        warning.innerHTML = `
            <span class="block sm:inline">Search is taking longer than expected...</span>
            <span class="absolute top-0 bottom-0 right-0 px-4 py-3 cursor-pointer" onclick="this.parentElement.remove()">
                <svg class="fill-current h-6 w-6 text-yellow-500" role="button" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
                    <path d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"/>
                </svg>
            </span>
        `;
        
        document.body.appendChild(warning);
        
        setTimeout(() => {
            if (warning.parentElement) {
                warning.remove();
            }
        }, 5000);
    }
    
    showErrorMessage(message) {
        // Show error message with retry option
        const errorDiv = document.createElement('div');
        errorDiv.className = 'fixed top-4 right-4 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded z-50';
        errorDiv.innerHTML = `
            <span class="block sm:inline">${message}</span>
            <button class="ml-4 bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-2 rounded text-sm" onclick="location.reload()">
                Retry
            </button>
            <span class="absolute top-0 bottom-0 right-0 px-4 py-3 cursor-pointer" onclick="this.parentElement.remove()">
                <svg class="fill-current h-6 w-6 text-red-500" role="button" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
                    <path d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"/>
                </svg>
            </span>
        `;
        
        document.body.appendChild(errorDiv);
        
        setTimeout(() => {
            if (errorDiv.parentElement) {
                errorDiv.remove();
            }
        }, 10000);
    }
    
    // Utility method for debouncing
    debounce(func, wait) {
        let timeout;
        return function executedFunction(...args) {
            const later = () => {
                clearTimeout(timeout);
                func(...args);
            };
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    }
}

// Initialize the enhanced search manager
document.addEventListener('DOMContentLoaded', () => {
    window.parkSearchManager = new ParkSearchManager();
});

// Export for potential module usage
if (typeof module !== 'undefined' && module.exports) {
    module.exports = ParkSearchManager;
}