import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useMemo, useState } from "react";
import { ChevronDown, X } from "lucide-react";
import ContentTree from "../ContentTree";
import { useEditContext } from "../client/editContext";
import { fetchItemStubs } from "../services/contentService";
import { Popover, PopoverContent, PopoverTrigger, } from "../../components/ui/popover";
import { Button } from "../../components/ui/button";
function normalizeLanguage(language) {
    if (!language || language === "*" || language === "mixed")
        return "en";
    return language;
}
function isLikelyGuid(value) {
    return /^[{(]?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}[)}]?$/i.test(value.trim());
}
export function TreeItemPicker({ value, rootItemId, language, disabled, placeholder = "Select item", inline, onChange, }) {
    const editContext = useEditContext();
    const effectiveLanguage = useMemo(() => normalizeLanguage(language ?? editContext?.currentItemDescriptor?.language ?? "en"), [language, editContext?.currentItemDescriptor?.language]);
    const [open, setOpen] = useState(false);
    const [stub, setStub] = useState();
    const [resolving, setResolving] = useState(false);
    const [fallbackStub, setFallbackStub] = useState();
    const currentItemId = editContext?.currentItemDescriptor?.id;
    useEffect(() => {
        let cancelled = false;
        setStub(undefined);
        if (!value || !isLikelyGuid(value))
            return;
        setResolving(true);
        fetchItemStubs([{ id: value, language: effectiveLanguage, version: 1 }])
            .then((stubs) => {
            if (cancelled)
                return;
            setStub(stubs?.[0]);
        })
            .catch(() => {
            if (!cancelled)
                setStub(undefined);
        })
            .finally(() => {
            if (!cancelled)
                setResolving(false);
        });
        return () => {
            cancelled = true;
        };
    }, [value, effectiveLanguage]);
    // Fetch the current item's stub so we can expand to it when no value is selected.
    useEffect(() => {
        let cancelled = false;
        setFallbackStub(undefined);
        if (!currentItemId || !isLikelyGuid(currentItemId))
            return;
        fetchItemStubs([
            { id: currentItemId, language: effectiveLanguage, version: 1 },
        ])
            .then((stubs) => {
            if (cancelled)
                return;
            setFallbackStub(stubs?.[0]);
        })
            .catch(() => {
            if (!cancelled)
                setFallbackStub(undefined);
        });
        return () => {
            cancelled = true;
        };
    }, [currentItemId, effectiveLanguage]);
    const label = (() => {
        if (!value)
            return placeholder;
        if (resolving && !stub)
            return "Loading…";
        if (stub)
            return stub.displayName?.trim() || stub.name || value;
        return value;
    })();
    const subtitle = stub?.path;
    const hasValue = !!value;
    // When a value is selected, expand to it. Otherwise fall back to the item
    // currently being edited so its branch is visible by default. As a last
    // resort, just expand the root.
    const expandIdPath = stub?.idPath || fallbackStub?.idPath || `/${rootItemId}`;
    if (inline) {
        const triggerLabel = !value
            ? placeholder
            : resolving && !stub
                ? "Loading…"
                : stub?.displayName?.trim() || stub?.name || value;
        return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("button", { type: "button", disabled: disabled, title: subtitle || (hasValue ? value : undefined), className: `inline-flex h-6 max-w-[16rem] items-center gap-1 rounded border px-1.5 align-baseline text-xs leading-6 transition-colors ${hasValue
                            ? "border-component-default/40 bg-feedback-blue-light text-neutral-grey-100 hover:bg-feedback-blue-light"
                            : "border-border-default text-neutral-grey-50 hover:border-border-default hover:text-neutral-grey-100 border-dashed bg-white"} disabled:cursor-not-allowed disabled:opacity-60`, children: [_jsx("span", { className: "truncate", children: triggerLabel }), _jsx(ChevronDown, { className: "size-3 shrink-0 opacity-60" })] }) }), _jsxs(PopoverContent, { align: "start", sideOffset: 4, className: "w-[28rem] max-w-[calc(100vw-2rem)] p-0", children: [_jsxs("div", { className: "border-border-default text-2xs text-neutral-grey-50 flex items-center justify-between gap-2 border-b px-3 py-2", children: [_jsx("span", { children: "Select an item" }), hasValue && (_jsx("button", { type: "button", className: "badge-pad-sm text-2xs text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-100 rounded", onClick: () => {
                                        onChange("");
                                        setOpen(false);
                                    }, children: "Clear" }))] }), _jsx("div", { className: "max-h-80 overflow-auto p-2", children: _jsx(ContentTree, { language: effectiveLanguage, selectionMode: "single", selectedItemIds: value ? [value] : [], rootItemIds: [rootItemId], expandIdPath: expandIdPath, scrollToSelected: true, onSelectionChange: (items) => {
                                    const picked = items?.[0];
                                    if (picked?.id) {
                                        onChange(picked.id);
                                        setOpen(false);
                                    }
                                } }) })] })] }));
    }
    return (_jsxs("div", { className: "flex items-stretch gap-1", children: [_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { type: "button", variant: "outline", size: "xs", disabled: disabled, className: "min-w-0 flex-1 justify-between gap-2 px-2 font-normal", children: [_jsxs("span", { className: "flex min-w-0 flex-col items-start text-left", children: [_jsx("span", { className: `truncate text-xs ${hasValue ? "text-neutral-grey-100" : "text-neutral-grey-50"}`, children: label }), subtitle && (_jsx("span", { className: "text-2xs text-neutral-grey-50 truncate", children: subtitle }))] }), _jsx(ChevronDown, { className: "text-neutral-grey-50 size-3 shrink-0" })] }) }), _jsxs(PopoverContent, { align: "start", sideOffset: 4, className: "w-[28rem] max-w-[calc(100vw-2rem)] p-0", children: [_jsx("div", { className: "border-border-default text-2xs text-neutral-grey-50 border-b px-3 py-2", children: "Select an item" }), _jsx("div", { className: "max-h-80 overflow-auto p-2", children: _jsx(ContentTree, { language: effectiveLanguage, selectionMode: "single", selectedItemIds: value ? [value] : [], rootItemIds: [rootItemId], expandIdPath: expandIdPath, scrollToSelected: true, onSelectionChange: (items) => {
                                        const picked = items?.[0];
                                        if (picked?.id) {
                                            onChange(picked.id);
                                            setOpen(false);
                                        }
                                    } }) })] })] }), hasValue && !disabled && (_jsx(Button, { type: "button", size: "xxs", variant: "ghost", "aria-label": "Clear selection", title: "Clear selection", className: "px-1", onClick: () => onChange(""), children: _jsx(X, { className: "size-3" }) }))] }));
}
//# sourceMappingURL=TreeItemPicker.js.map