import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { WizardIcon } from "../ui/Icons";
import { cn } from "../../lib/utils";
import { formatDate } from "../utils";
import { useEditContext, useFieldsEditContext } from "../client/editContext";
import { Loader2, AlertCircle, RotateCcw, Info } from "lucide-react";
import { DeleteIcon } from "../../components/ui/delete-icon";
import { Checkbox } from "../../components/ui/checkbox";
import { useEffect, useState } from "react";
import { getEditOperation } from "../services/editService";
const COMMON_DETAIL_KEYS = new Set([
    "type",
    "date",
    "id",
    "user",
    "undone",
    "sessionId",
    "title",
    "description",
    "canUndo",
    "canRedo",
    "undoSupported",
    "undoNotSupportedReason",
    "focus",
    "mainItem",
    "mainItemPath",
    "agentId",
    "toolCallId",
    "executionStatus",
    "statusMessage",
    "progress",
    "executionStarted",
    "executionCompleted",
    "errorMessage",
]);
const MAX_DETAIL_VALUE_LENGTH = 1600;
function formatDetailLabel(key) {
    return key
        .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
        .replace(/[-_]+/g, " ")
        .replace(/\b\w/g, (letter) => letter.toUpperCase());
}
function isEmptyDetailValue(value) {
    return (value === undefined ||
        value === null ||
        value === "" ||
        (Array.isArray(value) && value.length === 0));
}
function formatDetailValue(value) {
    let text = typeof value === "string" ? value : JSON.stringify(value, null, 2) || "";
    if (text.length > MAX_DETAIL_VALUE_LENGTH) {
        text = `${text.slice(0, MAX_DETAIL_VALUE_LENGTH)}...`;
    }
    return text;
}
function getOperationDate(o) {
    if (!o.date) {
        return "";
    }
    const date = new Date(o.date);
    if (isNaN(date.getTime())) {
        return "";
    }
    return formatDate(date);
}
function OperationDetailsPanel({ operation, loading, error, }) {
    const specificDetails = operation
        ? Object.entries(operation).filter(([key, value]) => !COMMON_DETAIL_KEYS.has(key) && !isEmptyDetailValue(value))
        : [];
    return (_jsx("div", { className: "border-border-default bg-neutral-grey-5/50 mt-2 rounded border p-2", "data-testid": "history-operation-details", children: loading ? (_jsxs("div", { className: "text-neutral-grey-50 flex items-center gap-2 text-[10px]", children: [_jsx(Loader2, { strokeWidth: 1, className: "h-3 w-3 animate-spin" }), "Loading details..."] })) : error ? (_jsx("div", { className: "text-feedback-red text-[10px]", children: error })) : operation ? (_jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "grid grid-cols-[72px_minmax(0,1fr)] gap-x-2 gap-y-1 text-[10px]", children: [_jsx("div", { className: "text-neutral-grey-50", children: "ID" }), _jsx("div", { className: "text-neutral-grey-100 min-w-0 truncate font-mono", children: operation.id }), _jsx("div", { className: "text-neutral-grey-50", children: "Type" }), _jsx("div", { className: "text-neutral-grey-100 min-w-0 truncate", children: operation.type }), operation.date && (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-neutral-grey-50", children: "Date" }), _jsx("div", { className: "text-neutral-grey-100 min-w-0 truncate", children: getOperationDate(operation) })] })), operation.mainItemPath && (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-neutral-grey-50", children: "Item" }), _jsx("div", { className: "text-neutral-grey-100 min-w-0 truncate", title: operation.mainItemPath, children: operation.mainItemPath })] })), operation.mainItem && (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-neutral-grey-50", children: "Version" }), _jsxs("div", { className: "text-neutral-grey-100 min-w-0 truncate", children: [operation.mainItem.language, ", v", operation.mainItem.version] })] })), operation.user?.name && (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-neutral-grey-50", children: "User" }), _jsx("div", { className: "text-neutral-grey-100 min-w-0 truncate", children: operation.user.name })] })), operation.sessionId && (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-neutral-grey-50", children: "Session" }), _jsx("div", { className: "text-neutral-grey-100 min-w-0 truncate font-mono", children: operation.sessionId })] })), operation.undoSupported === false && (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-neutral-grey-50", children: "Undo" }), _jsx("div", { className: "text-neutral-grey-100 min-w-0", children: operation.undoNotSupportedReason || "Not undoable" })] })), operation.executionStatus &&
                            operation.executionStatus !== "completed" && (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-neutral-grey-50", children: "Status" }), _jsxs("div", { className: "text-neutral-grey-100 min-w-0", children: [operation.executionStatus, operation.statusMessage
                                            ? ` - ${operation.statusMessage}`
                                            : ""] })] }))] }), specificDetails.length > 0 && (_jsx("div", { className: "border-border-default space-y-1 border-t pt-2", children: specificDetails.map(([key, value]) => (_jsxs("div", { className: "min-w-0", children: [_jsx("div", { className: "text-neutral-grey-50 mb-0.5 text-[10px]", children: formatDetailLabel(key) }), _jsx("pre", { className: "border-border-default bg-background text-neutral-grey-100 max-h-40 overflow-auto rounded border p-1.5 font-mono text-[10px] leading-snug whitespace-pre-wrap", children: formatDetailValue(value) })] }, key))) }))] })) : null }));
}
export function OperationItem({ operation: o, index: i, showUserName = false, showDescription = true, selected = false, onSelect, showCheckbox = false, hidePath = false, showLanguage = false, }) {
    const editContext = useEditContext();
    const fieldsContext = useFieldsEditContext();
    const [isDeleted, setIsDeleted] = useState(null);
    const [detailsOpen, setDetailsOpen] = useState(false);
    const [details, setDetails] = useState();
    const [detailsLoading, setDetailsLoading] = useState(false);
    const [detailsError, setDetailsError] = useState();
    const isExecuting = o.executionStatus === "executing";
    const isFailed = o.executionStatus === "failed";
    const isCompleted = o.executionStatus === "completed";
    // Check if the item is deleted (lazily, only for operations that reference an item)
    useEffect(() => {
        if (!o.mainItem || isDeleted !== null) {
            return;
        }
        // Skip check for delete-items operations as they're about deletion, not deleted items
        if (o.type === "delete-items") {
            setIsDeleted(false);
            return;
        }
        // Check if item exists by trying to fetch it
        const checkItemExists = async () => {
            try {
                if (editContext?.itemsRepository && o.mainItem) {
                    const items = await editContext.itemsRepository.getItems([
                        o.mainItem,
                    ]);
                    setIsDeleted(items.length === 0 || items[0] === undefined);
                }
            }
            catch (error) {
                // If fetching fails, assume item is deleted
                setIsDeleted(true);
            }
        };
        // Debounce the check to avoid too many requests
        const timeoutId = setTimeout(checkItemExists, 100);
        return () => clearTimeout(timeoutId);
    }, [o.mainItem, o.type, editContext?.itemsRepository, isDeleted]);
    function getOperationColor(type) {
        // Failed operations get red border
        if (isFailed)
            return "border-l-red-600";
        // Executing operations get a pulsing blue border
        if (isExecuting)
            return "border-l-blue-400";
        switch (type) {
            case "edit-field":
            case "update-rendering-parameters":
            case "update-rendering-rules":
                return "border-l-blue-500";
            case "create-item":
            case "add-component":
            case "add-version":
                return "border-l-green-500";
            case "move-component":
            case "move-items":
            case "rename-item":
                return "border-l-orange-500";
            case "delete-items":
            case "remove-component":
            case "remove-version":
                return "border-l-red-500";
            default:
                return "border-l-gray-400";
        }
    }
    function isOperationOnCurrentItem(o) {
        if (!editContext?.currentItemDescriptor || !o.mainItem) {
            return false;
        }
        const current = editContext.currentItemDescriptor;
        return (current.id === o.mainItem.id &&
            current.language === o.mainItem.language &&
            current.version === o.mainItem.version);
    }
    const isOnCurrentItem = isOperationOnCurrentItem(o);
    const colorClass = getOperationColor(o.type);
    function getSubpath(description, mainItemPath) {
        if (!mainItemPath || !description.startsWith(mainItemPath)) {
            return description;
        }
        const sub = description.substring(mainItemPath.length);
        if (sub === "" || sub === "/" || sub === "\\") {
            return "";
        }
        // Ensure it's a real sub-item (starts with path separator)
        if (sub.startsWith("/") || sub.startsWith("\\")) {
            return sub;
        }
        return description;
    }
    // Determine if item is deleted (true if explicitly checked and deleted, false otherwise)
    const itemIsDeleted = isDeleted === true;
    const className = cn("border-l-[3px] border-b border-border-default p-2 flex flex-col text-xs hover:bg-neutral-grey-5 font-light group", colorClass, {
        "text-neutral-grey-50 opacity-60": o.undone,
        "cursor-pointer": o.focus || (!isOnCurrentItem && o.mainItem && !itemIsDeleted),
        "bg-feedback-blue-light/50": isExecuting || selected,
        "bg-feedback-red-light/50": isFailed,
        "text-neutral-grey-50": itemIsDeleted && !o.undone,
        "opacity-75": itemIsDeleted && !o.undone,
    });
    const handleFocus = () => {
        if (o.focus) {
            const focusComponents = o.focus.split(":");
            if (focusComponents.length > 0) {
                editContext?.select([focusComponents[0]]);
            }
            if (focusComponents.length > 1 &&
                focusComponents[1] &&
                focusComponents[0]) {
                fieldsContext?.setFocusedField({
                    item: {
                        id: focusComponents[0],
                        language: editContext?.page?.item.language ||
                            editContext?.currentItemDescriptor?.language ||
                            "en",
                        version: editContext?.page?.item.version ||
                            editContext?.currentItemDescriptor?.version ||
                            0,
                    },
                    fieldId: focusComponents[1],
                }, false);
            }
        }
    };
    const handleClick = async (e) => {
        e.stopPropagation();
        // Don't navigate to deleted items
        if (itemIsDeleted) {
            return;
        }
        // If the operation is on a different item, navigate to it first
        if (!isOnCurrentItem && o.mainItem && editContext?.loadItem) {
            await editContext.loadItem(o.mainItem);
        }
        // Then handle focus if specified
        handleFocus();
    };
    const handleDetailsClick = async (e) => {
        e.stopPropagation();
        if (detailsOpen) {
            setDetailsOpen(false);
            return;
        }
        setDetailsOpen(true);
        if (details || detailsLoading) {
            return;
        }
        setDetailsError(undefined);
        setDetailsLoading(true);
        const result = await getEditOperation(o.id);
        setDetailsLoading(false);
        if (result.type === "success" && result.data) {
            setDetails(result.data);
            return;
        }
        const message = result.details || result.summary || "Failed to load operation details";
        setDetailsError(message);
    };
    return (_jsxs("div", { className: className, onClick: handleClick, "data-testid": "history-operation-item", "data-operation-id": o.id, "data-operation-title": o.title, "data-main-item-path": o.mainItemPath || "", children: [_jsxs("div", { className: "flex items-start gap-2", children: [showCheckbox && !o.undone && !isExecuting && (_jsx("div", { className: "mt-0.5", onClick: (e) => e.stopPropagation(), children: _jsx(Checkbox, { checked: selected, onCheckedChange: (checked) => onSelect?.(!!checked), "aria-label": `Select ${o.title}`, "data-testid": "history-operation-checkbox" }) })), _jsx("div", { className: "min-w-0 flex-1", children: _jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_auto] items-start gap-2", children: [_jsxs("div", { className: "flex min-w-0 gap-1", children: [isExecuting && (_jsx(Loader2, { strokeWidth: 1, className: "text-feedback-blue h-4 w-4 shrink-0 animate-spin" })), isFailed && (_jsx(AlertCircle, { strokeWidth: 1, className: "text-feedback-red h-4 w-4 shrink-0" })), !isExecuting && !isFailed && itemIsDeleted && (_jsx("span", { title: "Item has been deleted", children: _jsx(DeleteIcon, { size: "lg", className: cn("shrink-0", o.undone
                                                    ? "text-neutral-grey-15"
                                                    : "text-neutral-grey-50") }) })), !isExecuting &&
                                            !isFailed &&
                                            !itemIsDeleted &&
                                            (o.user?.agentId || o.agentId) && (_jsx(WizardIcon, { className: cn("h-4 w-4 shrink-0", o.undone
                                                ? "text-neutral-grey-15"
                                                : "text-neutral-grey-50") })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-1 pr-1", children: [_jsx("span", { className: "min-w-0 flex-1 truncate", children: o.type === "edit-field" &&
                                                                o.fieldName
                                                                ? `Edit ${o.fieldName}`
                                                                : o.title }), o.mainItem?.version > 0 && (_jsxs("span", { className: "text-neutral-grey-50 shrink-0 text-[10px]", children: ["v", o.mainItem.version] })), showLanguage && o.mainItem?.language && (_jsx("span", { className: "bg-neutral-grey-5 text-neutral-grey-50 shrink-0 rounded px-1 py-0.5 text-[10px]", children: o.mainItem.language })), !o.undone && o.undoSupported === false && !isExecuting && (_jsx("span", { className: "bg-neutral-grey-5 text-neutral-grey-50 shrink-0 rounded px-1 py-0.5 text-[10px]", title: o.undoNotSupportedReason || "Not undoable", children: "Not undoable" })), isExecuting && (_jsx("span", { className: "bg-feedback-blue-light text-feedback-blue shrink-0 rounded px-1 py-0.5 text-[10px]", children: "Running" })), isFailed && (_jsx("span", { className: "bg-feedback-red-light text-feedback-red shrink-0 rounded px-1 py-0.5 text-[10px]", children: "Failed" })), (o.user?.agentId || o.agentId) && (_jsx("button", { onClick: (e) => {
                                                                e.stopPropagation();
                                                                const agentId = o.user?.agentId || o.agentId;
                                                                // Open agents panel and load the agent (openAgent will load from history if needed)
                                                                if (editContext?.isMobile) {
                                                                    editContext.openSidebar("agents-panel");
                                                                }
                                                                else {
                                                                    editContext?.setShowAgentsPanel(true);
                                                                }
                                                                const dispatchOpenAgent = () => {
                                                                    window.dispatchEvent(new CustomEvent("editor:openAgent", {
                                                                        detail: { agentId },
                                                                    }));
                                                                };
                                                                if (editContext?.isMobile) {
                                                                    // 500ms delay on mobile to ensure the sidebar is mounted and listening.
                                                                    setTimeout(dispatchOpenAgent, 500);
                                                                }
                                                                else {
                                                                    dispatchOpenAgent();
                                                                }
                                                            }, className: "text-feedback-blue shrink-0 text-[10px] hover:underline", title: "Open agent", children: "[Agent]" })), _jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-0.5", children: [_jsx("button", { onClick: handleDetailsClick, className: cn("text-neutral-grey-50 hover:bg-neutral-grey-10 hover:text-neutral-grey-100 rounded p-0.5 transition-colors", detailsOpen &&
                                                                        "bg-neutral-grey-10 text-neutral-grey-100"), title: detailsOpen ? "Hide details" : "Show details", "aria-label": detailsOpen ? "Hide details" : "Show details", "aria-expanded": detailsOpen, "data-testid": "history-operation-details-button", children: detailsLoading ? (_jsx(Loader2, { strokeWidth: 1, className: "h-3 w-3 animate-spin" })) : (_jsx(Info, { className: "h-3 w-3", strokeWidth: 1 })) }), !o.undone && o.undoSupported === true && !isExecuting && (_jsx("button", { onClick: (e) => {
                                                                        e.stopPropagation();
                                                                        editContext?.operations.undoOperations([o.id]);
                                                                    }, className: "text-neutral-grey-50 hover:bg-neutral-grey-10 hover:text-neutral-grey-100 rounded p-0.5 opacity-0 transition-opacity group-hover:opacity-100", title: "Undo this operation", "data-testid": "history-operation-undo-button", children: _jsx(RotateCcw, { className: "h-3 w-3", strokeWidth: 1 }) }))] })] }), showDescription && o.description && (_jsx("div", { className: "text-neutral-grey-50 mt-0.5 text-[10px]", children: getSubpath(o.description, o.mainItemPath) })), !hidePath && o.mainItemPath && (_jsx("div", { className: "text-neutral-grey-50 mt-0.5 truncate text-[10px]", title: o.mainItemPath, children: o.mainItemPath }))] })] }), _jsxs("div", { className: "shrink-0 text-right", children: [_jsx("div", { className: "text-neutral-grey-50 text-[10px] leading-tight whitespace-nowrap tabular-nums", children: getOperationDate(o) }), showUserName && !o.user?.agentId && !o.agentId && (_jsx("div", { className: "text-neutral-grey-50 text-[10px] leading-tight", children: o.user?.name }))] })] }) })] }), isExecuting && o.progress !== undefined && (_jsxs("div", { className: "mt-1.5 w-full", children: [_jsxs("div", { className: "bg-neutral-grey-10 relative h-1 w-full overflow-hidden rounded-full", children: [_jsx("div", { className: "bg-feedback-blue h-full transition-all duration-300", style: { width: `${Math.min(o.progress, 100)}%` } }), _jsx("div", { className: "bg-feedback-blue absolute top-0 left-0 h-full animate-pulse opacity-50", style: {
                                    width: `${Math.max(Math.min(o.progress, 100), 2)}%`, // Minimum 2% width for visibility
                                    animationDuration: "1.5s",
                                } })] }), _jsxs("div", { className: "text-neutral-grey-50 mt-0.5 flex justify-between text-[10px]", children: [_jsx("span", { className: "mr-2 flex-1 truncate", children: o.statusMessage || "Processing..." }), _jsxs("span", { className: "shrink-0", children: [o.progress, "%"] })] })] })), isExecuting && o.progress === undefined && o.statusMessage && (_jsx("div", { className: "text-feedback-blue mt-1 text-[10px]", children: o.statusMessage })), isFailed && o.errorMessage && (_jsx("div", { className: "text-feedback-red mt-1 text-[10px]", children: o.errorMessage })), detailsOpen && (_jsx(OperationDetailsPanel, { operation: details, loading: detailsLoading, error: detailsError }))] }));
}
//# sourceMappingURL=OperationItem.js.map