import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useMemo } from "react";
import { TreeItemPicker } from "./TreeItemPicker";
function optionsFromSource(source) {
    if (!source)
        return [];
    return source
        .split(/[|;]/)
        .map((part) => part.trim())
        .filter(Boolean)
        .map((part) => {
        const [value, label] = part.includes("=")
            ? part.split("=")
            : [part, part];
        return {
            value: (value || "").trim(),
            label: (label || value || "").trim(),
        };
    });
}
const PLACEHOLDER_RE = /\[([^\]]+)\]/g;
function buildSegments(text) {
    const out = [];
    if (!text)
        return out;
    let last = 0;
    PLACEHOLDER_RE.lastIndex = 0;
    let match;
    while ((match = PLACEHOLDER_RE.exec(text)) !== null) {
        if (match.index > last) {
            out.push({ kind: "text", value: text.slice(last, match.index) });
        }
        const inner = match[1] ?? "";
        const parts = inner.split(",");
        const name = (parts[0] ?? "").trim();
        const last4 = (parts[parts.length - 1] ?? "").trim();
        out.push({
            kind: "param",
            name,
            placeholderLabel: last4 || name,
        });
        last = PLACEHOLDER_RE.lastIndex;
    }
    if (last < text.length) {
        out.push({ kind: "text", value: text.slice(last) });
    }
    return out;
}
export function RuleParameterInput({ element, values, disabled, onChange, prefix, stripLeadingWhere, }) {
    const text = useMemo(() => {
        const raw = element?.text ?? "";
        return stripLeadingWhere ? raw.replace(/^\s*where\s+/i, "") : raw;
    }, [element?.text, stripLeadingWhere]);
    const segments = useMemo(() => buildSegments(text), [text]);
    if (!element) {
        return null;
    }
    // Sitecore stores rule parameters as XML attributes (e.g. s:DataSource).
    // The placeholder name in the rule's Text field and the persisted attribute
    // name can drift in case across Sitecore versions, so look up and write
    // values case-insensitively to keep the UI in sync with what's stored.
    const findKey = (name) => Object.keys(values).find((key) => key.toLowerCase() === name.toLowerCase());
    const getValue = (name) => {
        const key = findKey(name);
        return key ? (values[key] ?? "") : "";
    };
    const setValue = (name, value) => {
        const existingKey = findKey(name);
        const key = existingKey ?? name;
        onChange({ ...values, [key]: value });
    };
    const placeholderNamesLower = new Set(segments
        .filter((s) => s.kind === "param")
        .map((s) => s.name.toLowerCase()));
    const orphanParameters = element.parameters.filter((p) => !placeholderNamesLower.has(p.name.toLowerCase()));
    if (segments.length === 0 && element.parameters.length === 0) {
        return (_jsx("div", { className: "text-2xs text-neutral-grey-50", children: "No parameters are required for this rule element." }));
    }
    return (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "text-neutral-grey-100 text-xs leading-7", children: [prefix, segments.map((segment, index) => {
                        if (segment.kind === "text") {
                            return _jsx("span", { children: segment.value }, index);
                        }
                        const parameter = element.parameters.find((p) => p.name.toLowerCase() === segment.name.toLowerCase());
                        return (_jsx(InlineParam, { parameter: parameter, fallbackName: segment.name, fallbackLabel: segment.placeholderLabel, value: getValue(segment.name), disabled: disabled, onChange: (next) => setValue(segment.name, next) }, index));
                    })] }), orphanParameters.length > 0 && (_jsx("div", { className: "border-border-default space-y-2 border-t pt-2", children: orphanParameters.map((parameter) => (_jsxs("label", { className: "block space-y-1", children: [_jsx("span", { className: "text-2xs text-neutral-grey-50 font-medium", children: parameter.title || parameter.name }), _jsx(InlineParam, { parameter: parameter, fallbackName: parameter.name, fallbackLabel: parameter.title || parameter.name, value: getValue(parameter.name), disabled: disabled, onChange: (next) => setValue(parameter.name, next), blockLayout: true })] }, parameter.name))) }))] }));
}
const INLINE_INPUT = "inline-flex h-6 max-w-full min-w-[3rem] rounded border border-border-default bg-white px-1.5 align-baseline text-xs leading-6 text-neutral-grey-100 outline-none focus:border-component-default";
const BLOCK_INPUT = "block w-full rounded border border-border-default bg-white badge-pad text-xs text-neutral-grey-100 outline-none focus:border-component-default";
function InlineParam({ parameter, fallbackName, fallbackLabel, value, disabled, onChange, blockLayout, }) {
    const type = (parameter?.type || "text").toLowerCase();
    const placeholder = fallbackLabel || parameter?.title || fallbackName;
    const sourceOptions = useMemo(() => optionsFromSource(parameter?.source), [parameter?.source]);
    const inputCls = blockLayout ? BLOCK_INPUT : INLINE_INPUT;
    const widthCh = Math.max(placeholder.length + 1, Math.min(value.length + 2, 32));
    if (type === "tree" && parameter?.rootItemId) {
        return (_jsx(TreeItemPicker, { value: value, rootItemId: parameter.rootItemId, disabled: disabled, placeholder: placeholder, inline: !blockLayout, onChange: onChange }));
    }
    if ((type === "droplink" || type === "enum") && sourceOptions.length > 0) {
        return (_jsxs("select", { className: inputCls, value: value, disabled: disabled, onChange: (event) => onChange(event.target.value), style: blockLayout ? undefined : { minWidth: `${widthCh}ch` }, children: [_jsxs("option", { value: "", children: [placeholder, "\u2026"] }), sourceOptions.map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value)))] }));
    }
    if (type === "operator") {
        const operatorOptions = parameter?.operators?.map((op) => ({
            value: op.id,
            label: op.displayName || op.name || op.id,
        })) ?? [];
        // The persisted value is a Sitecore GUID like {066602E2-...}. Match
        // case-insensitively and tolerate the braces-vs-no-braces variants so the
        // dropdown stays in sync with whatever shape the rule was saved in.
        const normalize = (v) => v
            .trim()
            .replace(/^\{|\}$/g, "")
            .toLowerCase();
        const normalizedValue = normalize(value);
        const matchedOption = operatorOptions.find((option) => normalize(option.value) === normalizedValue);
        const selectValue = matchedOption ? matchedOption.value : value;
        return (_jsxs("select", { className: inputCls, value: selectValue, disabled: disabled, onChange: (event) => onChange(event.target.value), style: blockLayout ? undefined : { minWidth: `${widthCh}ch` }, children: [_jsxs("option", { value: "", children: [placeholder, "\u2026"] }), operatorOptions.map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value)))] }));
    }
    if (type === "checkbox") {
        const checked = value === "1" || value.toLowerCase() === "true";
        if (blockLayout) {
            return (_jsx("input", { type: "checkbox", checked: checked, disabled: disabled, onChange: (event) => onChange(event.target.checked ? "1" : "0") }));
        }
        return (_jsxs("span", { className: "border-border-default inline-flex h-6 items-center gap-1 rounded border bg-white px-2 align-baseline text-xs leading-6", children: [_jsx("input", { type: "checkbox", checked: checked, disabled: disabled, onChange: (event) => onChange(event.target.checked ? "1" : "0") }), _jsx("span", { className: "text-2xs text-neutral-grey-50", children: placeholder })] }));
    }
    // text, item (without rootItemId), tree without rootItemId, and any
    // unknown type fall through to a plain inline text input.
    return (_jsx("input", { type: "text", className: inputCls, value: value, disabled: disabled, placeholder: placeholder, onChange: (event) => onChange(event.target.value), style: blockLayout ? undefined : { width: `${widthCh}ch` } }));
}
//# sourceMappingURL=RuleParameterInput.js.map