import React, { useState, useRef, useEffect } from 'react';
import { GoogleMap, LoadScript, Autocomplete, Marker } from '@react-google-maps/api';

const libraries: any = ['places'];

const GoogleMapComponent = ({
  defaultCenter,
  setAddress,
  setPlace
}: {
  defaultCenter: any;
  setAddress: any;
  setPlace: any;
}) => {
  const autocompleteRef = useRef<any>(null);
  const [map, setMap] = useState<any>(null);
  const [center, setCenter] = useState(defaultCenter);
  const [searchValue, setSearchValue] = useState('');

  useEffect(() => {
    if (defaultCenter?.lat && defaultCenter?.lng) {
      const newCenter = { lat: Number(defaultCenter.lat), lng: Number(defaultCenter.lng) };
      setCenter(newCenter);

      if (window.google?.maps?.Geocoder) {
        const geocoder = new window.google.maps.Geocoder();
        geocoder.geocode({ location: newCenter }, (results, status) => {
          if (status === 'OK' && results && results[0]) {
            const formatted_address = results[0].formatted_address;
            const address_components = results[0].address_components;

            setSearchValue(formatted_address);
            setAddress({
              place: formatted_address,
              location: newCenter
            });
            setPlace({
              geometry: {
                location: {
                  lat: () => newCenter.lat,
                  lng: () => newCenter.lng
                }
              },
              formatted_address,
              address_components
            });
          }
        });
      }
    }
  }, [defaultCenter?.lat, defaultCenter?.lng]);

  const handlePlaceSelected = () => {
    if (!autocompleteRef.current) return;
    const place = autocompleteRef.current.getPlace();
    if (place?.geometry) {
      const newCenter = {
        lat: place.geometry.location.lat(),
        lng: place.geometry.location.lng()
      };

      setSearchValue(place?.formatted_address);
      setPlace(place);
      setCenter(newCenter);
      setAddress({
        place: place.formatted_address,
        location: newCenter
      });
    }
  };

  const handleMapLoad = (mapInstance: any) => {
    setMap(mapInstance);

    if (defaultCenter?.lat && defaultCenter?.lng && window.google?.maps) {
      const geocoder = new window.google.maps.Geocoder();
      geocoder.geocode({ location: defaultCenter }, (results, status) => {
        if (status === 'OK' && results && results[0]) {
          const formatted_address = results[0].formatted_address;
          const address_components = results[0].address_components;

          setSearchValue(formatted_address);
          setAddress({
            place: formatted_address,
            location: defaultCenter
          });
          setPlace({
            geometry: {
              location: {
                lat: () => defaultCenter.lat,
                lng: () => defaultCenter.lng
              }
            },
            formatted_address,
            address_components
          });
        }
      });
    }
  };

  return (
    <LoadScript
      googleMapsApiKey={process.env.NEXT_PUBLIC_GOOGLE_MAP_KEY as string}
      libraries={libraries}
    >
      <div className="flex h-full w-full flex-col gap-2">
        <Autocomplete
          onLoad={(ref) => (autocompleteRef.current = ref)}
          onPlaceChanged={handlePlaceSelected}
        >
          <input
            type="text"
            placeholder="Enter an address"
            className="w-full rounded border p-2"
            value={searchValue}
            onChange={(e) => setSearchValue(e.target.value)}
          />
        </Autocomplete>

        <div className="map-wrapper w-full" style={{ height: '100%' }}>
          <GoogleMap
            center={center}
            zoom={12}
            mapContainerStyle={{ width: '100%', height: '100%' }}
            onLoad={handleMapLoad}
          >
            <Marker
              position={center}
              draggable={true}
              onDragEnd={(e) => {
                const newLat = e.latLng?.lat();
                const newLng = e.latLng?.lng();

                if (newLat && newLng) {
                  const newCenter = { lat: newLat, lng: newLng };
                  setCenter(newCenter);

                  const geocoder = new window.google.maps.Geocoder();
                  geocoder.geocode({ location: newCenter }, (results, status) => {
                    if (status === 'OK' && results && results[0]) {
                      const formatted_address = results[0].formatted_address;
                      const address_components = results[0].address_components;

                      setSearchValue(formatted_address);
                      setAddress({
                        place: formatted_address,
                        location: newCenter
                      });
                      setPlace({
                        geometry: {
                          location: {
                            lat: () => newLat,
                            lng: () => newLng
                          }
                        },
                        formatted_address,
                        address_components
                      });
                    }
                  });
                }
              }}
            />
          </GoogleMap>
        </div>
      </div>
    </LoadScript>
  );
};

export default GoogleMapComponent;
