import React, { useEffect, useRef } from 'react';
import { Box } from '@chakra-ui/react';

// Dynamically load Leaflet
let L: any = null;

interface ContactMapProps {
  latitude: number;
  longitude: number;
  zoom?: number;
  address?: string;
  clubName?: string;
  mapStyle?: string;
  height?: number;
  clubPrimaryColor?: string;
  clubSecondaryColor?: string;
}

// Available map styles
export const MAP_STYLES = {
  // Clean & Minimal
  'positron': {
    name: 'Positron (Light)',
    url: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png',
    attribution: '© OpenStreetMap © CartoDB',
    description: 'Clean light map, perfect for overlays'
  },
  'positron-no-labels': {
    name: 'Positron No Labels',
    url: 'https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png',
    attribution: '© OpenStreetMap © CartoDB',
    description: 'Minimal light map without labels'
  },
  
  // Dark Themes
  'dark': {
    name: 'Dark Matter',
    url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',
    attribution: '© OpenStreetMap © CartoDB',
    description: 'Dark theme, great for night mode'
  },
  'dark-no-labels': {
    name: 'Dark No Labels',
    url: 'https://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}{r}.png',
    attribution: '© OpenStreetMap © CartoDB',
    description: 'Dark map without labels'
  },
  
  // Black & White
  'toner': {
    name: 'Toner (B&W)',
    url: 'https://tiles.stadiamaps.com/tiles/stamen_toner/{z}/{x}/{y}{r}.png',
    attribution: '© Stamen Design © OpenStreetMap',
    description: 'High contrast black and white'
  },
  'toner-lite': {
    name: 'Toner Lite (B&W)',
    url: 'https://tiles.stadiamaps.com/tiles/stamen_toner_lite/{z}/{x}/{y}{r}.png',
    attribution: '© Stamen Design © OpenStreetMap',
    description: 'Subtle black and white'
  },
  
  // Colorful Options
  'voyager': {
    name: 'Voyager',
    url: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',
    attribution: '© OpenStreetMap © CartoDB',
    description: 'Balanced colors, good readability'
  },
  'terrain': {
    name: 'Terrain',
    url: 'https://tiles.stadiamaps.com/tiles/stamen_terrain/{z}/{x}/{y}{r}.jpg',
    attribution: '© Stamen Design © OpenStreetMap',
    description: 'Natural terrain visualization'
  },
  'watercolor': {
    name: 'Watercolor',
    url: 'https://tiles.stadiamaps.com/tiles/stamen_watercolor/{z}/{x}/{y}.jpg',
    attribution: '© Stamen Design © OpenStreetMap',
    description: 'Artistic watercolor style'
  },
  
  // Default
  'default': {
    name: 'OpenStreetMap',
    url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
    attribution: '© OpenStreetMap contributors',
    description: 'Standard OpenStreetMap'
  },
  
  // Satellite
  'satellite': {
    name: 'Satellite',
    url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
    attribution: '© Esri',
    description: 'Satellite imagery'
  },
};

const ContactMap: React.FC<ContactMapProps> = ({
  latitude,
  longitude,
  zoom = 15,
  address,
  clubName,
  mapStyle = 'default',
  height = 400,
  clubPrimaryColor,
  clubSecondaryColor,
}) => {
  const mapRef = useRef<HTMLDivElement>(null);
  const mapInstanceRef = useRef<any>(null);
  const tileLayerRef = useRef<any>(null);
  const markerRef = useRef<any>(null);
  const [isLoaded, setIsLoaded] = React.useState(false);
  const [loadError, setLoadError] = React.useState<string | null>(null);

  useEffect(() => {
    // Load Leaflet CSS and JS dynamically
    const loadLeaflet = async () => {
      try {
        // Check if already loaded
        if ((window as any).L) {
          L = (window as any).L;
          setIsLoaded(true);
          return;
        }

        // Load CSS
        if (!document.getElementById('leaflet-css')) {
          const link = document.createElement('link');
          link.id = 'leaflet-css';
          link.rel = 'stylesheet';
          link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';
          link.integrity = 'sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=';
          link.crossOrigin = '';
          document.head.appendChild(link);
        }

        // Load JS
        if (!document.getElementById('leaflet-js')) {
          const script = document.createElement('script');
          script.id = 'leaflet-js';
          script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';
          script.integrity = 'sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=';
          script.crossOrigin = '';
          
          script.onload = () => {
            L = (window as any).L;
            setIsLoaded(true);
          };

          script.onerror = () => {
            setLoadError('Failed to load map library');
          };

          document.head.appendChild(script);
        }
      } catch (error) {
        setLoadError('Error loading map');
      }
    };

    loadLeaflet();
  }, []);

  useEffect(() => {
    if (!isLoaded || !L || !mapRef.current || mapInstanceRef.current) return;

    try {
      // Initialize map
      const map = L.map(mapRef.current, {
        center: [latitude, longitude],
        zoom: zoom,
        scrollWheelZoom: false, // Disable scroll zoom for better UX
      });

      mapInstanceRef.current = map;

      // Initial tile layer
      const { tileUrl, attribution } = (() => {
        let url = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
        let attr = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
        if (mapStyle && MAP_STYLES[mapStyle as keyof typeof MAP_STYLES]) {
          const style = MAP_STYLES[mapStyle as keyof typeof MAP_STYLES];
          url = style.url;
          attr = style.attribution;
        } else if (mapStyle && mapStyle.startsWith('http')) {
          url = mapStyle;
        }
        return { tileUrl: url, attribution: attr };
      })();

      tileLayerRef.current = L.tileLayer(tileUrl, {
        attribution,
        maxZoom: 19,
      }).addTo(map);

      // Create custom marker icon with club colors
      const markerColor = clubPrimaryColor || '#3388ff';
      const customIcon = createCustomMarkerIcon(markerColor, L);

      // Add marker
      markerRef.current = L.marker([latitude, longitude], { icon: customIcon }).addTo(map);

      // Add popup if address is provided
      if (clubName || address) {
        let popupContent = '';
        if (clubName) popupContent += `<b>${clubName}</b><br>`;
        if (address) popupContent += address;
        markerRef.current.bindPopup(popupContent);
      }

      // Enable scroll zoom on click
      map.on('click', () => {
        map.scrollWheelZoom.enable();
      });

      // Disable scroll zoom on mouseout
      map.on('mouseout', () => {
        map.scrollWheelZoom.disable();
      });

      // Invalidate size after initial mount to ensure tiles render fully
      // (use a short delay to let layout settle)
      try {
        setTimeout(() => {
          try { map.invalidateSize(); } catch {}
        }, 150);
      } catch {}

    } catch (error) {
      console.error('Error initializing map:', error);
      setLoadError('Failed to initialize map');
    }

    // Cleanup on unmount
    return () => {
      try {
        if (mapInstanceRef.current) {
          mapInstanceRef.current.remove();
        }
      } finally {
        mapInstanceRef.current = null;
        tileLayerRef.current = null;
        markerRef.current = null;
      }
    };
  }, [isLoaded]);

  // Observe container visibility to invalidate size when it becomes visible (e.g., tabs, accordions)
  useEffect(() => {
    if (!mapRef.current) return;
    const el = mapRef.current;
    const observer = new IntersectionObserver((entries) => {
      const e = entries[0];
      if (e && e.isIntersecting && mapInstanceRef.current) {
        try {
          // Next frame ensures correct layout measurement
          requestAnimationFrame(() => {
            try { mapInstanceRef.current!.invalidateSize(); } catch {}
          });
        } catch {}
      }
    }, { root: null, threshold: 0.1 });
    observer.observe(el);
    return () => observer.disconnect();
  }, [isLoaded]);

  // Observe container resize to keep Leaflet in sync with layout changes
  useEffect(() => {
    if (!mapRef.current || !('ResizeObserver' in window)) return;
    const el = mapRef.current;
    const ro = new ResizeObserver(() => {
      if (!mapInstanceRef.current) return;
      try { mapInstanceRef.current.invalidateSize(); } catch {}
    });
    ro.observe(el);
    return () => ro.disconnect();
  }, [isLoaded]);

  // Update center/zoom and marker when coords/zoom change
  useEffect(() => {
    if (!mapInstanceRef.current || !L) return;
    try {
      const map = mapInstanceRef.current;
      if (typeof latitude === 'number' && typeof longitude === 'number') {
        map.setView([latitude, longitude], typeof zoom === 'number' ? zoom : map.getZoom());
        if (markerRef.current) {
          markerRef.current.setLatLng([latitude, longitude]);
        }
      }
    } catch {}
  }, [latitude, longitude, zoom]);

  // Update map style (tile layer) when mapStyle changes
  useEffect(() => {
    if (!mapInstanceRef.current || !L) return;
    try {
      const map = mapInstanceRef.current;
      // Compute URL and attribution
      let url = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
      let attr = '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
      if (mapStyle && MAP_STYLES[mapStyle as keyof typeof MAP_STYLES]) {
        const style = MAP_STYLES[mapStyle as keyof typeof MAP_STYLES];
        url = style.url;
        attr = style.attribution;
      } else if (mapStyle && mapStyle.startsWith('http')) {
        url = mapStyle;
      }
      if (tileLayerRef.current) {
        map.removeLayer(tileLayerRef.current);
      }
      tileLayerRef.current = L.tileLayer(url, { attribution: attr, maxZoom: 19 }).addTo(map);
    } catch {}
  }, [mapStyle]);

  // Update popup content when clubName/address change
  useEffect(() => {
    try {
      if (markerRef.current) {
        if (clubName || address) {
          let popupContent = '';
          if (clubName) popupContent += `<b>${clubName}</b><br>`;
          if (address) popupContent += address;
          markerRef.current.bindPopup(popupContent);
        } else {
          markerRef.current.unbindPopup();
        }
      }
    } catch {}
  }, [clubName, address]);

  // Helper function to create color filter
  function createColorFilter(color: string): string | null {
    try {
      // Validate and normalize color
      const tempDiv = document.createElement('div');
      tempDiv.style.color = color;
      document.body.appendChild(tempDiv);
      const computedColor = window.getComputedStyle(tempDiv).color;
      document.body.removeChild(tempDiv);
      return computedColor;
    } catch {
      return null;
    }
  }

  // Helper function to create custom marker with club colors
  function createCustomMarkerIcon(color: string, leaflet: any) {
    // Create SVG marker with custom color
    const svgIcon = `
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 36" width="36" height="54">
        <defs>
          <filter id="shadow" x="-50%" y="-50%" width="200%" height="200%">
            <feGaussianBlur in="SourceAlpha" stdDeviation="2"/>
            <feOffset dx="0" dy="2" result="offsetblur"/>
            <feComponentTransfer>
              <feFuncA type="linear" slope="0.3"/>
            </feComponentTransfer>
            <feMerge>
              <feMergeNode/>
              <feMergeNode in="SourceGraphic"/>
            </feMerge>
          </filter>
        </defs>
        <path fill="${color}" stroke="#fff" stroke-width="1.5" filter="url(#shadow)"
              d="M12 0C7.03 0 3 4.03 3 9c0 7.5 9 18 9 18s9-10.5 9-18c0-4.97-4.03-9-9-9z"/>
        <circle cx="12" cy="9" r="3" fill="#fff"/>
      </svg>
    `;
    
    const iconUrl = 'data:image/svg+xml;base64,' + btoa(svgIcon);
    
    return leaflet.icon({
      iconUrl: iconUrl,
      iconSize: [36, 54],
      iconAnchor: [18, 54],
      popupAnchor: [0, -54],
    });
  }

  if (loadError) {
    return (
      <Box
        ref={mapRef}
        w="100%"
        h={`${height}px`}
        bg="gray.100"
        display="flex"
        alignItems="center"
        justifyContent="center"
        borderRadius="md"
      >
        {loadError}
      </Box>
    );
  }

  return (
    <Box
      ref={mapRef}
      w="100%"
      h={`${height}px`}
      borderRadius="md"
      overflow="hidden"
      boxShadow="md"
    />
  );
};

export default ContactMap;
