/**
 * ThrillWiki Map Filters - Location Filtering Component
 * 
 * This module handles filter panel interactions and updates maps via HTMX
 * Supports location type filtering, geographic filtering, and real-time search
 */

class MapFilters {
    constructor(formId, options = {}) {
        this.formId = formId;
        this.options = {
            autoSubmit: true,
            searchDelay: 500,
            enableLocalStorage: true,
            storageKey: 'thrillwiki_map_filters',
            mapInstance: null,
            htmxTarget: '#map-container',
            htmxUrl: null,
            ...options
        };
        
        this.form = null;
        this.searchTimeout = null;
        this.currentFilters = {};
        this.filterChips = [];
        
        this.init();
    }
    
    /**
     * Initialize the filter component
     */
    init() {
        this.form = document.getElementById(this.formId);
        if (!this.form) {
            console.error(`Filter form with ID '${this.formId}' not found`);
            return;
        }
        
        this.setupFilterChips();
        this.bindEvents();
        this.loadSavedFilters();
        this.initializeFilters();
    }
    
    /**
     * Setup filter chip interactions
     */
    setupFilterChips() {
        this.filterChips = this.form.querySelectorAll('.filter-chip, .filter-pill');
        
        this.filterChips.forEach(chip => {
            const checkbox = chip.querySelector('input[type="checkbox"]');
            
            if (checkbox) {
                // Set initial state
                this.updateChipState(chip, checkbox.checked);
                
                // Bind click handler
                chip.addEventListener('click', (e) => {
                    e.preventDefault();
                    this.toggleChip(chip, checkbox);
                });
            }
        });
    }
    
    /**
     * Toggle filter chip state
     */
    toggleChip(chip, checkbox) {
        checkbox.checked = !checkbox.checked;
        this.updateChipState(chip, checkbox.checked);
        
        // Trigger change event
        this.handleFilterChange();
    }
    
    /**
     * Update visual state of filter chip
     */
    updateChipState(chip, isActive) {
        if (isActive) {
            chip.classList.add('active');
            chip.classList.remove('inactive');
        } else {
            chip.classList.remove('active');
            chip.classList.add('inactive');
        }
    }
    
    /**
     * Bind event handlers
     */
    bindEvents() {
        // Form submission
        this.form.addEventListener('submit', (e) => {
            if (this.options.autoSubmit) {
                e.preventDefault();
                this.submitFilters();
            }
        });
        
        // Input changes (excluding search)
        this.form.addEventListener('change', (e) => {
            if (e.target.name !== 'q' && !e.target.closest('.no-auto-submit')) {
                this.handleFilterChange();
            }
        });
        
        // Search input with debouncing
        const searchInput = this.form.querySelector('input[name="q"]');
        if (searchInput) {
            searchInput.addEventListener('input', () => {
                this.handleSearchInput();
            });
        }
        
        // Range inputs
        const rangeInputs = this.form.querySelectorAll('input[type="range"]');
        rangeInputs.forEach(input => {
            input.addEventListener('input', (e) => {
                this.updateRangeDisplay(e.target);
            });
        });
        
        // Clear filters button
        const clearButton = this.form.querySelector('[data-action="clear-filters"]');
        if (clearButton) {
            clearButton.addEventListener('click', (e) => {
                e.preventDefault();
                this.clearAllFilters();
            });
        }
        
        // HTMX events
        if (typeof htmx !== 'undefined') {
            this.form.addEventListener('htmx:beforeRequest', () => {
                this.showLoadingState(true);
            });
            
            this.form.addEventListener('htmx:afterRequest', (e) => {
                this.showLoadingState(false);
                if (e.detail.successful) {
                    this.onFiltersApplied(this.getCurrentFilters());
                }
            });
            
            this.form.addEventListener('htmx:responseError', (e) => {
                this.showLoadingState(false);
                this.handleError(e.detail);
            });
        }
    }
    
    /**
     * Handle search input with debouncing
     */
    handleSearchInput() {
        clearTimeout(this.searchTimeout);
        this.searchTimeout = setTimeout(() => {
            this.handleFilterChange();
        }, this.options.searchDelay);
    }
    
    /**
     * Handle filter changes
     */
    handleFilterChange() {
        const filters = this.getCurrentFilters();
        this.currentFilters = filters;
        
        if (this.options.autoSubmit) {
            this.submitFilters();
        }
        
        // Save filters to localStorage
        if (this.options.enableLocalStorage) {
            this.saveFilters(filters);
        }
        
        // Update map if connected
        if (this.options.mapInstance && this.options.mapInstance.updateFilters) {
            this.options.mapInstance.updateFilters(filters);
        }
        
        // Trigger custom event
        this.triggerFilterEvent('filterChange', filters);
    }
    
    /**
     * Submit filters via HTMX or form submission
     */
    submitFilters() {
        if (typeof htmx !== 'undefined' && this.options.htmxUrl) {
            // Use HTMX
            const formData = new FormData(this.form);
            const params = new URLSearchParams(formData);
            
            htmx.ajax('GET', `${this.options.htmxUrl}?${params}`, {
                target: this.options.htmxTarget,
                swap: 'none'
            });
        } else {
            // Regular form submission
            this.form.submit();
        }
    }
    
    /**
     * Get current filter values
     */
    getCurrentFilters() {
        const formData = new FormData(this.form);
        const filters = {};
        
        for (let [key, value] of formData.entries()) {
            if (value.trim() === '') continue;
            
            if (filters[key]) {
                if (Array.isArray(filters[key])) {
                    filters[key].push(value);
                } else {
                    filters[key] = [filters[key], value];
                }
            } else {
                filters[key] = value;
            }
        }
        
        return filters;
    }
    
    /**
     * Set filter values
     */
    setFilters(filters) {
        Object.entries(filters).forEach(([key, value]) => {
            const elements = this.form.querySelectorAll(`[name="${key}"]`);
            
            elements.forEach(element => {
                if (element.type === 'checkbox' || element.type === 'radio') {
                    if (Array.isArray(value)) {
                        element.checked = value.includes(element.value);
                    } else {
                        element.checked = element.value === value;
                    }
                    
                    // Update chip state if applicable
                    const chip = element.closest('.filter-chip, .filter-pill');
                    if (chip) {
                        this.updateChipState(chip, element.checked);
                    }
                } else {
                    element.value = Array.isArray(value) ? value[0] : value;
                    
                    // Update range display if applicable
                    if (element.type === 'range') {
                        this.updateRangeDisplay(element);
                    }
                }
            });
        });
        
        this.currentFilters = filters;
    }
    
    /**
     * Clear all filters
     */
    clearAllFilters() {
        // Reset form
        this.form.reset();
        
        // Update all chip states
        this.filterChips.forEach(chip => {
            const checkbox = chip.querySelector('input[type="checkbox"]');
            if (checkbox) {
                this.updateChipState(chip, false);
            }
        });
        
        // Update range displays
        const rangeInputs = this.form.querySelectorAll('input[type="range"]');
        rangeInputs.forEach(input => {
            this.updateRangeDisplay(input);
        });
        
        // Clear saved filters
        if (this.options.enableLocalStorage) {
            localStorage.removeItem(this.options.storageKey);
        }
        
        // Submit cleared filters
        this.handleFilterChange();
    }
    
    /**
     * Update range input display
     */
    updateRangeDisplay(rangeInput) {
        const valueDisplay = document.getElementById(`${rangeInput.id}-value`) ||
                           document.getElementById(`${rangeInput.name}-value`);
        
        if (valueDisplay) {
            valueDisplay.textContent = rangeInput.value;
        }
    }
    
    /**
     * Load saved filters from localStorage
     */
    loadSavedFilters() {
        if (!this.options.enableLocalStorage) return;
        
        try {
            const saved = localStorage.getItem(this.options.storageKey);
            if (saved) {
                const filters = JSON.parse(saved);
                this.setFilters(filters);
            }
        } catch (error) {
            console.warn('Failed to load saved filters:', error);
        }
    }
    
    /**
     * Save filters to localStorage
     */
    saveFilters(filters) {
        if (!this.options.enableLocalStorage) return;
        
        try {
            localStorage.setItem(this.options.storageKey, JSON.stringify(filters));
        } catch (error) {
            console.warn('Failed to save filters:', error);
        }
    }
    
    /**
     * Initialize filters from URL parameters or defaults
     */
    initializeFilters() {
        // Check for URL parameters
        const urlParams = new URLSearchParams(window.location.search);
        const urlFilters = {};
        
        for (let [key, value] of urlParams.entries()) {
            if (urlFilters[key]) {
                if (Array.isArray(urlFilters[key])) {
                    urlFilters[key].push(value);
                } else {
                    urlFilters[key] = [urlFilters[key], value];
                }
            } else {
                urlFilters[key] = value;
            }
        }
        
        if (Object.keys(urlFilters).length > 0) {
            this.setFilters(urlFilters);
        }
        
        // Emit initial filter state
        this.triggerFilterEvent('filterInit', this.getCurrentFilters());
    }
    
    /**
     * Show/hide loading state
     */
    showLoadingState(show) {
        const loadingIndicators = this.form.querySelectorAll('.filter-loading, .htmx-indicator');
        loadingIndicators.forEach(indicator => {
            indicator.style.display = show ? 'block' : 'none';
        });
        
        // Disable form during loading
        const inputs = this.form.querySelectorAll('input, select, button');
        inputs.forEach(input => {
            input.disabled = show;
        });
    }
    
    /**
     * Handle errors
     */
    handleError(detail) {
        console.error('Filter request failed:', detail);
        
        // Show user-friendly error message
        this.showMessage('Failed to apply filters. Please try again.', 'error');
    }
    
    /**
     * Show message to user
     */
    showMessage(message, type = 'info') {
        // Create or update message element
        let messageEl = this.form.querySelector('.filter-message');
        if (!messageEl) {
            messageEl = document.createElement('div');
            messageEl.className = 'filter-message';
            this.form.insertBefore(messageEl, this.form.firstChild);
        }
        
        messageEl.textContent = message;
        messageEl.className = `filter-message filter-message-${type}`;
        
        // Auto-hide after delay
        setTimeout(() => {
            if (messageEl.parentNode) {
                messageEl.remove();
            }
        }, 5000);
    }
    
    /**
     * Callback for when filters are successfully applied
     */
    onFiltersApplied(filters) {
        this.triggerFilterEvent('filterApplied', filters);
    }
    
    /**
     * Trigger custom events
     */
    triggerFilterEvent(eventName, data) {
        const event = new CustomEvent(eventName, {
            detail: data
        });
        this.form.dispatchEvent(event);
    }
    
    /**
     * Connect to a map instance
     */
    connectToMap(mapInstance) {
        this.options.mapInstance = mapInstance;
        
        // Listen to map events
        if (mapInstance.on) {
            mapInstance.on('boundsChange', (bounds) => {
                // Could update location-based filters here
            });
        }
    }
    
    /**
     * Export current filters as URL parameters
     */
    getFilterUrl(baseUrl = window.location.pathname) {
        const filters = this.getCurrentFilters();
        const params = new URLSearchParams();
        
        Object.entries(filters).forEach(([key, value]) => {
            if (Array.isArray(value)) {
                value.forEach(v => params.append(key, v));
            } else {
                params.append(key, value);
            }
        });
        
        return params.toString() ? `${baseUrl}?${params}` : baseUrl;
    }
    
    /**
     * Update URL with current filters (without page reload)
     */
    updateUrl() {
        const url = this.getFilterUrl();
        if (window.history && window.history.pushState) {
            window.history.pushState(null, '', url);
        }
    }
    
    /**
     * Get filter summary for display
     */
    getFilterSummary() {
        const filters = this.getCurrentFilters();
        const summary = [];
        
        // Location types
        if (filters.types) {
            const types = Array.isArray(filters.types) ? filters.types : [filters.types];
            summary.push(`Types: ${types.join(', ')}`);
        }
        
        // Geographic filters
        if (filters.country) summary.push(`Country: ${filters.country}`);
        if (filters.state) summary.push(`State: ${filters.state}`);
        if (filters.city) summary.push(`City: ${filters.city}`);
        
        // Search query
        if (filters.q) summary.push(`Search: "${filters.q}"`);
        
        // Radius
        if (filters.radius) summary.push(`Within ${filters.radius} miles`);
        
        return summary.length > 0 ? summary.join(' • ') : 'No filters applied';
    }
    
    /**
     * Reset to default filters
     */
    resetToDefaults() {
        const defaults = {
            types: ['park'],
            cluster: 'true'
        };
        
        this.setFilters(defaults);
        this.handleFilterChange();
    }
    
    /**
     * Destroy the filter component
     */
    destroy() {
        if (this.searchTimeout) {
            clearTimeout(this.searchTimeout);
        }
        
        // Remove event listeners would go here if we stored references
        // For now, rely on garbage collection
    }
}

// Auto-initialize filter forms
document.addEventListener('DOMContentLoaded', function() {
    // Initialize map filters form
    const mapFiltersForm = document.getElementById('map-filters');
    if (mapFiltersForm) {
        window.mapFilters = new MapFilters('map-filters', {
            htmxUrl: mapFiltersForm.getAttribute('hx-get'),
            htmxTarget: mapFiltersForm.getAttribute('hx-target') || '#map-container'
        });
        
        // Connect to map instance if available
        if (window.thrillwikiMap) {
            window.mapFilters.connectToMap(window.thrillwikiMap);
        }
    }
    
    // Initialize other filter forms with data attributes
    const filterForms = document.querySelectorAll('[data-filter-form]');
    filterForms.forEach(form => {
        const options = {};
        
        // Parse data attributes
        Object.keys(form.dataset).forEach(key => {
            if (key.startsWith('filter')) {
                const optionKey = key.replace('filter', '').toLowerCase();
                let value = form.dataset[key];
                
                // Parse boolean values
                if (value === 'true') value = true;
                else if (value === 'false') value = false;
                
                options[optionKey] = value;
            }
        });
        
        new MapFilters(form.id, options);
    });
});

// Export for use in other modules
if (typeof module !== 'undefined' && module.exports) {
    module.exports = MapFilters;
} else {
    window.MapFilters = MapFilters;
}