/**
 * Boundary Display Handler
 *
 * This script adds functionality to display geographical boundaries on the map
 * when a region is selected from the dropdown menus.
 */

class BoundaryDisplay {
    constructor(options = {}) {
        // Map reference
        this.map = options.map || null;

        // GeoSelector reference
        this.geoSelector = options.geoSelector || null;

        // Boundary layer
        this.boundaryLayer = null;

        // Selection elements
        this.selects = {
            country: document.getElementById('country_id'),
            province: document.getElementById('province_id'),
            county: document.getElementById('county_id'),
            district: document.getElementById('district_id'),
            city: document.getElementById('city_id'),
            village: document.getElementById('village_id'),
            zone: document.getElementById('zone_id')
        };

        // Currently displayed region type and ID
        this.currentRegion = {
            type: null,
            id: null
        };

        if (this.map) {
            this.setupEventListeners();
        } else {
            console.warn('Map reference not provided for BoundaryDisplay - boundary display is disabled');
        }
    }

    setupEventListeners() {
        // Add change event listeners to all select elements
        Object.entries(this.selects).forEach(([type, select]) => {
            if (select) {
                select.addEventListener('change', (e) => this.handleSelectChange(type, e.target.value));
            }
        });
    }

    handleSelectChange(regionType, regionId) {
        console.log(`Region selection changed: ${regionType} = ${regionId}`);

        if (regionId) {
            // Update the current region information
            this.currentRegion = {
                type: regionType,
                id: regionId
            };

            // Fetch and display the boundary
            this.fetchAndDisplayBoundary(regionType, regionId);
        } else if (regionType === this.currentRegion.type) {
            // If the region that was cleared was the currently displayed one
            this.clearBoundary();

            // Find the highest level region that is still selected
            const regionTypes = ['zone', 'village', 'city', 'district', 'county', 'province', 'country'];
            for (const type of regionTypes) {
                if (this.selects[type] && this.selects[type].value) {
                    this.currentRegion = {
                        type: type,
                        id: this.selects[type].value
                    };
                    this.fetchAndDisplayBoundary(type, this.selects[type].value);
                    break;
                }
            }
        }
    }

    async fetchAndDisplayBoundary(regionType, regionId) {
        if (!this.map) {
            console.warn('Map not initialized, cannot fetch and display boundary');
            return;
        }

        try {
            console.log(`Fetching boundary for ${regionType} ID: ${regionId}`);

            // Clear any existing boundary
            this.clearBoundary();

            // Try the admin API endpoint first
            let response = await fetch(`/admin/api/boundaries/${regionType}/${regionId}`);

            // If admin API fails, try the public API
            if (!response.ok) {
                console.log('Admin API failed, trying public API');
                response = await fetch(`/api/boundaries/${regionType}/${regionId}`);

                if (!response.ok) {
                    console.warn(`Failed to fetch boundary data for ${regionType} ID: ${regionId} - Status: ${response.statusText}`);
                    return;
                }
            }

            const data = await response.json();

            if (!data.boundaries) {
                console.info(`No boundary data available for ${regionType} ID: ${regionId} - This is normal for some regions`);
                return;
            }

            // Parse the GeoJSON from the boundaries column
            let geoJSON;
            try {
                // If boundaries is already a GeoJSON object, use it directly
                if (typeof data.boundaries === 'object') {
                    geoJSON = data.boundaries;
                } else {
                    // Otherwise, try to parse it from a string
                    geoJSON = JSON.parse(data.boundaries);
                }

                if (!geoJSON || (Array.isArray(geoJSON) && geoJSON.length === 0)) {
                    console.info(`Empty GeoJSON data for ${regionType} ID: ${regionId}`);
                    return;
                }
            } catch (error) {
                console.warn(`Failed to parse GeoJSON data for ${regionType} ID: ${regionId}: ${error.message}`);
                return;
            }

            // Create a GeoJSON layer with the boundary data
            this.boundaryLayer = L.geoJSON(geoJSON, {
                style: {
                    color: '#ff0000',     // Red border
                    weight: 2,            // Border width
                    opacity: 0.8,         // Opacity of border
                    fillColor: '#ff0000', // Fill color
                    fillOpacity: 0.1      // Fill opacity
                }
            }).addTo(this.map);

            // Fit the map to the boundary bounds
            this.map.fitBounds(this.boundaryLayer.getBounds());

        } catch (error) {
            console.warn(`Error displaying boundary for ${regionType} ID: ${regionId}: ${error.message}`);
        }
    }

    clearBoundary() {
        if (this.map && this.boundaryLayer) {
            this.map.removeLayer(this.boundaryLayer);
            this.boundaryLayer = null;
        }
    }
}

// Initialize when the DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
    // بررسی اینکه آیا BoundaryDisplay کلاس موجود است یا خیر
    if (typeof BoundaryDisplay === 'undefined') {
        console.warn('[BoundaryDisplay] BoundaryDisplay class not found, skipping initialization');
        return;
    }

    // بررسی اینکه آیا صفحه نیاز به boundary display دارد یا خیر
    const needsBoundaryDisplay = document.querySelector('#map') ||
                                 document.querySelector('.map-container') ||
                                 document.querySelector('[data-boundary-display]') ||
                                 document.querySelector('.leaflet-container');

    if (!needsBoundaryDisplay) {
        console.log('[BoundaryDisplay] No map container found, skipping boundary display initialization');
        return;
    }

    console.log('[BoundaryDisplay] Initializing boundary display...');

    // Using a more robust approach with multiple attempts and a global observer
    let attempts = 0;
    const maxAttempts = 5;
    const timeoutMs = 1000;
    let observer = null;

    // Setup a MutationObserver to watch for map creation
    try {
        observer = new MutationObserver((mutations) => {
            for (const mutation of mutations) {
                if (mutation.type === 'childList' && mutation.addedNodes.length) {
                    // Check if map was created
                    if (window.map || window.mapSelector?.map || window.iranHeatmap) {
                        console.log('[BoundaryDisplay] Map detected by observer, initializing boundary display');
                        initBoundaryDisplay(true);
                        if (observer) {
                            observer.disconnect(); // Stop observing once we've found a map
                            observer = null;
                        }
                        return;
                    }
                }
            }
        });

        // Start observing the document body
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    } catch (error) {
        console.error('[BoundaryDisplay] Error setting up MutationObserver:', error);
    }

    function initBoundaryDisplay(fromObserver = false) {
        if (!fromObserver) {
            attempts++;
            console.log(`[BoundaryDisplay] Attempt ${attempts} to initialize boundary display...`);
        }

        try {
            // Check if any map is available
            if (window.map) {
                window.boundaryDisplay = new BoundaryDisplay({
                    map: window.map
                });
                console.log('[BoundaryDisplay] Boundary display initialized with map');
                if (observer) {
                    observer.disconnect();
                    observer = null;
                }
                return true;
            } else if (window.mapSelector && window.mapSelector.map) {
                window.boundaryDisplay = new BoundaryDisplay({
                    map: window.mapSelector.map,
                    geoSelector: window.geoSelector
                });
                console.log('[BoundaryDisplay] Boundary display initialized with mapSelector');
                if (observer) {
                    observer.disconnect();
                    observer = null;
                }
                return true;
            } else if (window.iranHeatmap) {
                // Try to use the heatmap if available
                window.boundaryDisplay = new BoundaryDisplay({
                    map: window.iranHeatmap
                });
                console.log('[BoundaryDisplay] Boundary display initialized with iranHeatmap');
                if (observer) {
                    observer.disconnect();
                    observer = null;
                }
                return true;
            } else {
                if (attempts < maxAttempts) {
                    console.log(`[BoundaryDisplay] Map not available yet, will try again in ${timeoutMs}ms (attempt ${attempts}/${maxAttempts})`);
                    setTimeout(initBoundaryDisplay, timeoutMs);
                } else {
                    console.warn('[BoundaryDisplay] Map initialization timeout, stopping attempts');
                    // Stop the observer to prevent memory leaks
                    if (observer) {
                        observer.disconnect();
                        observer = null;
                    }
                }
                return false;
            }
        } catch (error) {
            console.error('[BoundaryDisplay] Error during initialization:', error);
            if (observer) {
                observer.disconnect();
                observer = null;
            }
            return false;
        }
    }

    // Also listen for custom map creation events
    window.addEventListener('mapCreated', () => {
        console.log('[BoundaryDisplay] Map created event detected, initializing boundary display');
        initBoundaryDisplay(true);
    });

    // Start the initialization process with a short delay
    setTimeout(() => {
        try {
            initBoundaryDisplay();
        } catch (error) {
            console.error('[BoundaryDisplay] Error starting initialization:', error);
        }
    }, 500);
});