import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// (C) 2026 GoodData Corporation
import { memo, useCallback, useDeferredValue, useMemo, useState } from "react";
import { defineMessages, useIntl } from "react-intl";
import { objRefToString } from "@gooddata/sdk-model";
import { bem } from "../@ui/@utils/bem.js";
import { UiButton } from "../@ui/UiButton/UiButton.js";
import { UiCheckbox } from "../@ui/UiCheckbox/UiCheckbox.js";
import { UiIcon } from "../@ui/UiIcon/UiIcon.js";
import { Input } from "../Form/Input.js";
import { LoadingSpinner } from "../LoadingSpinner/LoadingSpinner.js";
const { b, e } = bem("gd-ui-kit-parameter-picker");
const messages = defineMessages({
    empty: { id: "filter_bar_add_filter.parameters.empty" },
    noResults: { id: "filter_bar_add_filter.parameters.no_results" },
    searchPlaceholder: { id: "filter_bar_add_filter.parameters.search_placeholder" },
    add: { id: "filter_bar_add_filter.parameters.add" },
    cancel: { id: "cancel" },
    ungrouped: { id: "catalog.group_title.ungrouped" },
});
/**
 * Workspace-parameter catalog browser. Search, tag grouping, multi-select.
 * Already-added parameters (via `excludedKeys`) are omitted from the list.
 *
 * @internal
 */
export function ParameterPicker({ parameters, excludedKeys, isLoading, maxListHeight, onAdd, onCancel, }) {
    const intl = useIntl();
    const [search, setSearch] = useState("");
    const deferredSearch = useDeferredValue(search.trim());
    const [selectedKeys, setSelectedKeys] = useState(() => new Set());
    const collator = useMemo(() => new Intl.Collator(intl.locale), [intl.locale]);
    const ungroupedLabel = intl.formatMessage(messages.ungrouped);
    const groups = useMemo(() => buildFilteredGroups(parameters, deferredSearch, ungroupedLabel, collator, excludedKeys), [parameters, deferredSearch, ungroupedLabel, collator, excludedKeys]);
    const toggle = useCallback((key) => {
        setSelectedKeys((prev) => {
            const next = new Set(prev);
            if (next.has(key)) {
                next.delete(key);
            }
            else {
                next.add(key);
            }
            return next;
        });
    }, []);
    const handleAdd = () => {
        onAdd(parameters.filter((parameter) => selectedKeys.has(objRefToString(parameter.ref))));
    };
    if (isLoading) {
        return (_jsx("div", { className: b(), "data-testid": "parameter-picker", children: _jsx("div", { className: e("loading"), "data-testid": "parameter-picker-loading", children: _jsx(LoadingSpinner, { className: "small" }) }) }));
    }
    return (_jsxs("div", { className: b(), "data-testid": "parameter-picker", children: [
            _jsx("div", { className: e("search"), "data-testid": "parameter-picker-search", children: _jsx(Input, { value: search, onChange: (value) => setSearch(String(value)), placeholder: intl.formatMessage(messages.searchPlaceholder), autofocus: true, clearOnEsc: true, isSearch: true, isSmall: true }) }), groups.length === 0 ? (_jsx("div", { className: e("empty"), "data-testid": "parameter-picker-empty", children: deferredSearch.length > 0
                    ? intl.formatMessage(messages.noResults)
                    : intl.formatMessage(messages.empty) })) : (_jsx("div", { className: e("list"), style: { maxHeight: maxListHeight }, children: groups.map((group) => (_jsx(ParameterPickerGroup, { tag: group.tag, parameters: group.parameters, selectedKeys: selectedKeys, onToggle: toggle }, group.tag))) })), _jsxs("div", { className: e("footer"), children: [
                    _jsx(UiButton, { variant: "secondary", size: "small", label: intl.formatMessage(messages.cancel), dataTestId: "parameter-picker-cancel", onClick: onCancel }), _jsx(UiButton, { variant: "primary", size: "small", label: intl.formatMessage(messages.add), dataTestId: "parameter-picker-add", onClick: handleAdd, isDisabled: selectedKeys.size === 0 })
                ] })
        ] }));
}
function ParameterPickerGroup({ tag, parameters, selectedKeys, onToggle }) {
    return (_jsxs("div", { className: e("group"), children: [
            _jsx("div", { className: e("group-header"), children: tag }), _jsx("ul", { className: e("items"), children: parameters.map((parameter) => {
                    const key = objRefToString(parameter.ref);
                    return (_jsx(ParameterPickerRow, { rowKey: key, title: parameter.title, isSelected: selectedKeys.has(key), onToggle: onToggle }, key));
                }) })
        ] }));
}
const ParameterPickerRow = memo(function ParameterPickerRow({ rowKey, title, isSelected, onToggle, }) {
    return (_jsx("li", { className: e("item"), "data-testid": "parameter-picker-item", children: _jsxs("label", { className: e("item-label"), children: [
                _jsx(UiCheckbox, { checked: isSelected, onChange: () => onToggle(rowKey) }), _jsx("span", { className: e("item-icon"), children: _jsx(UiIcon, { type: "parameter", size: 18, color: "currentColor" }) }), _jsx("span", { className: e("item-title"), children: title })
            ] }) }));
});
function buildFilteredGroups(parameters, search, ungroupedLabel, collator, excludedKeys) {
    const needle = search.toLowerCase();
    const tagged = new Map();
    const untagged = [];
    for (const parameter of parameters) {
        if (excludedKeys.has(objRefToString(parameter.ref))) {
            continue;
        }
        if (needle && !parameter.title.toLowerCase().includes(needle)) {
            continue;
        }
        const paramTagKeys = new Set();
        for (const raw of parameter.tags ?? []) {
            const trimmed = raw.trim();
            if (!trimmed) {
                continue;
            }
            const key = trimmed.toLowerCase();
            if (paramTagKeys.has(key)) {
                continue;
            }
            paramTagKeys.add(key);
            const bucket = tagged.get(key);
            if (bucket) {
                bucket.parameters.push(parameter);
            }
            else {
                tagged.set(key, { tag: trimmed, parameters: [parameter] });
            }
        }
        if (paramTagKeys.size === 0) {
            untagged.push(parameter);
        }
    }
    const byTitle = (a, b) => collator.compare(a.title, b.title);
    const byTag = (a, b) => collator.compare(a.tag, b.tag);
    const sortedTagged = Array.from(tagged.values())
        .sort(byTag)
        .map(({ tag, parameters: groupParameters }) => ({
        tag,
        parameters: groupParameters.sort(byTitle),
    }));
    if (untagged.length === 0) {
        return sortedTagged;
    }
    return [...sortedTagged, { tag: ungroupedLabel, parameters: untagged.sort(byTitle) }];
}
