/**
 * Representatives Map Module
 * Handles map initialization, office location display, and popup cards
 */

// Map state
let representativesMap = null;
let representativeMarkers = [];
let currentPostalCode = null;

// Office location icons
const officeIcons = {
    federal: L.divIcon({
        className: 'office-marker federal',
        html: '<div class="marker-content">🏛️</div>',
        iconSize: [40, 40],
        iconAnchor: [20, 40],
        popupAnchor: [0, -40]
    }),
    provincial: L.divIcon({
        className: 'office-marker provincial',
        html: '<div class="marker-content">🏢</div>',
        iconSize: [40, 40],
        iconAnchor: [20, 40],
        popupAnchor: [0, -40]
    }),
    municipal: L.divIcon({
        className: 'office-marker municipal',
        html: '<div class="marker-content">🏛️</div>',
        iconSize: [40, 40],
        iconAnchor: [20, 40],
        popupAnchor: [0, -40]
    })
};

// Initialize the representatives map
function initializeRepresentativesMap() {
    const mapContainer = document.getElementById('main-map');
    if (!mapContainer) {
        console.warn('Map container not found');
        return;
    }

    // Avoid double initialization
    if (representativesMap) {
        console.log('Map already initialized, invalidating size instead');
        representativesMap.invalidateSize();
        return;
    }

    // Check if Leaflet is available
    if (typeof L === 'undefined') {
        console.error('Leaflet (L) is not defined. Map initialization failed.');
        return;
    }

    // We'll initialize the map even if not visible, then invalidate size when needed

    console.log('Initializing representatives map...');
    
    // Center on Alberta
    representativesMap = L.map('main-map').setView([53.9333, -116.5765], 6);

    // Add tile layer
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
        maxZoom: 19,
        minZoom: 2
    }).addTo(representativesMap);

    // Trigger size invalidation after a brief moment to ensure proper rendering
    setTimeout(() => {
        if (representativesMap) {
            representativesMap.invalidateSize();
        }
    }, 200);
}

// Clear all representative markers from the map
function clearRepresentativeMarkers() {
    representativeMarkers.forEach(marker => {
        representativesMap.removeLayer(marker);
    });
    representativeMarkers = [];
}

// Add representative offices to the map
function displayRepresentativeOffices(representatives, postalCode) {
    // Initialize map if not already done
    if (!representativesMap) {
        console.log('Map not initialized, initializing now...');
        initializeRepresentativesMap();
    }
    
    if (!representativesMap) {
        console.error('Failed to initialize map');
        return;
    }

    clearRepresentativeMarkers();
    currentPostalCode = postalCode;

    const validOffices = [];
    let bounds = [];

    console.log('Processing representatives for map display:', representatives.length);

    // Group representatives by office location to handle shared addresses
    const locationGroups = new Map();
    
    representatives.forEach((rep, index) => {
        console.log(`Processing representative ${index + 1}:`, rep.name, rep.representative_set_name);
        
        // Try to get office location from various sources
        const offices = getOfficeLocations(rep);
        console.log(`Found ${offices.length} offices for ${rep.name}:`, offices);
        
        offices.forEach((office, officeIndex) => {
            console.log(`Office ${officeIndex + 1} for ${rep.name}:`, office);
            
            if (office.lat && office.lng) {
                const locationKey = `${office.lat.toFixed(6)},${office.lng.toFixed(6)}`;
                
                if (!locationGroups.has(locationKey)) {
                    locationGroups.set(locationKey, {
                        lat: office.lat,
                        lng: office.lng,
                        address: office.address,
                        representatives: [],
                        offices: []
                    });
                }
                
                locationGroups.get(locationKey).representatives.push(rep);
                locationGroups.get(locationKey).offices.push(office);
                
                validOffices.push({ rep, office });
            } else {
                console.log(`No coordinates found for ${rep.name} office:`, office);
            }
        });
    });
    
    // Create markers for each location group
    let offsetIndex = 0;
    locationGroups.forEach((locationGroup, locationKey) => {
        console.log(`Creating markers for location ${locationKey} with ${locationGroup.representatives.length} representatives`);
        
        if (locationGroup.representatives.length === 1) {
            // Single representative at this location
            const rep = locationGroup.representatives[0];
            const office = locationGroup.offices[0];
            const marker = createOfficeMarker(rep, office);
            if (marker) {
                representativeMarkers.push(marker);
                marker.addTo(representativesMap);
                bounds.push([office.lat, office.lng]);
            }
        } else {
            // Multiple representatives at same location - create offset markers
            locationGroup.representatives.forEach((rep, repIndex) => {
                const office = locationGroup.offices[repIndex];
                
                // Add small offset to avoid exact overlap
                const offsetDistance = 0.0005; // About 50 meters
                const angle = (repIndex * 2 * Math.PI) / locationGroup.representatives.length;
                const offsetLat = office.lat + (offsetDistance * Math.cos(angle));
                const offsetLng = office.lng + (offsetDistance * Math.sin(angle));
                
                const offsetOffice = {
                    ...office,
                    lat: offsetLat,
                    lng: offsetLng
                };
                
                console.log(`Creating offset marker for ${rep.name} at ${offsetLat}, ${offsetLng}`);
                const marker = createOfficeMarker(rep, offsetOffice, locationGroup.representatives.length > 1);
                if (marker) {
                    representativeMarkers.push(marker);
                    marker.addTo(representativesMap);
                    bounds.push([offsetLat, offsetLng]);
                }
            });
        }
    });

    console.log(`Total markers created: ${representativeMarkers.length}`);
    console.log(`Bounds array:`, bounds);

    // Fit map to show all offices, or center on Alberta if no offices found
    if (bounds.length > 0) {
        representativesMap.fitBounds(bounds, { padding: [20, 20] });
    } else {
        // If no office locations found, show a message and keep Alberta view
        console.log('No office locations with coordinates found, showing message');
        showMapMessage('Office locations not available for representatives in this area.');
    }

    console.log(`Displayed ${validOffices.length} office locations on map`);
}

// Extract office locations from representative data
function getOfficeLocations(representative) {
    const offices = [];
    
    console.log(`Getting office locations for ${representative.name}`);
    console.log('Representative offices data:', representative.offices);
    
    // Check various sources for office location data
    if (representative.offices && Array.isArray(representative.offices)) {
        representative.offices.forEach((office, index) => {
            console.log(`Processing office ${index + 1}:`, office);
            
            // Use the 'postal' field which contains the address
            if (office.postal || office.address) {
                const officeData = {
                    type: office.type || 'office',
                    address: office.postal || office.address || 'Office Address',
                    postal_code: office.postal_code,
                    phone: office.tel || office.phone,
                    fax: office.fax,
                    lat: office.lat,
                    lng: office.lng
                };
                console.log('Created office data:', officeData);
                offices.push(officeData);
            }
        });
    }

    // For all offices without coordinates, add approximate coordinates
    offices.forEach(office => {
        if (!office.lat || !office.lng) {
            console.log(`Adding coordinates to office for ${representative.name}`);
            const approxLocation = getApproximateLocationByDistrict(representative.district_name, representative.representative_set_name);
            console.log('Approximate location:', approxLocation);
            
            if (approxLocation) {
                office.lat = approxLocation.lat;
                office.lng = approxLocation.lng;
                console.log('Updated office with coordinates:', office);
            }
        }
    });

    // If no offices found at all, create a fallback office
    if (offices.length === 0 && representative.representative_set_name) {
        console.log(`No offices found, creating fallback office for ${representative.name}`);
        const approxLocation = getApproximateLocationByDistrict(representative.district_name, representative.representative_set_name);
        console.log('Approximate location:', approxLocation);
        
        if (approxLocation) {
            const fallbackOffice = {
                type: 'representative',
                address: `${representative.name} - ${representative.district_name || representative.representative_set_name}`,
                lat: approxLocation.lat,
                lng: approxLocation.lng
            };
            console.log('Created fallback office:', fallbackOffice);
            offices.push(fallbackOffice);
        }
    }

    console.log(`Total offices found for ${representative.name}:`, offices.length);
    return offices;
}

// Get approximate location based on district and government level
function getApproximateLocationByDistrict(district, level) {
    // Specific locations for Edmonton officials
    const edmontonLocations = {
        // City Hall for municipal officials
        'Edmonton': { lat: 53.5444, lng: -113.4909 }, // Edmonton City Hall
        "O-day'min": { lat: 53.5444, lng: -113.4909 }, // Edmonton City Hall
        // Provincial Legislature
        'Edmonton-Glenora': { lat: 53.5344, lng: -113.5065 }, // Alberta Legislature
        // Federal offices (approximate downtown Edmonton)
        'Edmonton Centre': { lat: 53.5461, lng: -113.4938 }
    };
    
    // Try specific district first
    if (district && edmontonLocations[district]) {
        return edmontonLocations[district];
    }
    
    // Fallback based on government level
    const levelLocations = {
        'House of Commons': { lat: 53.5461, lng: -113.4938 }, // Downtown Edmonton
        'Legislative Assembly of Alberta': { lat: 53.5344, lng: -113.5065 }, // Alberta Legislature
        'Edmonton City Council': { lat: 53.5444, lng: -113.4909 } // Edmonton City Hall
    };
    
    return levelLocations[level] || { lat: 53.9333, lng: -116.5765 }; // Default to Alberta center
}

// Create a marker for an office location
function createOfficeMarker(representative, office, isSharedLocation = false) {
    if (!office.lat || !office.lng) {
        return null;
    }

    // Determine icon based on government level
    let icon = officeIcons.municipal; // default
    if (representative.representative_set_name) {
        if (representative.representative_set_name.includes('House of Commons')) {
            icon = officeIcons.federal;
        } else if (representative.representative_set_name.includes('Legislative Assembly')) {
            icon = officeIcons.provincial;
        }
    }

    const marker = L.marker([office.lat, office.lng], { icon });
    
    // Create popup content
    const popupContent = createOfficePopupContent(representative, office, isSharedLocation);
    marker.bindPopup(popupContent, {
        maxWidth: 300,
        className: 'office-popup'
    });

    return marker;
}

// Create popup content for office markers
function createOfficePopupContent(representative, office, isSharedLocation = false) {
    const level = getRepresentativeLevel(representative.representative_set_name);
    const levelClass = level.toLowerCase().replace(' ', '-');
    
    return `
        <div class="office-popup-content">
            <div class="rep-header ${levelClass}">
                ${representative.photo_url ? `<img src="${representative.photo_url}" alt="${representative.name}" class="rep-photo-small">` : ''}
                <div class="rep-info">
                    <h4>${representative.name}</h4>
                    <p class="rep-level">${level}</p>
                    <p class="rep-district">${representative.district_name || 'District not specified'}</p>
                    ${isSharedLocation ? '<p class="shared-location-note"><small><em>Note: Office location shared with other representatives</em></small></p>' : ''}
                </div>
            </div>
            
            <div class="office-details">
                <h5>Office Information</h5>
                ${office.address ? `<p><strong>Address:</strong> ${office.address}</p>` : ''}
                ${office.phone ? `<p><strong>Phone:</strong> <a href="tel:${office.phone}">${office.phone}</a></p>` : ''}
                ${office.fax ? `<p><strong>Fax:</strong> ${office.fax}</p>` : ''}
                ${office.postal_code ? `<p><strong>Postal Code:</strong> ${office.postal_code}</p>` : ''}
            </div>
            
            <div class="office-actions">
                ${representative.email ? `<button class="btn btn-primary btn-small email-btn" data-email="${representative.email}" data-name="${representative.name}" data-level="${representative.representative_set_name}">Send Email</button>` : ''}
            </div>
        </div>
    `;
}// Get representative level for display
function getRepresentativeLevel(representativeSetName) {
    if (!representativeSetName) return 'Representative';
    
    if (representativeSetName.includes('House of Commons')) {
        return 'Federal MP';
    } else if (representativeSetName.includes('Legislative Assembly')) {
        return 'Provincial MLA';
    } else {
        return 'Municipal Representative';
    }
}

// Show a message on the map
function showMapMessage(message) {
    const mapContainer = document.getElementById('main-map');
    if (!mapContainer) return;

    // Remove any existing message
    const existingMessage = mapContainer.querySelector('.map-message');
    if (existingMessage) {
        existingMessage.remove();
    }

    // Create and show new message
    const messageDiv = document.createElement('div');
    messageDiv.className = 'map-message';
    messageDiv.innerHTML = `
        <div class="map-message-content">
            <p>${message}</p>
        </div>
    `;
    
    mapContainer.appendChild(messageDiv);
    
    // Remove message after 5 seconds
    setTimeout(() => {
        if (messageDiv.parentNode) {
            messageDiv.remove();
        }
    }, 5000);
}

// Initialize form handlers
function initializePostalForm() {
    const postalForm = document.getElementById('postal-form');

    // Handle postal code form submission
    if (postalForm) {
        postalForm.addEventListener('submit', (event) => {
            event.preventDefault();
            const postalCode = document.getElementById('postal-code').value.trim();
            if (postalCode) {
                handlePostalCodeSubmission(postalCode);
            }
        });
    }

    // Handle email button clicks in popups
    document.addEventListener('click', (event) => {
        if (event.target.classList.contains('email-btn')) {
            event.preventDefault();
            const email = event.target.dataset.email;
            const name = event.target.dataset.name;
            const level = event.target.dataset.level;
            
            if (window.openEmailModal) {
                window.openEmailModal(email, name, level);
            }
        }
    });
}

// Handle postal code submission and fetch representatives
async function handlePostalCodeSubmission(postalCode) {
    try {
        showLoading();
        hideError();

        // Normalize postal code
        const normalizedPostalCode = postalCode.toUpperCase().replace(/\s/g, '');
        
        // Fetch representatives data
        const response = await fetch(`/api/representatives/by-postal/${normalizedPostalCode}`);
        const data = await response.json();

        hideLoading();

        if (data.success && data.data && data.data.representatives) {
            // Display representatives on map
            displayRepresentativeOffices(data.data.representatives, normalizedPostalCode);
            
            // Also update the representatives display section using the existing system
            if (window.representativesDisplay) {
                window.representativesDisplay.displayRepresentatives(data.data.representatives);
            }
            
            // Update location info manually if the existing system doesn't work
            const locationDetails = document.getElementById('location-details');
            if (locationDetails && data.data.location) {
                const location = data.data.location;
                locationDetails.textContent = `${location.city}, ${location.province} (${normalizedPostalCode})`;
            } else if (locationDetails) {
                locationDetails.textContent = `Postal Code: ${normalizedPostalCode}`;
            }
            
            if (window.locationInfo) {
                window.locationInfo.updateLocationInfo(data.data.location, normalizedPostalCode);
            }
            
            // Show the representatives section
            const representativesSection = document.getElementById('representatives-section');
            representativesSection.style.display = 'block';
            
            // Fix map rendering after section becomes visible
            setTimeout(() => {
                if (!representativesMap) {
                    initializeRepresentativesMap();
                }
                if (representativesMap) {
                    representativesMap.invalidateSize();
                    // Try to fit bounds again if we have markers
                    if (representativeMarkers.length > 0) {
                        const bounds = representativeMarkers.map(marker => marker.getLatLng());
                        if (bounds.length > 0) {
                            representativesMap.fitBounds(bounds, { padding: [20, 20] });
                        }
                    }
                }
            }, 300);
            
            // Show refresh button
            const refreshBtn = document.getElementById('refresh-btn');
            if (refreshBtn) {
                refreshBtn.style.display = 'inline-block';
                // Store postal code for refresh functionality
                refreshBtn.dataset.postalCode = normalizedPostalCode;
            }

            // Show success message
            if (window.messageDisplay) {
                window.messageDisplay.show(`Found ${data.data.representatives.length} representatives for ${normalizedPostalCode}`, 'success', 3000);
            }
        } else {
            showError(data.message || 'Unable to find representatives for this postal code.');
        }
    } catch (error) {
        hideLoading();
        console.error('Error fetching representatives:', error);
        showError('An error occurred while looking up representatives. Please try again.');
    }
}

// Utility functions for loading and error states
function showLoading() {
    const loading = document.getElementById('loading');
    if (loading) loading.style.display = 'block';
}

function hideLoading() {
    const loading = document.getElementById('loading');
    if (loading) loading.style.display = 'none';
}

function showError(message) {
    const errorDiv = document.getElementById('error-message');
    if (errorDiv) {
        errorDiv.textContent = message;
        errorDiv.style.display = 'block';
    }
}

function hideError() {
    const errorDiv = document.getElementById('error-message');
    if (errorDiv) {
        errorDiv.style.display = 'none';
    }
}

// Initialize form handlers
function initializePostalForm() {
    const postalForm = document.getElementById('postal-form');
    const refreshBtn = document.getElementById('refresh-btn');

    // Handle postal code form submission
    if (postalForm) {
        postalForm.addEventListener('submit', (event) => {
            event.preventDefault();
            const postalCode = document.getElementById('postal-code').value.trim();
            if (postalCode) {
                handlePostalCodeSubmission(postalCode);
            }
        });
    }
    
    // Handle refresh button
    if (refreshBtn) {
        refreshBtn.addEventListener('click', () => {
            const postalCode = refreshBtn.dataset.postalCode || document.getElementById('postal-code').value.trim();
            if (postalCode) {
                handlePostalCodeSubmission(postalCode);
            }
        });
    }
}

// Initialize everything when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
    initializeRepresentativesMap();
    initializePostalForm();
});

// Global function for opening email modal from map popups
window.openEmailModal = function(email, name, level) {
    if (window.emailComposer) {
        window.emailComposer.openModal({
            email: email,
            name: name,
            level: level
        }, currentPostalCode);
    }
};

// Export functions for use by other modules
window.RepresentativesMap = {
    displayRepresentativeOffices,
    initializeRepresentativesMap,
    clearRepresentativeMarkers,
    handlePostalCodeSubmission
};