import { useCallback, useMemo } from "react";
function findMatches(history, query) {
  if (!query) return [];
  const lowerQuery = query.toLowerCase();
  return history.filter((item) => item.toLowerCase().includes(lowerQuery)).reverse();
}
function useHistorySearch({
  ui,
  input,
  buffer,
  setUi,
  setInput
}) {
  const { historySearch } = ui;
  const { history } = input;
  const matches = useMemo(
    () => findMatches(history, historySearch.query),
    [history, historySearch.query]
  );
  const hasMatch = matches.length > 0;
  const currentMatch = hasMatch ? matches[Math.min(historySearch.matchIndex, matches.length - 1)] || null : historySearch.lastMatch || null;
  const enter = useCallback(() => {
    const currentText = buffer.text;
    setUi((prev) => ({
      ...prev,
      historySearch: {
        isActive: true,
        query: "",
        matchIndex: 0,
        originalInput: currentText,
        lastMatch: ""
      }
    }));
  }, [buffer, setUi]);
  const exit = useCallback(() => {
    setUi((prev) => ({
      ...prev,
      historySearch: {
        isActive: false,
        query: "",
        matchIndex: 0,
        originalInput: "",
        lastMatch: ""
      }
    }));
  }, [setUi]);
  const cancel = useCallback(() => {
    const originalInput = historySearch.originalInput;
    buffer.setText(originalInput);
    setInput((prev) => ({ ...prev, value: originalInput }));
    exit();
  }, [historySearch.originalInput, buffer, setInput, exit]);
  const applyMatch = useCallback(
    (match) => {
      if (match) {
        buffer.setText(match);
        setInput((prev) => ({ ...prev, value: match }));
      }
    },
    [buffer, setInput]
  );
  const updateQuery = useCallback(
    (newQuery) => {
      const newMatches = findMatches(history, newQuery);
      const newHasMatch = newMatches.length > 0;
      const newMatch = newHasMatch ? newMatches[0] : null;
      setUi((prev) => ({
        ...prev,
        historySearch: {
          ...prev.historySearch,
          query: newQuery,
          matchIndex: 0,
          // Update lastMatch only if we have a new match
          lastMatch: newMatch || prev.historySearch.lastMatch
        }
      }));
      if (newMatch) {
        applyMatch(newMatch);
      }
    },
    [history, setUi, applyMatch]
  );
  const appendToQuery = useCallback(
    (char) => {
      updateQuery(historySearch.query + char);
    },
    [historySearch.query, updateQuery]
  );
  const backspace = useCallback(() => {
    if (historySearch.query.length > 0) {
      updateQuery(historySearch.query.slice(0, -1));
    }
  }, [historySearch.query, updateQuery]);
  const cycleNext = useCallback(() => {
    if (matches.length === 0) return;
    const newIndex = Math.min(historySearch.matchIndex + 1, matches.length - 1);
    const newMatch = matches[newIndex];
    setUi((prev) => ({
      ...prev,
      historySearch: {
        ...prev.historySearch,
        matchIndex: newIndex,
        lastMatch: newMatch || prev.historySearch.lastMatch
      }
    }));
    if (newMatch) {
      applyMatch(newMatch);
    }
  }, [matches, historySearch.matchIndex, setUi, applyMatch]);
  const cyclePrev = useCallback(() => {
    if (matches.length === 0) return;
    const newIndex = Math.max(0, historySearch.matchIndex - 1);
    const newMatch = matches[newIndex];
    setUi((prev) => ({
      ...prev,
      historySearch: {
        ...prev.historySearch,
        matchIndex: newIndex,
        lastMatch: newMatch || prev.historySearch.lastMatch
      }
    }));
    if (newMatch) {
      applyMatch(newMatch);
    }
  }, [matches, historySearch.matchIndex, setUi, applyMatch]);
  const accept = useCallback(() => {
    exit();
  }, [exit]);
  const handleKey = useCallback(
    (inputStr, key) => {
      if (!historySearch.isActive) {
        if (key.ctrl && inputStr === "r") {
          enter();
          return true;
        }
        return false;
      }
      if (key.ctrl && inputStr === "e") {
        cyclePrev();
        return true;
      }
      if (key.ctrl && inputStr === "r") {
        cycleNext();
        return true;
      }
      if (key.return) {
        accept();
        return true;
      }
      if (key.escape) {
        cancel();
        return true;
      }
      if (key.backspace || key.delete) {
        backspace();
        return true;
      }
      if (inputStr && !key.ctrl && !key.meta) {
        appendToQuery(inputStr);
        return true;
      }
      return true;
    },
    [
      historySearch.isActive,
      enter,
      cycleNext,
      cyclePrev,
      accept,
      cancel,
      backspace,
      appendToQuery
    ]
  );
  return {
    isActive: historySearch.isActive,
    query: historySearch.query,
    currentMatch,
    hasMatch,
    originalInput: historySearch.originalInput,
    enter,
    exit,
    cancel,
    updateQuery,
    appendToQuery,
    backspace,
    cycleNext,
    cyclePrev,
    accept,
    handleKey
  };
}
export {
  useHistorySearch
};
