'use client';

import React, { useEffect, useState } from 'react';
import { MapContainer, TileLayer, Marker, Popup, useMap, useMapEvents, Polygon } from 'react-leaflet';
import L from 'leaflet';
import { Skeleton } from '@/components/ui/skeleton';
import 'leaflet/dist/leaflet.css';
import './CustomMap.css';
import { ActiveSearchbox } from '../input/ActiveSearchbox';

// Define types for our props
interface ServiceArea {
  type: "Polygon";
  coordinates: number[][][];
}

interface CustomMapProps {
  initialPosition: [number, number];
  zoom?: number;
  markers?: Array<{
    position: [number, number];
    title: string;
    icon?: L.Icon | L.DivIcon;
  }>;
  serviceArea?: ServiceArea | null;
  onPositionSelect?: (position: [number, number]) => void;
  onZoomChange?: (zoom: number) => void;
  onClick?: (event: L.LeafletMouseEvent) => void;
  searchEnabled?: boolean
  markerActive?: boolean
  onMapReady?: (map: L.Map) => void;
}

// Component to handle map events and position updates
function MapEvents({
  onZoomChange,
  onClick,
  center,
  setMapRef,
}: Pick<CustomMapProps, 'onZoomChange' | 'onClick'> & {
  center: [number, number];
  setMapRef: (map: L.Map) => void;
}) {
  const map = useMapEvents({
    zoom: () => {
      onZoomChange?.(map.getZoom());
    },
    click: (e) => {
      onClick?.(e);
    },
  });

  // Update map center when center prop changes
  React.useEffect(() => {
    map.setView(center, map.getZoom(), {
      animate: true,
      duration: 1
    });
  }, [map, center]);

  // Set map reference
  React.useEffect(() => {
    setMapRef(map);
  }, [map, setMapRef]);

  return null;
}

// Component to handle marker updates on zoom
function MarkerUpdater({ markers }: { markers?: CustomMapProps['markers'] }) {
  const map = useMap();

  useEffect(() => {
    // You can implement custom marker scaling or clustering logic here
    const zoom = map.getZoom();
    // Example: Scale markers based on zoom level
    markers?.forEach(marker => {
      const element = document.querySelector(`[title="${marker.title}"]`);
      if (element) {
        const scale = Math.min(1 + (zoom / 20), 1.5);
        (element as HTMLElement).style.transform = `scale(${scale})`;
      }
    });
  }, [map, markers]);

  return null;
}

// Component to auto-open popup for restaurant marker
function MarkerWithAutoOpen({ position, icon, title }: { position: [number, number]; icon?: L.Icon | L.DivIcon; title: string }) {
  const markerRef = React.useRef<L.Marker>(null);

  useEffect(() => {
    if (markerRef.current && title === 'موقعیت رستوران') {
      markerRef.current.openPopup();
    }
  }, [title]);

  return (
    <Marker ref={markerRef} position={position} icon={icon}>
      <Popup className="restaurant-popup">
        <div className="text-xs font-medium">{title}</div>
      </Popup>
    </Marker>
  );
}

const CustomMap: React.FC<CustomMapProps> = ({
  initialPosition,
  zoom = 13,
  markers = [],
  serviceArea,
  onPositionSelect,
  onZoomChange,
  onClick,
  markerActive = true,
  searchEnabled = true,
  onMapReady,
}) => {
  const [selectedPosition, setSelectedPosition] = useState<[number, number] | null>(null);
  const [mapInstance, setMapInstance] = useState<L.Map | null>(null);
  const [isSearching, setIsSearching] = useState(false);
  const [searchResults, setSearchResults] = useState<Array<{ id: string; title: string; position: [number, number] }>>([]);
  const [isMapLoading, setIsMapLoading] = useState(true);

  // Handle map load complete
  useEffect(() => {
    const checkTiles = () => {
      if (mapInstance) {
        const container = document.querySelector('.leaflet-tile-container');
        if (container && container.children.length > 0) {
          setIsMapLoading(false);
        } else {
          setTimeout(checkTiles, 100);
        }
      }
    };
    checkTiles();
  }, [mapInstance]);

  // Notify parent when map is ready
  useEffect(() => {
    if (mapInstance && onMapReady) {
      onMapReady(mapInstance);
    }
  }, [mapInstance, onMapReady]);

  // Initialize default icon on client side only
  useEffect(() => {
    // Dynamic import of Leaflet on the client side
    // Fix for default marker icon in Next.js
    delete ((L.Icon.Default.prototype) as { _getIconUrl?: unknown })._getIconUrl;
    L.Icon.Default.mergeOptions({
      iconRetinaUrl: '/marker-icon-2x.png',
      iconUrl: '/marker-icon.png',
      shadowUrl: '/marker-shadow.png',
    });
  }, []);

  const handleMapClick = (e: L.LeafletMouseEvent) => {
    const newPosition: [number, number] = [e.latlng.lat, e.latlng.lng];
    if (markerActive) {
      setSelectedPosition(newPosition);
    }
    onPositionSelect?.(newPosition);
    onClick?.(e);
  };

  const [searchTimeout, setSearchTimeout] = useState<NodeJS.Timeout>();

  const handleSearch = async (value: string) => {
    if (!value || value.trim().length === 0) {
      setSearchResults([]);
      return;
    }

    // Clear previous timeout
    if (searchTimeout) {
      clearTimeout(searchTimeout);
    }

    setIsSearching(true);

    // Set new timeout
    const timeout = setTimeout(async () => {
      try {
        // Iran's bounding box coordinates (roughly)
        const viewbox = '44.0,25.0,63.0,40.0'; // [min lon, min lat, max lon, max lat]
        const response = await fetch(
          `https://nominatim.openstreetmap.org/search?` +
          `format=json&` +
          `q=${encodeURIComponent(value)}&` +
          `countrycodes=ir&` + // Prioritize Iran
          `viewbox=${viewbox}&` +
          `bounded=0&` + // Allow results outside viewbox but prioritize inside
          `limit=10&` + // Limit results to 10
          `namedetails=1&` + // Get native names
          `accept-language=fa` // Request Persian results
          , {
            headers: {
              'Accept-Language': 'fa,en;q=0.9' // Prefer Persian, fallback to English
            }
          });
        interface SearchResult {
          place_id: string;
          display_name: string;
          lat: string;
          lon: string;
          namedetails?: {
            name?: string;
            'name:fa'?: string;
            alt_name?: string;
            'alt_name:fa'?: string;
          };
        }
        const data: SearchResult[] = await response.json();
        setSearchResults(data.map((item) => ({
          id: item.place_id,
          // Use Persian name if available, fallback to display_name
          title: /* item.namedetails?.['name:fa'] || 
                 item.namedetails?.name || 
                 item.namedetails?.['alt_name:fa'] || 
                 item.namedetails?.alt_name || */
            item.display_name,
          position: [parseFloat(item.lat), parseFloat(item.lon)] as [number, number]
        })));
      } catch (error) {
        console.error('Search error:', error);
        setSearchResults([]);
      } finally {
        setIsSearching(false);
      }
    }, 500); // Wait 500ms after last keystroke

    setSearchTimeout(timeout);
  };

  const handleSearchResultSelect = (result: { id: string; title: string; position: [number, number] }) => {
    console.log(result);
    setSelectedPosition(result.position);
    if (mapInstance) {
      mapInstance.setView(result.position, mapInstance.getZoom());
    }
  };

  return (
    <div className="w-full h-full relative">
      {searchEnabled &&
        <ActiveSearchbox
          placeholder="جستجو"
          onSearch={handleSearch}
          isLoading={isSearching}
          results={searchResults}
          onResultSelect={(v) => {
            // Find the full result object with position
            const result = searchResults.find(r => r.id === v.id && r.title === v.title);
            if (result) {
              handleSearchResultSelect(result);
            }
          }}
        />
      }
      <div className="map-zoom-controls">
        <button
          onClick={(e) => {
            e.stopPropagation();
            if (mapInstance) {
              const center = selectedPosition || mapInstance.getCenter();
              mapInstance.setZoomAround(center, mapInstance.getZoom() + 1);
            }
          }}
          className="zoom-button"
          aria-label="بزرگنمایی"
        >
          +
        </button>
        <button
          onClick={(e) => {
            e.stopPropagation();
            if (mapInstance) {
              const center = selectedPosition || mapInstance.getCenter();
              mapInstance.setZoomAround(center, mapInstance.getZoom() - 1);
            }
          }}
          className="zoom-button"
          aria-label="کوچک نمایی"
        >
          −
        </button>
      </div>
      {isMapLoading && (
        <div className="absolute inset-0 bg-zinc-50/80 backdrop-blur-sm z-[400]">
          <div className="grid grid-cols-3 gap-4 p-8 h-full">
            <Skeleton className="h-full" />
            <Skeleton className="h-full" />
            <Skeleton className="h-full" />
          </div>
        </div>
      )}
      <MapContainer
        center={initialPosition}
        zoom={zoom}
        className="map-google-style"
        style={{ height: '100%', width: '100%' }}
        zoomControl={false} // Disable default zoom control
      >
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />

        {/* Service Area Polygon */}
        {serviceArea && serviceArea.coordinates && serviceArea.coordinates.length > 0 && (
          <Polygon
            positions={serviceArea.coordinates[0].map(coord => [coord[1], coord[0]] as [number, number])}
            pathOptions={{
              color: '#3b82f6',
              fillColor: '#3b82f6',
              fillOpacity: 0.2,
              weight: 2,
              interactive: false,
            }}
          />
        )}

        {/* Custom markers */}
        {markers.map((marker, index) => (
          <MarkerWithAutoOpen
            key={`${marker.position}-${index}`}
            position={marker.position}
            icon={marker.icon}
            title={marker.title}
          />
        ))}

        {/* Selected position marker */}
        {selectedPosition && (
          <Marker position={selectedPosition}>
            <Popup>
              <div className="text-sm px-2">موقعیت انتخاب شده</div>
            </Popup>
          </Marker>
        )}

        {/* Event handlers */}
        <MapEvents
          onZoomChange={onZoomChange}
          onClick={handleMapClick}
          center={initialPosition}
          setMapRef={setMapInstance}
        />
        {/* Marker updater for zoom effects */}
        <MarkerUpdater markers={markers} />
      </MapContainer>
    </div>
  );
};

export default CustomMap;
