"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 { deleteSuggestedEdit, createOrUpdateSuggestedEdit, } from "../services/suggestedEditsService";
import { cleanupPendingSuggestedEditOperations } from "../client/operations";
import { Check, Trash2, Brush, GalleryVertical, } from "lucide-react";
import { DiffView } from "./DiffView";
import { SimpleIconButton } from "../ui/SimpleIconButton";
import { createPatch, applyPatch } from "diff";
import { cn } from "../../lib/utils";
export function SuggestionDisplayPopover({ suggestion, children, onSuggestionUpdated, }) {
    const editContext = useEditContext();
    const fieldsContext = useFieldsEditContext();
    const [isOpen, setIsOpen] = useState(false);
    const [deleteConfirm, setDeleteConfirm] = useState(false);
    const [isApplying, setIsApplying] = useState(false);
    const [item, setItem] = useState(null);
    const [patchPossible, setPatchPossible] = useState(true);
    const [patchWarning, setPatchWarning] = useState("");
    const [ignoreFormatting, setIgnoreFormatting] = useState(true);
    const [clipUnchanged, setClipUnchanged] = useState(true);
    const canDelete = suggestion.author === editContext?.user?.name &&
        suggestion.status !== "applied";
    const canApply = suggestion.status !== "applied" && !editContext?.readonly;
    // Load the full item when popover opens
    React.useEffect(() => {
        if (isOpen && editContext?.itemsRepository && suggestion.itemId) {
            editContext.itemsRepository
                .getItem({
                id: suggestion.itemId,
                language: suggestion.mainItemLanguage,
                version: suggestion.mainItemVersion,
            })
                .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 patch = createPatch("field", suggestion.oldValue, suggestion.newValue);
        const patchedCandidate = applyPatch(currentValue, patch);
        if (patchedCandidate === false || typeof patchedCandidate !== "string") {
            setPatchPossible(false);
            setPatchWarning("Patch cannot be applied cleanly to current field value.");
        }
        else {
            setPatchPossible(true);
            setPatchWarning("");
        }
    };
    const handleDelete = async () => {
        if (!deleteConfirm) {
            setDeleteConfirm(true);
            return;
        }
        try {
            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);
            }
        }
        catch (error) {
            console.error("Failed to delete suggested edit:", error);
        }
        finally {
            setIsOpen(false);
            onSuggestionUpdated?.();
        }
    };
    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 () => {
                editContext.setMode("edit");
                await action();
            },
        });
    };
    const applySuggestionPatch = async () => {
        if (!patchPossible || !editContext || isApplying)
            return;
        setIsApplying(true);
        try {
            // Recalculate the patch immediately before applying
            const field = item?.fields?.find((f) => f.id === suggestion.fieldId);
            if (!field)
                return;
            const currentValue = field.rawValue || "";
            const patch = createPatch("field", suggestion.oldValue, suggestion.newValue);
            const patchedCandidate = applyPatch(currentValue, patch);
            if (patchedCandidate === false || typeof patchedCandidate !== "string") {
                setPatchWarning("Patch cannot be applied cleanly to current field value.");
                return;
            }
            await editContext.operations.editField({
                field: {
                    fieldId: suggestion.fieldId,
                    item: {
                        id: suggestion.itemId,
                        language: suggestion.mainItemLanguage,
                        version: suggestion.mainItemVersion,
                    },
                },
                value: patchedCandidate,
                rawValue: patchedCandidate,
                refresh: "immediate",
            });
            // Update the suggestion status to "applied"
            const updatedSuggestion = { ...suggestion, status: "applied" };
            await createOrUpdateSuggestedEdit(updatedSuggestion);
            onSuggestionUpdated?.();
            setIsOpen(false);
        }
        finally {
            setIsApplying(false);
        }
    };
    const replaceCompletely = async () => {
        if (!editContext || isApplying)
            return;
        setIsApplying(true);
        try {
            await editContext.operations.editField({
                field: {
                    fieldId: suggestion.fieldId,
                    item: {
                        id: suggestion.itemId,
                        language: suggestion.mainItemLanguage,
                        version: suggestion.mainItemVersion,
                    },
                },
                value: suggestion.newValue,
                rawValue: suggestion.newValue,
                refresh: "immediate",
            });
            const updatedSuggestion = { ...suggestion, status: "applied" };
            await createOrUpdateSuggestedEdit(updatedSuggestion);
            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 renderContextInfo = () => {
        const pageName = editContext?.currentItemDescriptor?.name;
        const itemName = item ? item.name : undefined;
        const fieldName = item && item.fields
            ? item.fields.find((f) => f.id === suggestion.fieldId)?.name || undefined
            : undefined;
        const segments = [pageName, itemName, fieldName].filter((x) => !!x && x.length > 0);
        if (segments.length === 0)
            return null;
        return (_jsx("div", { className: "mt-3 flex items-center border-t pt-3 text-xs", children: segments.map((seg, idx) => (_jsxs(React.Fragment, { children: [idx > 0 && _jsx("div", { className: "mx-2 text-xs text-gray-500", children: ">" }), _jsx("div", { className: "text-xs text-gray-500", children: seg })] }, idx))) }));
    };
    const renderDiffToggleButtons = () => {
        return (_jsxs("div", { className: "mb-2 flex gap-2", children: [_jsx(SimpleIconButton, { icon: _jsx(Brush, { size: 14, className: "p-0.5", strokeWidth: 1 }), label: "Ignore Formatting", onClick: () => setIgnoreFormatting((prev) => !prev), className: cn("text-gray-500", ignoreFormatting ? "bg-gray-200" : "") }), _jsx(SimpleIconButton, { icon: _jsx(GalleryVertical, { size: 14, className: "p-0.5", strokeWidth: 1 }), label: "Clip", onClick: () => setClipUnchanged((prev) => !prev), className: cn("text-gray-500", clipUnchanged ? "bg-gray-200" : "") })] }));
    };
    return (_jsxs(Popover, { open: isOpen, onOpenChange: (open) => {
            setIsOpen(open);
            if (!open) {
                setDeleteConfirm(false);
                setPatchWarning("");
            }
        }, enableIframeClickDetection: true, children: [_jsx(PopoverTrigger, { asChild: true, children: children }), _jsx(PopoverContent, { className: "w-96 p-4", side: "bottom", align: "start", children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { children: [_jsx("div", { className: "text-sm font-semibold text-gray-900", children: suggestion.authorDisplayName || suggestion.author }), _jsx("div", { className: "text-xs text-gray-500", children: suggestion.created
                                                ? formatDate(new Date(suggestion.created))
                                                : "" })] }), _jsxs("div", { className: "flex items-center gap-1", children: [canApply && patchPossible && suggestion.status !== "applied" && (_jsx(Button, { variant: "ghost", size: "sm", onClick: handleApplyPatch, disabled: isApplying, className: "h-8 w-8 p-0 text-green-600", children: _jsx(Check, { size: 14, strokeWidth: 1 }) })), suggestion.status === "applied" && (_jsx("div", { className: "flex h-8 w-8 items-center justify-center", children: _jsx(Check, { size: 14, strokeWidth: 1, className: "text-green-500" }) })), canDelete && (_jsx(Button, { variant: "ghost", size: "sm", onClick: handleDelete, className: `h-8 w-8 p-0 ${deleteConfirm ? "text-red-500" : "text-gray-400"}`, children: _jsx(Trash2, { size: 14, strokeWidth: 1 }) }))] })] }), suggestion.status === "applied" && (_jsxs("div", { className: "text-xs font-medium text-green-600", children: ["\u2713 Applied", " ", suggestion.updatedBy ? `by ${suggestion.updatedBy}` : "", suggestion.updated
                                    ? ` on ${formatDate(new Date(suggestion.updated))}`
                                    : ""] })), renderDiffToggleButtons(), _jsxs("div", { className: "text-sm", children: [_jsx(DiffView, { oldText: suggestion.oldValue, newText: suggestion.newValue, ignoreFormatting: ignoreFormatting, clipUnchanged: clipUnchanged, clipThreshold: 50, clipContext: 10 }), canApply && patchWarning && (_jsxs("div", { className: "mt-2 text-xs text-red-500", children: [patchWarning, _jsx("button", { className: "ml-2 cursor-pointer underline hover:text-red-700", onClick: handleReplaceCompletely, disabled: isApplying, children: "Click here to replace the field content completely." })] }))] }), renderContextInfo(), deleteConfirm && (_jsxs("div", { className: "border-t pt-3", children: [_jsx("div", { className: "mb-2 text-sm text-red-600", children: "Are you sure you want to delete this suggestion?" }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: "outline", size: "sm", onClick: () => setDeleteConfirm(false), children: "Cancel" }), _jsx(Button, { variant: "destructive", size: "sm", onClick: handleDelete, children: "Delete" })] })] })), 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" }) })), !deleteConfirm && !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: suggestion.mainItemLanguage,
                                                version: suggestion.mainItemVersion,
                                            },
                                        }, false);
                                        editContext?.select?.([suggestion.itemId]);
                                    }
                                    // Open the feedback sidebar
                                    editContext?.openSidebar("feedback");
                                }, className: "w-full", children: "View in Comments Panel" }) }))] }) })] }));
}
//# sourceMappingURL=SuggestionDisplayPopover.js.map