"use client"

import { useEffect, useRef, useState, useCallback, useMemo } from "react"
import L from "leaflet"
import { debounce, throttle } from "lodash"

// Optimized imports - only import CSS once
import "leaflet/dist/leaflet.css"

// Memoized tile providers configuration
const tileProviders = {
  carto: {
    name: "CartoDB Light",
    url: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
    attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
    mobile: true // Good for mobile
  },
  osm: {
    name: "OpenStreetMap",
    url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
    attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    mobile: true
  },
  cartoDark: {
    name: "CartoDB Dark",
    url: "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
    attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors © <a href="https://carto.com/attributions">CARTO</a>',
    mobile: true
  }
} as const

// Optimized property interface
interface Property {
  id: number
  coordinates: [number, number]
  price: number
  type: string
  bedrooms: number
  bathrooms: number
  sqft: number
  address: string
  status: 'active' | 'pending' | 'sold'
}

interface OptimizedLeafletMapProps {
  properties: Property[]
  onPropertySelect: (property: Property | null) => void
  selectedProperty: Property | null
  className?: string
}

// Memoized currency formatter
const formatCurrency = (() => {
  const formatter = new Intl.NumberFormat('en-CA', {
    style: 'currency',
    currency: 'CAD',
    minimumFractionDigits: 0,
    maximumFractionDigits: 0,
    notation: 'compact' // Use compact notation on mobile
  })
  return (value: number, compact = false) => {
    if (compact && value >= 1000000) {
      return formatter.format(value).replace('CAD', '').replace('$', '$').trim()
    }
    return formatter.format(value).replace('CAD', '').replace('$', '$').trim()
  }
})()

// Optimized marker colors
const markerColors = {
  active: '#10B981',
  pending: '#F59E0B', 
  sold: '#EF4444'
} as const

export default function OptimizedLeafletMap({ 
  properties, 
  onPropertySelect, 
  selectedProperty,
  className = ""
}: OptimizedLeafletMapProps) {
  const mapRef = useRef<L.Map | null>(null)
  const mapContainerRef = useRef<HTMLDivElement>(null)
  const markersRef = useRef<L.Marker[]>([])
  const tileLayerRef = useRef<L.TileLayer | null>(null)
  const markerClusterRef = useRef<L.MarkerClusterGroup | null>(null)
  
  const [currentTileProvider, setCurrentTileProvider] = useState<keyof typeof tileProviders>('carto')
  const [isMobile, setIsMobile] = useState(false)
  const [mapReady, setMapReady] = useState(false)

  // Detect mobile device
  useEffect(() => {
    const checkMobile = () => {
      setIsMobile(window.innerWidth < 768 || 'ontouchstart' in window)
    }
    checkMobile()
    
    const debouncedResize = debounce(checkMobile, 150)
    window.addEventListener('resize', debouncedResize)
    return () => window.removeEventListener('resize', debouncedResize)
  }, [])

  // Memoized icon creation with mobile optimizations
  const createOptimizedIcon = useCallback((property: Property, isSelected = false) => {
    const color = markerColors[property.status] || '#3B82F6'
    const priceText = formatCurrency(property.price, isMobile)
    const scale = isMobile ? 0.9 : 1
    const fontSize = isMobile ? '11px' : '12px'
    
    return L.divIcon({
      html: `
        <div style="
          background: ${color};
          color: white;
          padding: ${isMobile ? '3px 6px' : '4px 8px'};
          border-radius: ${isMobile ? '8px' : '12px'};
          font-size: ${fontSize};
          font-weight: 600;
          text-align: center;
          box-shadow: 0 2px 4px rgba(0,0,0,0.2);
          white-space: nowrap;
          border: 2px solid white;
          transform: scale(${isSelected ? scale * 1.1 : scale});
          transition: transform 0.2s ease;
          cursor: pointer;
        ">
          ${priceText}
        </div>
      `,
      className: 'custom-property-marker',
      iconSize: isMobile ? [100, 24] : [120, 30],
      iconAnchor: isMobile ? [50, 24] : [60, 30]
    })
  }, [isMobile])

  // Throttled property selection handler
  const handlePropertyClick = useCallback(
    throttle((property: Property) => {
      onPropertySelect(property)
      if (mapRef.current) {
        mapRef.current.setView(property.coordinates, isMobile ? 14 : 12, { 
          animate: true,
          duration: isMobile ? 0.5 : 1 
        })
      }
    }, 300),
    [onPropertySelect, isMobile]
  )

  // Optimized marker management
  const updateMarkers = useCallback(() => {
    if (!mapRef.current || !mapReady) return

    // Clear existing markers efficiently
    markersRef.current.forEach(marker => marker.remove())
    markersRef.current = []

    // Add new markers with batching for performance
    const batch = isMobile ? 10 : 20 // Smaller batches on mobile
    let index = 0

    const addBatch = () => {
      const endIndex = Math.min(index + batch, properties.length)
      
      for (let i = index; i < endIndex; i++) {
        const property = properties[i]
        const isSelected = selectedProperty?.id === property.id
        
        const marker = L.marker(property.coordinates, {
          icon: createOptimizedIcon(property, isSelected),
          // Add riseOnHover for better UX on desktop
          riseOnHover: !isMobile
        }).addTo(mapRef.current!)

        marker.on('click', () => handlePropertyClick(property))
        
        // Add touch events for mobile
        if (isMobile) {
          marker.on('touchstart', (e) => {
            e.originalEvent.preventDefault()
            handlePropertyClick(property)
          })
        }

        markersRef.current.push(marker)
      }
      
      index = endIndex
      
      // Continue with next batch if there are more properties
      if (index < properties.length) {
        requestAnimationFrame(addBatch)
      }
    }

    addBatch()
  }, [properties, selectedProperty, createOptimizedIcon, handlePropertyClick, mapReady, isMobile])

  // Initialize map with mobile optimizations
  useEffect(() => {
    if (!mapContainerRef.current || mapRef.current) return

    // Mobile-optimized map options
    const mapOptions: L.MapOptions = {
      center: [56.1304, -96.0000],
      zoom: isMobile ? 3 : 4,
      zoomControl: !isMobile, // Hide zoom controls on mobile to save space
      attributionControl: !isMobile,
      preferCanvas: true, // Better performance for markers
      // Mobile touch optimizations
      tap: isMobile,
      touchZoom: isMobile,
      bounceAtZoomLimits: false,
      maxBoundsViscosity: isMobile ? 0.1 : 1
    }

    mapRef.current = L.map(mapContainerRef.current, mapOptions)

    // Add mobile-specific controls
    if (isMobile) {
      // Add minimal attribution
      L.control.attribution({
        prefix: false,
        position: 'bottomright'
      }).addTo(mapRef.current)
      
      // Add mobile-friendly zoom control in better position
      L.control.zoom({
        position: 'topright'
      }).addTo(mapRef.current)
    }

    // Add optimized tile layer
    const provider = tileProviders[currentTileProvider]
    tileLayerRef.current = L.tileLayer(provider.url, {
      attribution: provider.attribution,
      subdomains: 'abcd',
      maxZoom: 19,
      // Performance optimizations
      keepBuffer: isMobile ? 1 : 2,
      updateWhenIdle: isMobile,
      updateWhenZooming: !isMobile
    }).addTo(mapRef.current)

    // Performance optimization: defer marker loading slightly
    const timer = setTimeout(() => {
      setMapReady(true)
    }, 100)

    return () => {
      clearTimeout(timer)
      if (mapRef.current) {
        mapRef.current.remove()
        mapRef.current = null
      }
      markersRef.current = []
      setMapReady(false)
    }
  }, [currentTileProvider, isMobile])

  // Update markers when properties or selection changes
  useEffect(() => {
    updateMarkers()
  }, [updateMarkers])

  // Handle tile provider changes efficiently
  const changeTileProvider = useCallback((newProvider: keyof typeof tileProviders) => {
    if (!mapRef.current || !tileLayerRef.current) return

    mapRef.current.removeLayer(tileLayerRef.current)
    
    const provider = tileProviders[newProvider]
    tileLayerRef.current = L.tileLayer(provider.url, {
      attribution: provider.attribution,
      subdomains: 'abcd',
      maxZoom: 19,
      keepBuffer: isMobile ? 1 : 2,
      updateWhenIdle: isMobile,
      updateWhenZooming: !isMobile
    }).addTo(mapRef.current)

    setCurrentTileProvider(newProvider)
  }, [isMobile])

  // Public methods for parent component
  const flyToProperty = useCallback((coordinates: [number, number]) => {
    if (mapRef.current) {
      mapRef.current.setView(coordinates, isMobile ? 14 : 12, { 
        animate: true,
        duration: isMobile ? 0.5 : 1 
      })
    }
  }, [isMobile])

  const resetView = useCallback(() => {
    if (mapRef.current) {
      mapRef.current.setView([56.1304, -96.0000], isMobile ? 3 : 4, { 
        animate: true,
        duration: isMobile ? 0.5 : 1 
      })
    }
  }, [isMobile])

  return (
    <div className={`relative w-full h-full ${className}`}>
      <div 
        ref={mapContainerRef} 
        className="w-full h-full"
        style={{ minHeight: isMobile ? '300px' : '400px' }}
      />
      
      {/* Mobile-optimized style switcher */}
      <div className={`absolute ${isMobile ? 'top-2 right-2' : 'top-4 right-4'} z-[1000]`}>
        <select 
          value={currentTileProvider}
          onChange={(e) => changeTileProvider(e.target.value as keyof typeof tileProviders)}
          className={`
            px-2 py-1 bg-white border border-gray-300 rounded-md shadow-sm 
            text-sm font-medium text-gray-700 hover:bg-gray-50 
            focus:outline-none focus:ring-2 focus:ring-blue-500
            ${isMobile ? 'text-xs' : 'text-sm'}
          `}
          aria-label="Select map style"
        >
          {Object.entries(tileProviders).map(([key, provider]) => (
            <option key={key} value={key}>
              {isMobile ? provider.name.split(' ')[0] : provider.name}
            </option>
          ))}
        </select>
      </div>
      
      {/* Loading indicator */}
      {!mapReady && (
        <div className="absolute inset-0 bg-gray-100 flex items-center justify-center z-[999]">
          <div className="text-center">
            <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mx-auto mb-2"></div>
            <p className="text-sm text-gray-600">Loading map...</p>
          </div>
        </div>
      )}

      <style jsx global>{`
        .custom-property-marker {
          background: transparent !important;
          border: none !important;
        }
        
        /* Mobile-specific map optimizations */
        @media (max-width: 768px) {
          .leaflet-container {
            font-size: 12px;
          }
          
          .leaflet-control-attribution {
            font-size: 10px;
            background: rgba(255, 255, 255, 0.8) !important;
          }
          
          .leaflet-control-zoom a {
            width: 32px !important;
            height: 32px !important;
            line-height: 32px !important;
          }
          
          .custom-property-marker {
            touch-action: manipulation;
          }
        }
      `}</style>
    </div>
  )
}