import L, { LatLngTuple } from 'leaflet';
import 'leaflet/dist/leaflet.css';
import { useEffect, useRef } from 'react';
import { MapContainer, Marker, TileLayer, useMap } from 'react-leaflet';

// Fix for default marker icon issue in Leaflet with webpack/vite
delete (L.Icon.Default.prototype as unknown as { _getIconUrl?: unknown })._getIconUrl;
L.Icon.Default.mergeOptions({
  iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon-2x.png',
  iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon.png',
  shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-shadow.png',
});

interface MapPickerProps {
  value?: { lat: number; lng: number };
  onChange?: (value: { lat: number; lng: number }) => void;
  location?: { lat: number; lng: number };
  onLocationChange?: (value: { lat: number; lng: number }) => void;
}

/**
 * Component to sync map center with value prop and zoom in when location changes
 */
const MapCenterSync = ({ value }: { value: { lat: number; lng: number } }) => {
  const map = useMap();
  const lastValueRef = useRef<{ lat: number; lng: number } | null>(null);

  useEffect(() => {
    // Check if this is a new location (not just initial render)
    const isNewLocation =
      !lastValueRef.current ||
      Math.abs(lastValueRef.current.lat - value.lat) > 0.0001 ||
      Math.abs(lastValueRef.current.lng - value.lng) > 0.0001;

    if (isNewLocation) {
      // Zoom in to a closer level when a place is selected
      const targetZoom = 16; // Closer zoom level for selected location
      map.setView([value.lat, value.lng], targetZoom, { animate: true });
      lastValueRef.current = { lat: value.lat, lng: value.lng };
    }
  }, [map, value.lat, value.lng]);

  return null;
};

const MapPicker = ({ value, onChange, location, onLocationChange }: MapPickerProps) => {
  // Support both prop naming conventions for backward compatibility
  const actualValue = value || location || { lat: 54.5384152, lng: 52.7955953 };
  const actualOnChange = onChange || onLocationChange || (() => {});
  const position: LatLngTuple = [actualValue.lat, actualValue.lng];

  return (
    <div className="h-64 w-full rounded-lg border overflow-hidden relative">
      <MapContainer
        center={position}
        zoom={13}
        scrollWheelZoom={true}
        attributionControl={false}
        className="rounded-lg h-full w-full"
      >
        <MapCenterSync value={actualValue} />

        {/* Optional: Add a tile layer for reference (can be removed if you want blank map) */}
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          opacity={0.3}
        />

        <Marker
          position={position}
          draggable={true}
          eventHandlers={{
            dragend: (e) => {
              const marker = e.target;
              const newPosition = marker.getLatLng();
              actualOnChange({ lat: newPosition.lat, lng: newPosition.lng });
            },
          }}
        />

        {/* Click handler for map */}
        <MapClickHandler onChange={actualOnChange} />
      </MapContainer>
    </div>
  );
};

/**
 * Component to handle map clicks
 */
const MapClickHandler = ({
  onChange,
}: {
  onChange: (value: { lat: number; lng: number }) => void;
}) => {
  const map = useMap();

  useEffect(() => {
    const handleClick = (e: L.LeafletMouseEvent) => {
      onChange({ lat: e.latlng.lat, lng: e.latlng.lng });
    };

    map.on('click', handleClick);
    return () => {
      map.off('click', handleClick);
    };
  }, [map, onChange]);

  return null;
};

export default MapPicker;
