
import { Status, Wrapper } from "@googlemaps/react-wrapper";
import { useEffect, useRef, useState } from "react";

interface GoogleMapProps {
  onLocationSelect?: (lat: number, lng: number, address: string) => void;
  height?: string;
  readOnly?: boolean;
  initialLocation?: { lat: number; lng: number; address?: string };
}

function MapComponent({
  onLocationSelect,
  height = "100%",
  readOnly = false,
  initialLocation,
}: GoogleMapProps) {
  const mapRef = useRef<HTMLDivElement>(null);
  const markerRef = useRef<google.maps.Marker | null>(null);
  const [map, setMap] = useState<google.maps.Map | null>(null);

  // Prevent touch events from bubbling up to parent components
  const handleTouchStart = (e: React.TouchEvent) => {
    e.stopPropagation();
  };

  const handleTouchMove = (e: React.TouchEvent) => {
    e.stopPropagation();
  };

  const handleTouchEnd = (e: React.TouchEvent) => {
    e.stopPropagation();
  };

  // Prevent mouse events from bubbling up
  const handleMouseDown = (e: React.MouseEvent) => {
    e.stopPropagation();
  };

  const handleMouseMove = (e: React.MouseEvent) => {
    e.stopPropagation();
  };

  const handleMouseUp = (e: React.MouseEvent) => {
    e.stopPropagation();
  };

  // Prevent wheel events from bubbling up
  const handleWheel = (e: React.WheelEvent) => {
    e.stopPropagation();
  };

  useEffect(() => {
    if (mapRef.current && !map) {
      const center = initialLocation
        ? { lat: initialLocation.lat, lng: initialLocation.lng }
        : { lat: 24.7136, lng: 46.6753 }; // Default to Riyadh, Saudi Arabia

      const newMap = new google.maps.Map(mapRef.current, {
        center,
        zoom: initialLocation ? 15 : 13,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        mapTypeControl: false,
        streetViewControl: false,
        fullscreenControl: false,
        zoomControl: true,
        styles: [
          {
            featureType: "poi",
            elementType: "labels",
            stylers: [{ visibility: "off" }],
          },
        ],
      });

      setMap(newMap);
      console.log('Map initialized successfully');

      // If we have an initial location, add a marker
      if (initialLocation) {
        const initialMarker = new google.maps.Marker({
          position: { lat: initialLocation.lat, lng: initialLocation.lng },
          map: newMap,
          draggable: true,
        });
        markerRef.current = initialMarker;

        // Add drag end listener to the initial marker
        initialMarker.addListener("dragend", () => {
          const position = initialMarker.getPosition();
          if (position) {
            const lat = position.lat();
            const lng = position.lng();
            
            // Get address from coordinates
            const geocoder = new google.maps.Geocoder();
            geocoder.geocode({ location: { lat, lng } }, (results, status) => {
              if (status === "OK" && results && results[0]) {
                const address = results[0].formatted_address;
                console.log('Initial marker drag - calling onLocationSelect:', { lat, lng, address });
                onLocationSelect?.(lat, lng, address);
              } else {
                console.log('Geocoding failed on initial marker drag:', status);
                // Fallback: use coordinates as address if geocoding fails
                const fallbackAddress = `Location: ${lat.toFixed(6)}, ${lng.toFixed(6)}`;
                console.log('Using fallback address for initial marker drag:', fallbackAddress);
                onLocationSelect?.(lat, lng, fallbackAddress);
              }
            });
          }
        });
      }

      // Only add click listener if not in readOnly mode
      if (!readOnly) {
        newMap.addListener("click", (e: google.maps.MapMouseEvent) => {
          if (e.latLng) {
            const lat = e.latLng.lat();
            const lng = e.latLng.lng();

            // Remove existing marker
            if (markerRef.current) {
              markerRef.current.setMap(null);
            }

            // Add new marker
            const newMarker = new google.maps.Marker({
              position: { lat, lng },
              map: newMap,
              draggable: true,
            });

            markerRef.current = newMarker;

            // Add drag end listener to the marker
            newMarker.addListener("dragend", () => {
              const position = newMarker.getPosition();
              if (position) {
                const lat = position.lat();
                const lng = position.lng();
                
                // Get address from coordinates
                const geocoder = new google.maps.Geocoder();
                geocoder.geocode({ location: { lat, lng } }, (results, status) => {
                  if (status === "OK" && results && results[0]) {
                    const address = results[0].formatted_address;
                    console.log('Marker drag - calling onLocationSelect:', { lat, lng, address });
                    onLocationSelect?.(lat, lng, address);
                  } else {
                    console.log('Geocoding failed on drag:', status);
                    // Fallback: use coordinates as address if geocoding fails
                    const fallbackAddress = `Location: ${lat.toFixed(6)}, ${lng.toFixed(6)}`;
                    console.log('Using fallback address for drag:', fallbackAddress);
                    onLocationSelect?.(lat, lng, fallbackAddress);
                  }
                });
              }
            });

            // Get address from coordinates
            const geocoder = new google.maps.Geocoder();
            geocoder.geocode({ location: { lat, lng } }, (results, status) => {
              if (status === "OK" && results && results[0]) {
                const address = results[0].formatted_address;
                console.log('Map click - calling onLocationSelect:', { lat, lng, address });
                onLocationSelect?.(lat, lng, address);
              } else {
                console.log('Geocoding failed on click:', status);
                // Fallback: use coordinates as address if geocoding fails
                const fallbackAddress = `Location: ${lat.toFixed(6)}, ${lng.toFixed(6)}`;
                console.log('Using fallback address:', fallbackAddress);
                onLocationSelect?.(lat, lng, fallbackAddress);
              }
            });
          }
        });
      }
    }
  }, [map, onLocationSelect, readOnly, initialLocation]);

  return (
    <div
      ref={mapRef}
      style={{
        width: "100%",
        height: height,
        borderRadius: "8px",
      }}
      onTouchStart={handleTouchStart}
      onTouchMove={handleTouchMove}
      onTouchEnd={handleTouchEnd}
      onMouseDown={handleMouseDown}
      onMouseMove={handleMouseMove}
      onMouseUp={handleMouseUp}
      onWheel={handleWheel}
    />
  );
}

export function GoogleMap({
  onLocationSelect,
  height,
  readOnly,
  initialLocation,
}: GoogleMapProps) {
  const render = (status: Status) => {
    switch (status) {
      case Status.LOADING:
        return (
          <div
            style={{
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              height: height || "100%",
              backgroundColor: "#f5f5f5",
              borderRadius: "8px",
            }}
          >
            <div>Loading map...</div>
          </div>
        );
      case Status.FAILURE:
        return (
          <div
            style={{
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              height: height || "100%",
              backgroundColor: "#ffebee",
              color: "#c62828",
              borderRadius: "8px",
              padding: "20px",
              textAlign: "center",
            }}
          >
            <div>
              <div style={{ fontWeight: "500", marginBottom: "8px" }}>
                Failed to load Google Maps
              </div>
              <div style={{ fontSize: "12px", marginBottom: "8px" }}>
                API not activated or key invalid
              </div>
              <div style={{ fontSize: "11px", color: "#999" }}>
                Please enable Maps JavaScript API in Google Cloud Console
              </div>
            </div>
          </div>
        );
      default:
        return (
          <MapComponent
            onLocationSelect={onLocationSelect}
            height={height}
            readOnly={readOnly}
            initialLocation={initialLocation}
          />
        );
    }
  };

  const apiKey =
    // process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY ||
    "AIzaSyAPIJLJlpGyFkSImiOqI0KpymhR0A2qwzg";

  return <Wrapper apiKey={apiKey} render={render} />;
}
