// (C) 2025-2026 GoodData Corporation
import { useId, useMemo } from "react";
import { makeKeyboardNavigation } from "../@utils/keyboardNavigation.js";
import { useComboboxChrome } from "./useComboboxChrome.js";
import { useComboboxSelection } from "./useComboboxSelection.js";
// Omit handlers where we want default behavior to fall through —
// `makeKeyboardNavigation` preventDefaults every registered action.
const comboboxKeys = makeKeyboardNavigation({
    onArrowDown: [{ code: "ArrowDown" }],
    onArrowUp: [{ code: "ArrowUp" }],
    onEnter: [{ code: ["Enter", "NumpadEnter"] }],
    onEscape: [{ code: "Escape" }],
});
/** @internal */
export function useCombobox(params) {
    const { value, defaultValue = "", onValueChange, options, creatable = false } = params;
    const listboxId = useId();
    const selection = useComboboxSelection({
        options,
        value,
        defaultValue,
        onValueChange,
        creatable,
        setIsOpen: (open) => chrome.setIsOpen(open),
    });
    const chrome = useComboboxChrome(selection.availableOptions);
    const activeOption = chrome.activeOption;
    const onInputKeyDown = useMemo(() => {
        // Leave Enter unhandled when there's no selectable target so creatable
        // flows like UiTags (add tag on unhandled Enter) can react to it.
        const onEnter = chrome.isOpen && activeOption
            ? activeOption.disabled
                ? () => undefined
                : () => selection.selectOption(activeOption)
            : undefined;
        // Leave Escape unhandled when idle so the enclosing modal can dismiss.
        const hasSomethingToClose = chrome.isOpen || selection.inputValue.length > 0;
        const onEscape = hasSomethingToClose
            ? (event) => {
                event.nativeEvent.stopPropagation();
                if (chrome.isOpen) {
                    chrome.setIsOpen(false);
                    return;
                }
                selection.resetState();
            }
            : undefined;
        return comboboxKeys({
            onArrowDown: () => chrome.focusByDelta(1),
            onArrowUp: () => chrome.focusByDelta(-1),
            onEnter,
            onEscape,
        });
    }, [chrome, selection, activeOption]);
    return useMemo(() => ({
        availableOptions: selection.availableOptions,
        inputValue: selection.inputValue,
        isOpen: chrome.isOpen,
        setIsOpen: chrome.setIsOpen,
        onInputChange: selection.onInputChange,
        onInputKeyDown,
        onInputBlur: selection.onInputBlur,
        activeIndex: chrome.activeIndex,
        setActiveIndex: chrome.setActiveIndex,
        activeOption,
        selectedOption: selection.selectedOption,
        selectOption: selection.selectOption,
        anchorRef: chrome.anchorRef,
        registerItemRef: chrome.registerItemRef,
        shouldRenderPopup: selection.availableOptions.length > 0,
        creatable,
        listboxId,
    }), [chrome, selection, onInputKeyDown, activeOption, creatable, listboxId]);
}
