"use client";

import { useEffect, useRef, useState } from "react";
import { useCombobox } from "downshift";
import ArrowLeftLineIcon from "remixicon-react/ArrowLeftLineIcon";
import { useTranslation } from "react-i18next";
import { useSearch } from "@/context/search";
import { Types } from "@/context/search/search.reducer";
import { Button } from "@/components/button";
import LocationIcon from "@/assets/icons/location";
import SearchIcon from "@/assets/icons/search";
import { error } from "@/components/alert";
import clsx from "clsx";
import { SearchErrorMessage } from "./place-search-error-message";
import { NearbySearch } from "./nearby-search";
import { mapIrSearch, MapIrSearchItem } from "@/lib/map-ir";

interface PlaceSelectProps {
  closeModal?: () => void;
  onSelect?: () => void;
}

function applyPlace(
  item: MapIrSearchItem,
  dispatch: ReturnType<typeof useSearch>["dispatch"]
) {
  dispatch({ type: Types.SetLocationPLaceId, payload: item.id || "" });
  dispatch({
    type: Types.SetLocation,
    payload: {
      query: item.address || item.title,
      geolocation: {
        longitude: String(item.lng),
        latitude: String(item.lat),
      },
    },
  });
}

export const PlaceSelect = ({ closeModal, onSelect }: PlaceSelectProps) => {
  const { t } = useTranslation();
  const { dispatch, state } = useSearch();
  const [value, setValue] = useState(state.location.query || "");
  const [items, setItems] = useState<MapIrSearchItem[]>([]);
  const [loading, setLoading] = useState(false);
  const requestId = useRef(0);
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const selectingRef = useRef(false);

  useEffect(
    () => () => {
      if (debounceRef.current) clearTimeout(debounceRef.current);
    },
    []
  );

  const runSearch = async (q: string) => {
    if (selectingRef.current) return;
    if (q.trim().length < 2) {
      setItems([]);
      setLoading(false);
      dispatch({
        type: Types.SetSearchPredictions,
        payload: { predictions: [], status: "" },
      });
      return;
    }
    const id = ++requestId.current;
    setLoading(true);
    try {
      const results = await mapIrSearch(q);
      if (id !== requestId.current) return;
      setItems(results);
      if (results.length) openMenu();
      dispatch({
        type: Types.SetSearchPredictions,
        payload: {
          predictions: results.map((r) => ({
            id: r.id,
            name: { string: r.title, length: r.title.length, offset: 0 },
            address: { string: r.address },
          })),
          status: results.length ? "OK" : "ZERO_RESULTS",
        },
      });
    } finally {
      if (id === requestId.current) setLoading(false);
    }
  };

  const finishSelect = (item: MapIrSearchItem) => {
    selectingRef.current = true;
    if (debounceRef.current) clearTimeout(debounceRef.current);
    setValue(item.address || item.title);
    setItems([]);
    applyPlace(item, dispatch);
    onSelect?.();
    closeModal?.();
    // بعد از بستن مودال، فلگ را ریست کن
    setTimeout(() => {
      selectingRef.current = false;
    }, 0);
  };

  const { getInputProps, getItemProps, getMenuProps, openMenu, highlightedIndex, isOpen } =
    useCombobox({
      items,
      inputValue: value,
      onInputValueChange: ({ inputValue, type }) => {
        if (selectingRef.current) return;
        // با انتخاب از لیست دوباره سرچ نکن
        if (
          type === useCombobox.stateChangeTypes.ItemClick ||
          type === useCombobox.stateChangeTypes.ControlledPropUpdatedSelectedItem ||
          type === useCombobox.stateChangeTypes.FunctionSelectItem
        ) {
          return;
        }
        const q = inputValue || "";
        setValue(q);
        if (debounceRef.current) clearTimeout(debounceRef.current);
        debounceRef.current = setTimeout(() => {
          void runSearch(q);
        }, 350);
      },
      itemToString: (item) => item?.address || item?.title || "",
      onSelectedItemChange: ({ selectedItem, type }) => {
        if (!selectedItem) return;
        if (
          type === useCombobox.stateChangeTypes.ItemClick ||
          type === useCombobox.stateChangeTypes.InputKeyDownEnter ||
          type === useCombobox.stateChangeTypes.FunctionSelectItem
        ) {
          finishSelect(selectedItem);
        }
      },
    });

  const handleSelectLocation = () => {
    if (!value.trim()) return;
    const selected =
      items.find((i) => i.title === value || i.address === value) || items[0];
    if (!selected) {
      error(t("cant.get.place.detail") || "آدرس را از لیست انتخاب کنید");
      return;
    }
    finishSelect(selected);
  };

  return (
    <div className="md:px-8 px-4 pt-6 pb-8">
      <div className="flex items-center gap-2 mb-4">
        <button type="button" onClick={closeModal}>
          <ArrowLeftLineIcon />
        </button>
        <span className="text-xl font-semibold">{t("where")}</span>
      </div>

      <div className="relative">
        <div className="relative">
          <span className="pointer-events-none absolute inset-y-0 left-3 flex items-center z-[4] text-gray-field">
            <SearchIcon />
          </span>
          <input
            {...getInputProps({
              onFocus: () => {
                if (items.length) openMenu();
              },
            })}
            className="block px-4 pl-10 w-full text-sm bg-transparent rounded-button border border-gray-link appearance-none focus:outline-none focus:ring-0 focus-visible:border-primary py-[19px]"
            placeholder={t("search.address") || "جستجوی آدرس، محله، شهر..."}
          />
        </div>

        {loading && (
          <p className="text-sm text-gray-field mt-2 text-start">
            {t("loading") || "در حال جستجو..."}
          </p>
        )}

        <ul
          {...getMenuProps()}
          className={clsx(
            "absolute z-20 w-full bg-white dark:bg-dark shadow-lg rounded-button mt-1 max-h-60 overflow-auto text-start",
            (!isOpen || !items.length) && "hidden"
          )}
        >
          {items.map((item, index) => (
            <li
              key={`${item.id}-${index}`}
              {...getItemProps({
                item,
                index,
                // جلوگیری از blur اینپوت قبل از ثبت کلیک (باگ رایج downshift در مودال)
                onMouseDown: (e) => e.preventDefault(),
              })}
              className={clsx(
                "px-4 py-3 cursor-pointer flex gap-2 items-start border-b border-gray-link last:border-0",
                highlightedIndex === index
                  ? "bg-gray-50 dark:bg-gray-bold"
                  : "hover:bg-gray-50 dark:hover:bg-gray-bold"
              )}
            >
              <LocationIcon />
              <div>
                <div className="font-medium">{item.title}</div>
                {item.address && item.address !== item.title && (
                  <div className="text-sm text-gray-field">{item.address}</div>
                )}
              </div>
            </li>
          ))}
        </ul>
      </div>

      <SearchErrorMessage status={state.location.status} />
      <NearbySearch
        onSuccess={(result) => {
          setValue(result || "");
        }}
      />
      <div className="mt-6">
        <Button fullWidth color="black" onClick={handleSelectLocation}>
          {t("select")}
        </Button>
      </div>
    </div>
  );
};
