import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEditContext } from "../client/editContext";
import { Tooltip, TooltipContent, TooltipTrigger, } from "../../components/ui/tooltip";
import { Button } from "../../components/ui/button";
import { useState, useEffect, useRef } from "react";
import uuid from "react-uuid";
import { Popover, PopoverContent, PopoverTrigger, } from "../../components/ui/popover";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "../../components/ui/dropdown-menu";
import { cn } from "../../lib/utils";
import { ChevronDown, FileText, FileUp, FolderTree, RefreshCcw, Rocket, } from "lucide-react";
import { WorkboxItemsTable } from "../ui/WorkboxItemsTable";
import { SimpleIconButton } from "../ui/SimpleIconButton";
import { SearchInput } from "../../components/SearchInput";
import { ItemList } from "../ui/ItemList";
import { ScrollingContentTree } from "../ScrollingContentTree";
import { getLanguagesAndVersions, getWorkboxDescendants, } from "../services/contentService";
import { executeSearch } from "../services/searchService";
import { useDebouncedCallback } from "use-debounce";
import { toast } from "sonner";
import { Spinner } from "../ui/Spinner";
import { getItemDescriptor } from "../utils";
import { PublishItemDialog } from "../ui/PublishItemDialog";
export function Workbox() {
    const [mode, setMode] = useState("page");
    const [selectedRootItem, setSelectedRootItem] = useState();
    const [rootSelectorOpen, setRootSelectorOpen] = useState(false);
    const [descendantWorkboxItems, setDescendantWorkboxItems] = useState([]);
    const [loadingDescendants, setLoadingDescendants] = useState(false);
    const [openingPublishItemDialog, setOpeningPublishItemDialog] = useState(false);
    const [publishingWorkbox, setPublishingWorkbox] = useState(false);
    const [descendantsTotalCount, setDescendantsTotalCount] = useState(0);
    const [descendantsIsTruncated, setDescendantsIsTruncated] = useState(false);
    // Root selector search state
    const [query, setQuery] = useState("");
    const [searchResults, setSearchResults] = useState([]);
    const [loading, setLoading] = useState(false);
    const [hoveredItem, setHoveredItem] = useState();
    const inputRef = useRef(null);
    const editContext = useEditContext();
    // Load descendants when root item changes and mode is "root"
    useEffect(() => {
        if (mode === "root" && selectedRootItem) {
            loadDescendants(selectedRootItem);
        }
    }, [mode, selectedRootItem]);
    // Refresh the descendants list when one of this user's publish jobs reaches
    // a terminal state. Page mode is refreshed centrally in
    // useSocketMessageHandler so it also works while this sidebar is unmounted.
    useEffect(() => {
        if (mode !== "root" || !selectedRootItem)
            return;
        const unsubscribe = editContext?.addSocketMessageListener?.((message) => {
            if ((message.type === "operation:completed" ||
                message.type === "operation:failed") &&
                message.payload?.type === "publish-item") {
                loadDescendants(selectedRootItem);
            }
        });
        return unsubscribe;
    }, [mode, selectedRootItem, editContext?.addSocketMessageListener]);
    const loadDescendants = async (rootItem) => {
        setLoadingDescendants(true);
        try {
            const itemDescriptor = getItemDescriptor(rootItem);
            const result = await getWorkboxDescendants(itemDescriptor);
            if (result.data) {
                // Sort: non-final state items first, then by workflow commands count
                const sorted = result.data.items.sort((a, b) => {
                    if (a.isPublished === b.isPublished)
                        return ((b.workflowCommands?.length || 0) -
                            (a.workflowCommands?.length || 0));
                    return !a.isPublished || !a.isPublishable ? -1 : 1;
                });
                setDescendantWorkboxItems(sorted);
                setDescendantsTotalCount(result.data.totalCount);
                setDescendantsIsTruncated(result.data.isTruncated);
            }
        }
        catch (error) {
            console.error("Error loading workbox descendants:", error);
            toast.error("Failed to load workbox items");
        }
        finally {
            setLoadingDescendants(false);
        }
    };
    // Search handler for root selector
    const handleSearch = useDebouncedCallback(async (searchPrompt) => {
        if (!editContext || !searchPrompt) {
            setSearchResults([]);
            setLoading(false);
            return;
        }
        setLoading(true);
        const currentQuery = searchPrompt;
        // Check if it's a GUID
        const guidPattern = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
        if (guidPattern.test(searchPrompt)) {
            const item = await editContext.itemsRepository.getItem({
                id: searchPrompt,
                language: "en",
                version: 0,
            });
            if (item) {
                if (query === currentQuery) {
                    const resultItem = {
                        id: item.id,
                        name: item.name,
                        language: item.language || "en",
                        icon: item.icon,
                        path: item.path || item.name,
                        idPath: item.idPath,
                    };
                    setSearchResults([resultItem]);
                }
            }
            else {
                if (query === currentQuery) {
                    setSearchResults([]);
                }
            }
            setLoading(false);
            return;
        }
        // Regular search
        const result = await executeSearch({
            index: "master",
            query: searchPrompt,
            editContext,
            maxResults: 5,
        });
        if (query === currentQuery) {
            if (result.type == "success") {
                setSearchResults(result.data);
            }
            else {
                toast.error(result.response.statusText || "Error searching");
                setSearchResults([]);
            }
        }
        setLoading(false);
    }, 600);
    useEffect(() => {
        if (query) {
            setLoading(true);
            handleSearch(query);
        }
        else {
            setSearchResults([]);
            setLoading(false);
        }
    }, [query]);
    useEffect(() => {
        if (inputRef.current && rootSelectorOpen) {
            inputRef.current.focus();
        }
    }, [rootSelectorOpen]);
    const loadRootItem = async (selectedItem) => {
        if (Array.isArray(selectedItem) && selectedItem[0]) {
            selectedItem = selectedItem[0];
        }
        if (!selectedItem)
            return;
        const itemDescriptor = selectedItem;
        const item = await editContext?.itemsRepository.getItem({
            id: itemDescriptor.id,
            language: itemDescriptor.language,
            version: itemDescriptor.version || 0,
        });
        if (item) {
            setSelectedRootItem(item);
            setRootSelectorOpen(false);
            setQuery("");
            setSearchResults([]);
        }
    };
    if (!editContext)
        return null;
    // Determine which items to display based on mode
    const displayItems = mode === "page" ? editContext.workboxItems : descendantWorkboxItems;
    const currentPublishItem = mode === "root" ? selectedRootItem : editContext.item;
    const currentPublishDescriptor = mode === "root"
        ? currentPublishItem
            ? getItemDescriptor(currentPublishItem)
            : undefined
        : editContext.currentItemDescriptor;
    const currentPublishWorkboxItem = displayItems.find((item) => item.item.id === currentPublishDescriptor?.id &&
        item.item.language === currentPublishDescriptor?.language &&
        item.item.version === currentPublishDescriptor?.version);
    const isLoadingDisplayItems = mode === "page" ? editContext.isWorkboxLoading : loadingDescendants;
    const publishableWorkboxItems = displayItems.filter((item) => item.isPublishable && !item.isPublished);
    const publishableWorkboxItemCount = publishableWorkboxItems.length;
    const isPublishActionBusy = openingPublishItemDialog || publishingWorkbox;
    const canPublishCurrentItem = !!currentPublishDescriptor &&
        !isPublishActionBusy &&
        !editContext.readonly &&
        (mode !== "root" ||
            (!!currentPublishItem &&
                currentPublishItem.canWriteItem &&
                currentPublishItem.canWriteLanguage));
    const canPublishWorkbox = !isPublishActionBusy &&
        !editContext.readonly &&
        !isLoadingDisplayItems &&
        publishableWorkboxItemCount > 0;
    const publishItemTooltip = !currentPublishDescriptor
        ? mode === "root"
            ? "Select a root item to publish as an item."
            : "No current item is available to publish as an item."
        : currentPublishWorkboxItem?.workflowState &&
            !currentPublishWorkboxItem.isPublishable
            ? `Open publish options for this item. It is currently in "${currentPublishWorkboxItem.workflowState}".`
            : "Publish the current item.";
    const publishWorkboxTooltip = editContext.readonly
        ? "Read-only mode cannot start publishing."
        : isLoadingDisplayItems
            ? "Wait for the workbox to finish loading."
            : publishableWorkboxItemCount === 0
                ? "No unpublished publishable workbox items to publish."
                : `Smart publish ${publishableWorkboxItemCount} unpublished publishable workbox item${publishableWorkboxItemCount === 1 ? "" : "s"}.`;
    const publishItemMenuLabel = "Publish current item...";
    const publishCurrentItem = async () => {
        if (!currentPublishDescriptor || !canPublishCurrentItem) {
            return;
        }
        setOpeningPublishItemDialog(true);
        try {
            const item = currentPublishItem ||
                (await editContext.itemsRepository.getItem(currentPublishDescriptor));
            if (!item) {
                toast.error("Failed to load item for publishing.");
                return;
            }
            // The descendants list refreshes when the publish job completes (socket
            // listener below) -- refreshing on dialog close would show stale state.
            await editContext.openDialog(PublishItemDialog, { item });
        }
        catch {
            toast.error("Failed to open publish dialog.");
        }
        finally {
            setOpeningPublishItemDialog(false);
        }
    };
    const publishWorkboxItems = async () => {
        if (!canPublishWorkbox)
            return;
        const fallbackLanguage = currentPublishDescriptor?.language ||
            editContext.currentItemDescriptor?.language;
        const publishCandidates = publishableWorkboxItems.map((workboxItem) => ({
            name: workboxItem.name,
            descriptor: {
                ...workboxItem.item,
                language: workboxItem.item.language || fallbackLanguage,
            },
        }));
        const publishable = publishCandidates.filter((candidate) => !!candidate.descriptor.language);
        const publishableItems = publishable.map((candidate) => candidate.descriptor);
        const skippedCount = publishCandidates.length - publishableItems.length;
        const firstPublishable = publishable[0];
        if (!firstPublishable) {
            toast("No unpublished publishable workbox items to publish.");
            return;
        }
        const firstPublishableItem = firstPublishable.descriptor;
        setPublishingWorkbox(true);
        try {
            // Publishing targets are configured per source database, so one lookup
            // covers every workbox item.
            const result = await getLanguagesAndVersions(firstPublishableItem, {
                includePublishingTargets: true,
            });
            if (result.type !== "success" || !result.data) {
                toast.error("Failed to load publishing targets.");
                return;
            }
            const targetDatabases = (result.data.publishingTargets || []).map((target) => target.targetDatabase);
            if (targetDatabases.length === 0) {
                toast.error("No publishing targets are available.");
                return;
            }
            const languages = [
                ...new Set(publishableItems.map((item) => item.language)),
            ];
            const operation = {
                type: "publish-item",
                id: uuid(),
                date: new Date().toISOString(),
                title: publishableItems.length === 1
                    ? `Publish ${firstPublishable.name}`
                    : `Publish ${publishableItems.length} workbox items`,
                description: `smart workbox publish to ${targetDatabases.length} target(s)`,
                mainItem: firstPublishableItem,
                item: firstPublishableItem,
                items: publishableItems,
                targetDatabases,
                languages,
                publishMode: "smart",
                includeSubitems: false,
                publishRelatedItems: false,
                canUndo: false,
            };
            try {
                const result = await editContext.operations.publishItem(operation);
                if (result.errorMessage || result.executionStatus === "failed") {
                    toast.error("Failed to start publishing workbox items.");
                    return;
                }
            }
            catch {
                toast.error("Failed to start publishing workbox items.");
                return;
            }
            toast.success(`Started publishing ${publishableItems.length} workbox item${publishableItems.length === 1 ? "" : "s"}${skippedCount > 0 ? ` (${skippedCount} skipped)` : ""}.`);
        }
        finally {
            setPublishingWorkbox(false);
        }
    };
    const hasResults = searchResults.length > 0;
    return (_jsxs("div", { className: "flex h-full flex-col", children: [_jsxs("div", { className: "border-border-default flex items-center gap-2 border-b p-2", children: [_jsxs("div", { className: "flex gap-1", children: [_jsx(SimpleIconButton, { icon: _jsx(FileText, { className: "h-4 w-4", strokeWidth: 1 }), label: "Current Page", selected: mode === "page", onClick: () => setMode("page"), size: "small" }), _jsx(SimpleIconButton, { icon: _jsx(FolderTree, { className: "h-4 w-4", strokeWidth: 1 }), label: "Browse Descendants", selected: mode === "root", onClick: () => setMode("root"), size: "small" }), mode === "root" && selectedRootItem && (_jsx(SimpleIconButton, { icon: _jsx(RefreshCcw, { className: cn("h-4 w-4", loadingDescendants && "animate-spin"), strokeWidth: 1 }), label: "Refresh", onClick: () => loadDescendants(selectedRootItem), size: "small", "data-testid": "refresh-workbox-button" }))] }), mode === "root" && (_jsxs(Popover, { open: rootSelectorOpen, onOpenChange: setRootSelectorOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("div", { className: "border-border-default badge-pad hover:bg-neutral-grey-5 flex-1 cursor-pointer rounded border text-xs", "data-testid": "root-selector-button", children: selectedRootItem ? (_jsxs("div", { className: "truncate", children: [_jsx("span", { className: "font-medium", children: selectedRootItem.name }), _jsx("span", { className: "text-neutral-grey-50 ml-1", children: selectedRootItem.path })] })) : (_jsx("span", { className: "text-neutral-grey-50", children: "Select root item..." })) }) }), _jsx(PopoverContent, { className: "w-96 p-0", align: "start", children: _jsxs("div", { className: "flex h-[50vh] max-h-[400px] max-w-96 min-w-96 flex-col overflow-hidden", children: [_jsx("div", { className: "border-border-default border-b p-2", children: _jsx(SearchInput, { value: query, onChange: setQuery, ref: inputRef, placeholder: "Search content...", loading: loading, className: "w-full", spinnerStyle: { width: "18px", height: "18px" } }) }), _jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [hasResults && (_jsx("div", { className: "border-border-default max-h-[50%] shrink-0 overflow-auto border-b", children: _jsx("div", { className: "p-2", children: _jsx(ItemList, { items: searchResults, onItemHover: setHoveredItem, onItemClick: loadRootItem, maxItems: 20, className: "max-h-full overflow-auto" }) }) })), _jsx("div", { className: "relative min-h-0 flex-1", children: _jsx("div", { className: "absolute inset-0 overflow-auto", children: _jsx(ScrollingContentTree, { hideRootNodes: true, selectedItemId: hoveredItem?.id ?? selectedRootItem?.id, onSelectionChange: loadRootItem }) }) })] })] }) })] })), _jsxs("div", { className: "ml-auto flex h-7 shrink-0 items-stretch", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { className: "flex", children: _jsx(Button, { size: "xs", className: "h-7 rounded-r-none shadow-none", onClick: publishWorkboxItems, disabled: !canPublishWorkbox, "data-testid": "publish-workbox-button", children: publishingWorkbox ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { size: "sm" }), " Publishing..."] })) : (_jsxs(_Fragment, { children: [_jsx(Rocket, { className: "h-3.5 w-3.5", strokeWidth: 1 }), "Publish workbox items (", publishableWorkboxItemCount, ")"] })) }) }) }), _jsx(TooltipContent, { children: publishWorkboxTooltip })] }), _jsxs(DropdownMenu, { children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { size: "iconXs", className: "h-7 rounded-l-none border-l border-white/25 shadow-none", disabled: !canPublishCurrentItem, "data-testid": "publish-actions-menu-trigger", "aria-label": "More publish actions", children: _jsx(ChevronDown, { className: "h-3.5 w-3.5", strokeWidth: 1 }) }) }) }), _jsx(TooltipContent, { children: "More publish actions" })] }), _jsx(DropdownMenuContent, { align: "end", className: "w-48", children: _jsxs(DropdownMenuItem, { disabled: !canPublishCurrentItem, onClick: publishCurrentItem, title: publishItemTooltip, "data-testid": "publish-item-button", children: [openingPublishItemDialog ? (_jsx(Spinner, { size: "sm" })) : (_jsx(FileUp, { className: "h-3.5 w-3.5", strokeWidth: 1 })), openingPublishItemDialog ? "Opening..." : publishItemMenuLabel] }) })] })] })] }), _jsx("div", { className: "flex-1 overflow-auto", children: mode === "root" && !selectedRootItem ? (_jsx("div", { className: "text-neutral-grey-50 flex h-full items-center justify-center text-xs", children: "Select a root item to view descendants" })) : (_jsx(WorkboxItemsTable, { items: displayItems, isLoading: isLoadingDisplayItems, emptyMessage: mode === "page"
                        ? "No items to display"
                        : "No items pending workflow approval", headerNotice: mode === "root" && descendantsIsTruncated ? (_jsxs("div", { className: "border-component-shared bg-component-shared-drop-zone text-component-shared border-b px-3 py-2 text-xs", children: ["Showing ", descendantWorkboxItems.length, " of", " ", descendantsTotalCount, " items pending workflow approval"] })) : undefined, onAfterWorkflowCommand: mode === "root" && selectedRootItem
                        ? () => loadDescendants(selectedRootItem)
                        : undefined })) })] }));
}
//# sourceMappingURL=Workbox.js.map