'use client';

import { useEffect, useRef } from 'react';
import type { Map as LeafletMap, Marker } from 'leaflet';

interface Props {
  lat: number;
  lng: number;
  height?: number;
  onMove?: (coords: { lat: number; lng: number }) => void;
  /** Sólo mostrar la ubicación (detalle de un pedido): marcador fijo y sin buscador. */
  readOnly?: boolean;
}

export default function GeoMap({ lat, lng, height = 220, onMove, readOnly = false }: Props) {
  const containerRef = useRef<HTMLDivElement>(null);
  const mapRef = useRef<LeafletMap | null>(null);
  const markerRef = useRef<Marker | null>(null);
  // Store onMove in a ref so the event closure always uses the latest version
  const onMoveRef = useRef(onMove);
  useEffect(() => { onMoveRef.current = onMove; }, [onMove]);

  useEffect(() => {
    if (!containerRef.current || mapRef.current) return;

    let L: typeof import('leaflet');

    const init = async () => {
      L = (await import('leaflet')).default;

      // Fix default marker icons (webpack/Next.js strips them)
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      delete (L.Icon.Default.prototype as any)._getIconUrl;
      L.Icon.Default.mergeOptions({
        iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',
        iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',
        shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',
      });

      const map = L.map(containerRef.current!, { zoomControl: true, attributionControl: false }).setView([lat, lng], 16);
      mapRef.current = map;

      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19 }).addTo(map);

      const marker = L.marker([lat, lng], { draggable: !readOnly }).addTo(map);
      markerRef.current = marker;
      if (readOnly) return;

      marker.on('dragend', () => {
        const pos = marker.getLatLng();
        onMoveRef.current?.({ lat: pos.lat, lng: pos.lng });
      });

      // Search control via leaflet-geosearch
      const { GeoSearchControl, OpenStreetMapProvider } = await import('leaflet-geosearch');

      const provider = new OpenStreetMapProvider({
        params: { countrycodes: 'py', addressdetails: 1 },
      });

      const searchControl = GeoSearchControl({
        provider,
        style: 'bar',
        showMarker: false,
        showPopup: false,
        autoClose: true,
        retainZoomLevel: false,
        animateZoom: true,
        keepResult: true,
        searchLabel: 'Buscar dirección...',
      });

      map.addControl(searchControl);

      // When a result is selected, move the draggable marker there
      map.on('geosearch/showlocation', (result: unknown) => {
        const { location } = result as { location: { x: number; y: number } };
        const latlng = { lat: location.y, lng: location.x };
        marker.setLatLng([latlng.lat, latlng.lng]);
        map.setView([latlng.lat, latlng.lng], 17);
        onMoveRef.current?.(latlng);
      });
    };

    init();

    return () => {
      mapRef.current?.remove();
      mapRef.current = null;
      markerRef.current = null;
    };
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Keep marker in sync if lat/lng change externally (e.g. initial geo detection)
  useEffect(() => {
    if (!mapRef.current || !markerRef.current) return;
    markerRef.current.setLatLng([lat, lng]);
    mapRef.current.setView([lat, lng], mapRef.current.getZoom());
  }, [lat, lng]);

  return (
    <div
      ref={containerRef}
      style={{
        width: '100%',
        height,
        borderRadius: 12,
        overflow: 'hidden',
        border: '1px solid rgba(20,33,31,0.12)',
        boxShadow: '0 4px 14px rgba(15,23,42,0.08)',
      }}
    />
  );
}
