"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from "react";
import { useState } from "react";
import { useEditContext, useFieldsEditContext } from "../client/editContext";
import { Popover, PopoverContent, PopoverTrigger, } from "../../components/ui/popover";
import { formatDate } from "../utils";
import { Button } from "../../components/ui/button";
import { Alert, AlertDescription } from "../../components/ui/alert";
import { deleteSuggestedEdit } from "../services/suggestedEditsService";
import { cleanupPendingSuggestedEditOperations } from "../client/operations";
import { Check, Lightbulb, X } from "lucide-react";
import { DeleteIcon } from "../../components/ui/delete-icon";
import { DiffView } from "./DiffView";
import { SuggestionCommentThread } from "./SuggestionCommentThread";
import { FeedbackContextHeader, getSuggestionContextSegments, } from "./FeedbackCard";
import { getFeedbackAvatarClassName, useFeedbackAuthor, } from "./feedbackAvatar";
import { Avatar } from "../../components/ui/avatar";
import { FEEDBACK_TEXT_CLASS } from "./feedbackSidebarText";
import { openCommentsFeedback } from "./openCommentsFeedback";
import { markSuggestedEditRemoved } from "./suggestedEditState";
import { applySuggestedEditPatch, replaceSuggestedEditCompletely, } from "./applySuggestedEditActions";
import { getConflictingSuggestionPeers, getSuggestedEditItemLanguage, getSuggestedEditItemVersion, getSuggestionDisplayValue, getSuggestionSelectionKey, } from "./suggestionDisplayValue";
import { applySuggestionPatchToValue } from "./suggestionPatch";
export function SuggestionDisplayPopover({ suggestion, children, onSuggestionUpdated, }) {
    const editContext = useEditContext();
    const fieldsContext = useFieldsEditContext();
    const author = useFeedbackAuthor(suggestion);
    const [isOpen, setIsOpen] = useState(false);
    const [isApplying, setIsApplying] = useState(false);
    const [item, setItem] = useState(null);
    const [patchPossible, setPatchPossible] = useState(true);
    const [patchWarning, setPatchWarning] = useState("");
    const canDelete = (suggestion.author === editContext?.user?.name ||
        editContext?.user?.isAdministrator === true) &&
        suggestion.status !== "applied";
    const canApply = suggestion.status === "pending" && !editContext?.readonly;
    const suggestionComments = React.useMemo(() => (editContext?.comments || []).filter((comment) => comment.suggestedEditId === suggestion.id), [editContext?.comments, suggestion.id]);
    // Load the full item when popover opens
    React.useEffect(() => {
        if (isOpen && editContext?.itemsRepository && suggestion.itemId) {
            editContext.itemsRepository
                .getItem({
                id: suggestion.itemId,
                language: getSuggestedEditItemLanguage(suggestion),
                version: getSuggestedEditItemVersion(suggestion),
            })
                .then((loadedItem) => {
                setItem(loadedItem);
                checkAndComputePatch(loadedItem);
            })
                .catch((err) => {
                console.error("Error loading item:", err);
            });
        }
    }, [isOpen, suggestion, editContext?.itemsRepository]);
    // Check if the patch can be applied cleanly
    const checkAndComputePatch = async (loadedItem) => {
        const field = loadedItem?.fields?.find((f) => f.id === suggestion.fieldId);
        if (!field)
            return;
        const currentValue = field.rawValue || "";
        const patchedCandidate = applySuggestionPatchToValue(currentValue, suggestion.oldValue, suggestion.newValue);
        if (patchedCandidate === false || typeof patchedCandidate !== "string") {
            setPatchPossible(false);
            setPatchWarning("Patch cannot be applied cleanly to current field value.");
        }
        else {
            setPatchPossible(true);
            setPatchWarning("");
        }
    };
    const deleteCurrentSuggestion = async () => {
        try {
            markSuggestedEditRemoved(suggestion.id);
            await deleteSuggestedEdit(suggestion);
            // Clean up pending operations to prevent race conditions
            cleanupPendingSuggestedEditOperations(suggestion, editContext?.user);
            // Immediately update local state to reflect deletion
            if (editContext?.setSuggestedEdits && editContext?.suggestedEdits) {
                const updatedEdits = editContext.suggestedEdits.filter((e) => e.id !== suggestion.id);
                editContext.setSuggestedEdits(updatedEdits);
            }
            if (editContext?.setComments && editContext?.comments) {
                editContext.setComments(editContext.comments.filter((comment) => comment.suggestedEditId !== suggestion.id));
            }
        }
        catch (error) {
            console.error("Failed to delete suggested edit:", error);
        }
        finally {
            setIsOpen(false);
            onSuggestionUpdated?.();
        }
    };
    const handleDelete = () => {
        editContext?.confirm({
            header: "Delete suggestion",
            message: "Delete this suggestion? This action cannot be undone.",
            acceptLabel: "Delete",
            showCancel: true,
            accept: () => {
                void deleteCurrentSuggestion();
            },
        });
    };
    const runInEditMode = (action, actionDescription) => {
        if (!editContext || isApplying)
            return;
        if (editContext.mode === "edit") {
            void action();
            return;
        }
        editContext.confirm({
            header: "Switch to Edit Mode?",
            message: `Applying suggestions requires edit mode. Switch to edit mode to ${actionDescription}?`,
            acceptLabel: "Switch and apply",
            rejectLabel: "Cancel",
            accept: async () => {
                await editContext.changeMode("edit", { reason: "apply-suggestion" });
                await action();
            },
        });
    };
    const applySuggestionPatch = async () => {
        if (!patchPossible || !editContext || isApplying)
            return;
        setIsApplying(true);
        try {
            const result = await applySuggestedEditPatch(suggestion, editContext);
            if (result.type === "patch-conflict") {
                setPatchWarning("Patch cannot be applied cleanly to current field value.");
                return;
            }
            if (result.type === "success") {
                onSuggestionUpdated?.();
                setIsOpen(false);
            }
        }
        finally {
            setIsApplying(false);
        }
    };
    const replaceCompletely = async () => {
        if (!editContext || isApplying)
            return;
        setIsApplying(true);
        try {
            const result = await replaceSuggestedEditCompletely(suggestion, editContext);
            if (result.type === "success") {
                onSuggestionUpdated?.();
                setIsOpen(false);
            }
        }
        finally {
            setIsApplying(false);
        }
    };
    const handleApplyPatch = () => {
        if (!patchPossible || !editContext || isApplying)
            return;
        runInEditMode(applySuggestionPatch, "apply this suggestion");
    };
    const handleReplaceCompletely = () => {
        if (!editContext || isApplying)
            return;
        runInEditMode(replaceCompletely, "replace the field content");
    };
    const fieldName = item && item.fields
        ? item.fields.find((f) => f.id === suggestion.fieldId)?.name || undefined
        : undefined;
    const contextSegments = getSuggestionContextSegments(suggestion, editContext?.currentItemDescriptor?.name, item ? item.name : undefined, fieldName);
    const conflictDisplay = React.useMemo(() => {
        if (!item || !suggestion.fieldId)
            return undefined;
        const field = item.fields?.find((candidate) => candidate.id === suggestion.fieldId);
        if (!field)
            return undefined;
        const language = getSuggestedEditItemLanguage(suggestion);
        const version = getSuggestedEditItemVersion(suggestion) ?? 0;
        const selectionKey = getSuggestionSelectionKey({
            itemId: suggestion.itemId,
            language,
            fieldId: suggestion.fieldId,
        });
        return getSuggestionDisplayValue({
            repositoryValue: field.rawValue ?? "",
            suggestedEdits: editContext?.suggestedEdits ?? [],
            field: {
                itemId: suggestion.itemId,
                language,
                version,
                fieldId: suggestion.fieldId,
                pageItemId: suggestion.mainItemId,
                pageItemLanguage: suggestion.mainItemLanguage,
                pageItemVersion: suggestion.mainItemVersion,
            },
            mode: "suggestions",
            selectedVariantId: editContext?.suggestionVariantSelection[selectionKey],
        });
    }, [
        editContext?.suggestedEdits,
        editContext?.suggestionVariantSelection,
        item,
        suggestion,
    ]);
    const conflictPeers = React.useMemo(() => conflictDisplay
        ? getConflictingSuggestionPeers(conflictDisplay.suggestions, suggestion.id)
        : [], [conflictDisplay, suggestion.id]);
    const isConflicting = conflictPeers.length > 0;
    return (_jsxs(Popover, { open: isOpen, onOpenChange: (open) => {
            setIsOpen(open);
            if (!open) {
                setPatchWarning("");
            }
        }, enableIframeClickDetection: true, children: [_jsx(PopoverTrigger, { asChild: true, children: children }), _jsx(PopoverContent, { className: `${FEEDBACK_TEXT_CLASS} border-border-default w-[420px] overflow-hidden rounded-2xl border bg-white p-0 shadow-xl`, side: "bottom", align: "start", children: _jsxs("div", { className: "flex max-h-[560px] flex-col", children: [_jsxs("div", { className: "border-border-default flex h-11 shrink-0 items-center border-b px-4", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(Lightbulb, { strokeWidth: 1, className: "text-feedback-orange h-4 w-4 shrink-0" }), _jsx("div", { className: "text-neutral-grey-100 truncate text-base font-medium", children: "Suggestion" })] }), _jsxs("div", { className: "ml-auto flex items-center gap-1", children: [canApply && patchPossible && suggestion.status !== "applied" && (_jsxs(Button, { size: "sm", onClick: handleApplyPatch, disabled: isApplying, className: "h-8 gap-1.5 px-3", "aria-label": "Apply suggestion", children: [_jsx(Check, { size: 16, strokeWidth: 1 }), isApplying ? "Applying..." : "Apply"] })), suggestion.status === "applied" && (_jsx("div", { className: "flex h-8 w-8 items-center justify-center", children: _jsx(Check, { size: 16, strokeWidth: 1, className: "text-feedback-green" }) })), canDelete && (_jsx(Button, { variant: "ghost", size: "sm", onClick: handleDelete, className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-50 h-8 w-8 p-0", "aria-label": "Delete suggestion", children: _jsx(DeleteIcon, { size: "lg" }) })), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setIsOpen(false), className: "text-neutral-grey-50 hover:bg-neutral-grey-5 hover:text-neutral-grey-50 h-8 w-8 p-0", "aria-label": "Close suggestion", "data-testid": "close-suggestion-popover", children: _jsx(X, { size: 16, strokeWidth: 1 }) })] })] }), _jsx(FeedbackContextHeader, { segments: contextSegments }), _jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto p-4", children: [_jsxs("div", { className: "mb-3 flex items-start gap-3", children: [_jsx(Avatar, { src: author.avatarUrl, name: author.displayName, size: "sm", fallbackColor: author.fallbackColor, fallbackClassName: getFeedbackAvatarClassName(suggestion), className: "!text-[10px] font-medium", title: author.title }), _jsxs("div", { children: [_jsx("div", { className: "text-neutral-grey-100 text-sm font-medium", children: author.displayName }), _jsx("div", { className: "text-neutral-grey-50 text-xs", children: suggestion.created
                                                        ? formatDate(new Date(suggestion.created))
                                                        : "" })] })] }), suggestion.status === "applied" && (_jsxs("div", { className: "text-feedback-green text-xs font-medium", children: ["\u2713 Applied", " ", suggestion.updatedBy ? `by ${suggestion.updatedBy}` : "", suggestion.updated
                                            ? ` on ${formatDate(new Date(suggestion.updated))}`
                                            : ""] })), isConflicting && suggestion.fieldId && (_jsx(Alert, { className: "mb-3", children: _jsxs(AlertDescription, { className: "flex items-center justify-between gap-3", children: [_jsxs("span", { children: ["Conflicts with ", conflictPeers.length, " other pending suggestion(s)."] }), _jsx(Button, { type: "button", size: "xs", variant: "outline", onClick: () => {
                                                    const selectionKey = getSuggestionSelectionKey({
                                                        itemId: suggestion.itemId,
                                                        language: getSuggestedEditItemLanguage(suggestion),
                                                        fieldId: suggestion.fieldId,
                                                    });
                                                    const variantId = conflictDisplay?.variants.some((variant) => variant.id === suggestion.id)
                                                        ? suggestion.id
                                                        : "merged";
                                                    editContext?.setSuggestionVariantSelection((current) => ({
                                                        ...current,
                                                        [selectionKey]: variantId,
                                                    }));
                                                }, children: "Preview on page" })] }) })), _jsxs("div", { className: "text-sm", children: [_jsx(DiffView, { oldText: suggestion.oldValue, newText: suggestion.newValue, ignoreFormatting: true, clipUnchanged: true, clipThreshold: 50, clipContext: 10 }), canApply && patchWarning && (_jsxs("div", { className: "text-feedback-red mt-2 text-xs", children: [patchWarning, _jsx("button", { className: "hover:text-feedback-red ml-2 cursor-pointer underline", onClick: handleReplaceCompletely, disabled: isApplying, children: "Click here to replace the field content completely." })] }))] }), canApply && !patchPossible && suggestion.status !== "applied" && (_jsx("div", { className: "border-t pt-3", children: _jsx(Button, { size: "sm", onClick: handleReplaceCompletely, disabled: isApplying, className: "w-full", children: isApplying ? "Applying..." : "Replace Field Content" }) })), (!editContext?.readonly || suggestionComments.length > 0) && (_jsx("div", { className: "border-t pt-3", children: _jsx(SuggestionCommentThread, { suggestion: suggestion, comments: suggestionComments, compact: true, constrainHeight: true }) })), !editContext?.configuration?.forceFullscreen && (_jsx("div", { className: "border-t pt-3", children: _jsx(Button, { variant: "outline", size: "sm", onClick: () => {
                                            setIsOpen(false);
                                            // Exit fullscreen mode if active
                                            if (editContext?.fullscreen) {
                                                editContext.setFullscreen(false);
                                            }
                                            // Focus on the field and select the item
                                            if (suggestion.fieldId) {
                                                fieldsContext?.setFocusedField({
                                                    fieldId: suggestion.fieldId,
                                                    item: {
                                                        id: suggestion.itemId,
                                                        language: getSuggestedEditItemLanguage(suggestion),
                                                        version: getSuggestedEditItemVersion(suggestion),
                                                    },
                                                }, false);
                                                editContext?.select?.([suggestion.itemId]);
                                            }
                                            openCommentsFeedback(editContext);
                                        }, className: "w-full", children: "View in Comments & Suggestions" }) }))] })] }) })] }));
}
//# sourceMappingURL=SuggestionDisplayPopover.js.map