import React, {
  useState,
  Dispatch,
  SetStateAction,
  useEffect,
  useRef,
} from "react";
import useDebounce from "../../hooks/useDebounce";
import { useGetCities, useGetCountries, useGetStates } from "../../utils/hooks";

interface LocationBoxProps {
  setSortAndFilterOptions: Dispatch<SetStateAction<SortAndFilterOptionsType>>;
  sortAndFilterOptions: SortAndFilterOptionsType;
  setClearAllStateDisabled: Dispatch<SetStateAction<boolean>>;
}

const LocationBox: React.FC<LocationBoxProps> = ({
  setSortAndFilterOptions,
  sortAndFilterOptions,
  setClearAllStateDisabled,
}) => {
  const [countries, setCountries] = useState<CountryData[]>();
  const [states, setStates] = useState<StatesData[]>();
  const [cities, setCities] = useState<CitiesData[]>();

  const [selectedCountry, setSelectedCountry] = useState<number | null>(null);
  const [selectedState, setSelectedState] = useState<number | null>(null);

  const [query, setQuery] = useState("");
  const debouncedQuery = useDebounce(query, 350);

  const countryQuery = query.split(", ")[0]?.trim();
  const stateQuery = query.split(", ")[1]?.trim();
  const cityQuery = query.split(", ")[2]?.trim();

  const [activeIndex, setActiveIndex] = useState<number>(-1);
  const listRef = useRef<HTMLUListElement | null>(null);

  const [isFinalSelection, setIsFinalSelection] = useState(false);

  const handleLocationChange = (query: string) => {
    if (query !== "") setClearAllStateDisabled(false);
    setSortAndFilterOptions({
      ...sortAndFilterOptions,
      locationSearchKeyword: query,
    });
  };

  useEffect(() => {
    handleLocationChange(debouncedQuery);
  }, [debouncedQuery]);

  useEffect(() => {
    const getCountries = async () => {
      try {
        const { resp, status } = (await useGetCountries()) as Response;
        if (status === 200) setCountries(resp.data);
      } catch (error) {
        console.error("Error fetching countries:", error);
      }
    };
    getCountries();
  }, []);

  useEffect(() => {
    const matched = countries?.find((c) => c.name === countryQuery);
    if (matched) {
      setSelectedCountry(matched.id);
    } else {
      setSelectedCountry(null);
      setStates(undefined);
      setCities(undefined);
    }
  }, [countryQuery, countries]);

  useEffect(() => {
    const getStates = async () => {
      if (selectedCountry) {
        try {
          const { resp, status } = (await useGetStates(
            selectedCountry
          )) as Response;
          if (status === 200) setStates(resp.data);
        } catch (error) {
          console.error("Error fetching states:", error);
        }
      }
    };
    getStates();
  }, [selectedCountry]);

  useEffect(() => {
    const matched = states?.find((s) => s.name === stateQuery);
    if (matched) {
      setSelectedState(matched.id);
    } else {
      setSelectedState(null);
      setCities(undefined);
    }
  }, [stateQuery, states]);

  useEffect(() => {
    const getCities = async () => {
      if (selectedState) {
        try {
          const { resp, status } = (await useGetCities(
            selectedState
          )) as Response;
          if (status === 200) setCities(resp.data);
        } catch (error) {
          console.error("Error fetching cities:", error);
        }
      }
    };
    getCities();
  }, [selectedState]);

  useEffect(() => {
    if (query.trim() === "") {
      setSelectedCountry(null);
      setSelectedState(null);
      setStates(undefined);
      setCities(undefined);
    }
    // Always reset selection when typing
    setIsFinalSelection(false);
  }, [query]);

  const getDropdownItems = () => {
    const items: { key: string; value: string; label: string }[] = [];

    if (query && !query.includes(",")) {
      countries
        ?.filter((country) =>
          country.name.toLowerCase().includes(query.toLowerCase())
        )
        .forEach((country) => {
          items.push({
            key: `country-${country.id}`,
            value: `${country.name}`,
            label: `${country.name}`,
          });
        });
    } else if (countryQuery && !query.includes(",", query.indexOf(",") + 1)) {
      const matchedCountry = countries?.find(
        (c) => c.name.toLowerCase() === countryQuery.toLowerCase()
      );
      if (matchedCountry && states) {
        states
          .filter((state) =>
            state.name.toLowerCase().includes(stateQuery?.toLowerCase() || "")
          )
          .forEach((state) => {
            items.push({
              key: `state-${state.id}`,
              value: `${matchedCountry.name}, ${state.name}`,
              label: `${state.name}, ${matchedCountry.name}`,
            });
          });
      }
    } else if (countryQuery && stateQuery && cities) {
      const matchedCountry = countries?.find(
        (c) => c.name.toLowerCase() === countryQuery.toLowerCase()
      );
      const matchedState = states?.find(
        (s) => s.name.toLowerCase() === stateQuery.toLowerCase()
      );
      if (matchedCountry && matchedState) {
        cities
          .filter((city) =>
            city.name.toLowerCase().includes(cityQuery?.toLowerCase() || "")
          )
          .forEach((city) => {
            items.push({
              key: `city-${city.id}`,
              value: `${matchedCountry.name}, ${matchedState.name}, ${city.name}`,
              label: `${city.name}, ${matchedState.name}, ${matchedCountry.name}`,
            });
          });
      }
    }

    return items;
  };

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    const listItems = listRef.current?.querySelectorAll("li") || [];
    if (e.key === "ArrowDown") {
      e.preventDefault();
      setActiveIndex((prev) => Math.min(prev + 1, listItems.length - 1));
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      setActiveIndex((prev) => Math.max(prev - 1, 0));
    } else if (e.key === "Enter" && activeIndex >= 0) {
      e.preventDefault();
      const selectedItem = listItems[activeIndex];
      selectedItem?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
    }
  };

  useEffect(() => {
    const listItems = listRef.current?.querySelectorAll("li");
    if (listItems && listItems[activeIndex]) {
      (listItems[activeIndex] as HTMLElement).scrollIntoView({
        block: "nearest",
      });
    }
  }, [activeIndex]);

  return (
    <form method="post" style={{ position: "relative" }}>
      <span className="icon flaticon-map-locator"></span>
      <input
        type="text"
        name="listing-search"
        placeholder="Search Country"
        value={query}
        onChange={(e) => {
          setQuery(e.target.value);
          setActiveIndex(-1);
        }}
        onKeyDown={handleKeyDown}
        style={{
          width: "100%",
          padding: "8px",
          paddingLeft: "50px",
          fontSize: "1rem",
        }}
      />
      {getDropdownItems().length > 0 && !isFinalSelection && (
        <ul
          className="auto-complete-list"
          ref={listRef}
          style={{
            listStyle: "none",
            padding: 0,
            margin: 0,
            maxHeight: "200px",
            overflowY: "auto",
            border: "1px solid #ccc",
            borderRadius: "4px",
            position: "absolute",
            width: "100%",
            backgroundColor: "white",
            zIndex: 10,
          }}
        >
          {getDropdownItems().map((item, index) => (
            <li
              key={item.key}
              onClick={() => {
                setQuery(item.value);
                setActiveIndex(-1);

                // If full location selected, stop showing dropdown
                if (item.value.split(",").length === 3) {
                  setIsFinalSelection(true);
                } else {
                  setIsFinalSelection(false);
                }
              }}
              style={{
                padding: "8px",
                cursor: "pointer",
                backgroundColor: index === activeIndex ? "#eee" : "#fff",
              }}
            >
              {item.label}
            </li>
          ))}
        </ul>
      )}
    </form>
  );
};

export default LocationBox;
