import React, { useState, useRef, useEffect } from "react";
import usePlacesAutocomplete, {
  getGeocode,
  getLatLng,
} from "use-places-autocomplete";
import {
  UseFormRegister,
  FieldValues,
  FieldError,
  FieldErrorsImpl,
  Merge,
} from "react-hook-form";
import useGoogleApi from "~/hooks/useGoogleApi";

interface AddressSelectorProps {
  register: UseFormRegister<FieldValues>;
  registerOptions?: Record<string, unknown>;
  required?: boolean;
  fieldName: string;
  setValue: any;
}

interface ApartmentDetails {
  lat: number | null;
  lng: number | null;
  placeId: string | null;
}

const AddressSelector: React.FC<AddressSelectorProps> = ({
  register,
  registerOptions,
  required,
  setValue,
  fieldName,
}) => {
  const [open, setOpen] = useState(false);
  const [result, setResult] = useState("");
  const [apartmentDetails, setApartmentDetails] = useState<ApartmentDetails>({
    lat: null,
    lng: null,
    placeId: null,
  });
  const triggerRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    if (triggerRef.current) {
      document.documentElement.style.setProperty(
        "--portal-width",
        `${triggerRef.current.clientWidth}px`
      );
    }
  }, []);

  const {
    ready,
    init,
    setValue: setQuery,
    suggestions: { data, loading, status },
  } = usePlacesAutocomplete({
    requestOptions: { componentRestrictions: { country: ["ng"] } },
    debounce: 800,
  });

  useGoogleApi({ onLoad: () => init() });

  async function handleSelect(currentValue: string, place_id: string) {
    if (currentValue === result) {
      setResult("");
      setValue(fieldName, "", { shouldValidate: true });
      setApartmentDetails({ lat: null, lng: null, placeId: null });
      return;
    }
    setResult(currentValue);
    setValue(fieldName, currentValue, { shouldValidate: true });
    try {
      const geocode = (await getGeocode({ address: currentValue }))?.[0];
      const { lat, lng } = getLatLng(geocode);
      setApartmentDetails({ lat, lng, placeId: place_id });
    } catch (error) {
      console.log("Error: ", error);
    }
    setOpen(false);
  }

  return (
    <>
      <div className="w-full">
        {!open && (
          <div
            className="w-full cursor-text border-2 rounded text-lg"
            onClick={() => setOpen(!open)}
            ref={triggerRef}
          >
            <input
              id={fieldName}
              placeholder="Select an address"
              className="w-full focus:outline-none focus:border-primary rounded px-3 py-2 text-left"
              {...register(fieldName, {
                required: required && "This field is required",
                ...registerOptions,
              })}
              readOnly
            />
          </div>
        )}
        {open && (
          <div
            className="relative z-10 w-full bg-white rounded p-0"
            style={{ width: "var(--portal-width)" }}
          >
            <input
              placeholder="Search address..."
              autoFocus={open}
              onChange={(e) => setQuery(e.target.value)}
              disabled={!ready}
              className="focus:outline-none focus:border-primary w-full rounded-md px-3 border-2 border-stroke py-2 text-lg"
            />
            {loading && (
              <div className="p-2 absolute bg-white w-full">Loading...</div>
            )}
            {status === "OK" && !loading && (
              <ul className="border absolute bg-white rounded min-h-full w-full p-2">
                {data.map(({ place_id, description }) => (
                  <li
                    key={place_id}
                    className="p-2 cursor-pointer hover:bg-gray-200 rounded"
                    onClick={() => handleSelect(description, place_id)}
                  >
                    {description}
                  </li>
                ))}
              </ul>
            )}
            {status === "ZERO_RESULTS" && (
              <div className="p-2">No such address found.</div>
            )}
          </div>
        )}
      </div>
      <input type="hidden" name="lat" value={apartmentDetails.lat ?? ""} />
      <input type="hidden" name="lng" value={apartmentDetails.lng ?? ""} />
      <input
        type="hidden"
        name="placeId"
        value={apartmentDetails.placeId ?? ""}
      />
    </>
  );
};

export default AddressSelector;
