import { useEffect, useRef, type InputHTMLAttributes } from "react";
import { loadGoogleMaps } from "@/components/Map";

type AddressAutocompleteInputProps = Omit<
  InputHTMLAttributes<HTMLInputElement>,
  "value" | "onChange"
> & {
  value: string;
  onValueChange: (value: string) => void;
  onPlaceSelected?: (place: google.maps.places.PlaceResult) => void;
  onMapsReady?: () => void;
  onMapsUnavailable?: () => void;
};

/**
 * A browser-safe Google Places address field shared by all offer forms. It
 * gracefully falls back to manual entry if the proxy-backed Maps script cannot
 * load, so a seller is never blocked from submitting a property address.
 */
export function AddressAutocompleteInput({
  value,
  onValueChange,
  onPlaceSelected,
  onMapsReady,
  onMapsUnavailable,
  ...inputProps
}: AddressAutocompleteInputProps) {
  const inputRef = useRef<HTMLInputElement>(null);
  const callbacksRef = useRef({ onValueChange, onPlaceSelected, onMapsReady, onMapsUnavailable });
  callbacksRef.current = { onValueChange, onPlaceSelected, onMapsReady, onMapsUnavailable };

  useEffect(() => {
    let active = true;
    let autocomplete: google.maps.places.Autocomplete | null = null;
    let listener: google.maps.MapsEventListener | undefined;

    const attachAutocomplete = (attempt = 0) => {
      if (!active || !inputRef.current) return;
      if (!window.google?.maps?.places) {
        if (attempt < 12) {
          window.setTimeout(() => attachAutocomplete(attempt + 1), 80);
        } else {
          callbacksRef.current.onMapsUnavailable?.();
        }
        return;
      }

      autocomplete = new window.google.maps.places.Autocomplete(inputRef.current, {
        componentRestrictions: { country: "us" },
        fields: ["formatted_address", "address_components"],
        types: ["address"],
      });
      callbacksRef.current.onMapsReady?.();

      listener = autocomplete.addListener("place_changed", () => {
        const place = autocomplete?.getPlace();
        if (!place) return;
        if (place.formatted_address) callbacksRef.current.onValueChange(place.formatted_address);
        callbacksRef.current.onPlaceSelected?.(place);
      });
    };

    void loadGoogleMaps()
      .then(() => attachAutocomplete())
      .catch(() => {
        if (active) callbacksRef.current.onMapsUnavailable?.();
      });

    return () => {
      active = false;
      listener?.remove();
      if (autocomplete) window.google?.maps.event.clearInstanceListeners(autocomplete);
    };
  }, []);

  return <input ref={inputRef} value={value} onChange={(event) => onValueChange(event.target.value)} {...inputProps} />;
}
