"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from "react";
import { useEffect, useState } from "react";
import uuid from "react-uuid";
import { MessageCirclePlus } from "lucide-react";
import { useEditContext, useFieldsEditContext, } from "../client/editContext";
import { createOrUpdateComment } from "../services/reviewsService";
import { toast } from "sonner";
import { Popover, PopoverContent, PopoverTrigger, PopoverAnchor, } from "../../components/ui/popover";
import { CloseButton } from "../../components/ui/close-button";
import { CommentEditor, COMMENT_INPUT_PLACEHOLDER } from "./CommentEditor";
import { FEEDBACK_TEXT_CLASS } from "./feedbackSidebarText";
import * as ReactDOM from "react-dom/client";
import { COMMENT_TRANSIENT_ELEMENT_KEY, COMMENT_TRANSIENT_SELECTION_RECT, publishCommentDraftSelection, } from "./commentTransientSelection";
import { activateCommentsMode } from "./openCommentsFeedback";
function cleanId(value) {
    return (value || "").replace(/[{}]/g, "").toLowerCase();
}
function selectionRangeMatchesField(range, field) {
    if (!range || !field)
        return false;
    return (cleanId(range.fieldId) === cleanId(field.fieldId) &&
        cleanId(range.itemId) === cleanId(field.item.id) &&
        (!range.language || range.language === field.item.language) &&
        (typeof range.version !== "number" || range.version === field.item.version));
}
function isUsableTextSelectionRange(range) {
    return !!(range &&
        range.text?.trim() &&
        typeof range.startOffset === "number" &&
        typeof range.endOffset === "number" &&
        range.startOffset !== range.endOffset &&
        range.fieldId &&
        range.itemId);
}
function getSelectionFieldDescriptor(range, fallback) {
    if (!isUsableTextSelectionRange(range))
        return undefined;
    return {
        fieldId: range.fieldId,
        item: {
            id: range.itemId,
            language: range.language || fallback.language,
            version: typeof range.version === "number" ? range.version : fallback.version,
        },
    };
}
export function CommentPopover({ children, editContext: externalEditContext, position, onClose, initialField, initialRange, }) {
    const [isOpen, setIsOpen] = useState(!!position);
    const [saving, setSaving] = useState(false);
    const contextFromHook = useEditContext();
    const editContext = externalEditContext || contextFromHook;
    const availableTags = editContext?.availableCommentTags || [];
    const fieldsContext = useFieldsEditContext();
    const contentRef = React.useRef(null);
    // When the comment attaches to a text selection with known geometry, anchor
    // the popover to the selection rectangle instead of the trigger point. Radix
    // then opens below the selection (flipping above when space runs out), so
    // the popover never covers the text being commented on.
    const anchorRange = initialRange || editContext?.selectedRange;
    const selectionAnchorRect = isUsableTextSelectionRange(anchorRange) && anchorRange.clientRect
        ? anchorRange.clientRect
        : undefined;
    useEffect(() => {
        if (position) {
            activateCommentsMode(editContext, { reason: "comment-popover-open" });
            publishCommentDraftSelection(initialRange || editContext?.selectedRange);
            setIsOpen(true);
        }
    }, [editContext, initialRange, position?.x, position?.y]);
    useEffect(() => {
        return () => {
            publishCommentDraftSelection(undefined);
        };
    }, []);
    // Tags are now provided by editContext.availableCommentTags
    const handleSave = async (text, tags) => {
        if (!editContext || !text || saving)
            return;
        const descriptor = editContext.item?.descriptor;
        if (!descriptor)
            return;
        const rangeCandidate = initialRange || editContext.selectedRange;
        const selectedRangeField = getSelectionFieldDescriptor(rangeCandidate, descriptor);
        const snapshotField = selectedRangeField || initialField || fieldsContext?.focusedField;
        const snapshotRange = !snapshotField ||
            selectionRangeMatchesField(rangeCandidate, snapshotField)
            ? rangeCandidate
            : undefined;
        const currentSelection = editContext.getSelection();
        const itemId = snapshotField?.item.id ||
            (currentSelection.length > 0 ? currentSelection[0] : undefined) ||
            descriptor.id;
        if (!itemId)
            return;
        const language = snapshotField?.item.language || descriptor.language;
        const version = typeof snapshotField?.item.version === "number"
            ? snapshotField.item.version
            : descriptor.version;
        const getFieldName = async () => {
            if (!snapshotField)
                return undefined;
            const field = await editContext.itemsRepository.getField(snapshotField);
            return field?.name;
        };
        const getItemName = async () => {
            const item = await editContext.itemsRepository.getItem({
                id: itemId,
                language,
                version,
            });
            return item?.name;
        };
        setSaving(true);
        try {
            activateCommentsMode(editContext, { reason: "comment-save" });
            const newComment = {
                id: uuid(),
                isNew: false,
                itemId,
                itemName: await getItemName(),
                fieldId: snapshotField?.fieldId,
                fieldName: await getFieldName(),
                mainItemId: descriptor.id,
                language,
                version,
                position: 0,
                rangeStart: snapshotRange?.startOffset || 0,
                rangeEnd: snapshotRange?.endOffset || 0,
                author: editContext.user?.name,
                authorDisplayName: editContext.user?.fullName,
                created: new Date().toISOString(),
                text: text,
                tags: tags.join(","),
            };
            if (snapshotRange?.clientRect) {
                newComment[COMMENT_TRANSIENT_SELECTION_RECT] = snapshotRange.clientRect;
            }
            if (snapshotRange?.elementKey) {
                newComment[COMMENT_TRANSIENT_ELEMENT_KEY] = snapshotRange.elementKey;
            }
            editContext.setComments([newComment, ...editContext.comments]);
            editContext.setSelectedComment(newComment);
            editContext.setSelectedSuggestedEdit(undefined);
            try {
                const item = await editContext.itemsRepository.getItem({
                    id: itemId,
                    language,
                    version,
                });
                if (item && newComment.fieldId) {
                    newComment.fieldValue = item.fields.find((f) => f.id === newComment.fieldId)?.rawValue;
                }
            }
            catch { }
            const result = await createOrUpdateComment(newComment);
            if (result.type === "error" || result.type === "unauthorized") {
                console.error("Failed to save comment:", result);
                toast.error(result.details || result.summary || "Failed to save comment");
                return;
            }
            editContext.loadComments();
        }
        finally {
            setSaving(false);
            setIsOpen(false);
            onClose?.();
        }
    };
    const handleCancel = () => {
        publishCommentDraftSelection(undefined);
        setIsOpen(false);
        onClose?.();
    };
    return (_jsxs(Popover, { open: isOpen, onOpenChange: (open) => {
            setIsOpen(open);
            if (open) {
                activateCommentsMode(editContext, { reason: "comment-popover-open" });
            }
            if (!open) {
                publishCommentDraftSelection(undefined);
                onClose?.();
            }
        }, enableIframeClickDetection: true, modal: true, children: [position && (_jsx(PopoverAnchor, { "data-testid": "add-comment-popover-anchor", style: selectionAnchorRect
                    ? {
                        position: "fixed",
                        left: selectionAnchorRect.left,
                        top: selectionAnchorRect.top,
                        width: selectionAnchorRect.width,
                        height: selectionAnchorRect.height,
                        pointerEvents: "none",
                    }
                    : {
                        position: "fixed",
                        left: position.x,
                        top: position.y,
                        width: 1,
                        height: 1,
                        pointerEvents: "none",
                    } })), !position && (_jsx(PopoverTrigger, { asChild: true, children: (children ?? _jsx(MessageCirclePlus, { size: 16, strokeWidth: 1 })) })), _jsx(PopoverContent, { ref: contentRef, tabIndex: -1, className: `${FEEDBACK_TEXT_CLASS} w-96 px-4 pt-3 pb-4`, "data-testid": "add-comment-popover", side: "bottom", align: "start", sideOffset: 8, collisionPadding: 8, onOpenAutoFocus: (e) => {
                    e.preventDefault();
                    contentRef.current?.focus();
                }, onInteractOutside: (e) => {
                    const target = e.target;
                    if (target &&
                        target.closest('[data-slot="tooltip-content"], [data-mention-textarea-popover]')) {
                        e.preventDefault();
                    }
                }, onPointerDownOutside: (e) => {
                    const target = e.target;
                    if (target &&
                        target.closest('[data-slot="tooltip-content"], [data-mention-textarea-popover]')) {
                        e.preventDefault();
                    }
                }, onFocusOutside: (e) => {
                    const target = e.target;
                    if (target &&
                        target.closest('[data-slot="tooltip-content"], [data-mention-textarea-popover]')) {
                        e.preventDefault();
                    }
                }, onMouseDown: (e) => e.stopPropagation(), onClick: (e) => e.stopPropagation(), children: _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsx("div", { className: "text-neutral-grey-100 text-base font-medium", children: "Add Comment" }), _jsx(CloseButton, { label: "Close comment composer", onClick: handleCancel, "data-testid": "add-comment-cancel" })] }), _jsx(CommentEditor, { editContext: editContext, onSave: handleSave, onCancel: handleCancel, isSaving: saving, availableTags: availableTags, placeholder: COMMENT_INPUT_PLACEHOLDER, submitLabel: "Add Comment", autoFocus: true, showCancelButton: false })] }) })] }));
}
export const COMMENT_POPOVER_OVERLAY_ID = "comment-popover";
// The imperatively-opened comment popover lives in its own React root, so it
// cannot observe editContext.currentOverlay reactively. EditorShell's central
// overlay effect closes it through this module-level handle instead.
let activeCommentPopoverClose = null;
export function closeActiveCommentPopover() {
    activeCommentPopoverClose?.();
}
export function showCommentPopoverAt(position, editContext, options) {
    // Only one imperative comment popover at a time.
    activeCommentPopoverClose?.();
    activateCommentsMode(editContext, { reason: "comment-popover-open" });
    // Snapshot the effective range once so the draft highlight, the popover
    // anchor, and the saved comment all describe the same selection.
    const range = options?.range || editContext.selectedRange;
    publishCommentDraftSelection(range);
    const container = document.createElement("div");
    document.body.appendChild(container);
    const root = ReactDOM.createRoot(container);
    let closed = false;
    const handleClose = () => {
        if (closed)
            return;
        closed = true;
        if (activeCommentPopoverClose === handleClose) {
            activeCommentPopoverClose = null;
        }
        editContext.setCurrentOverlay?.((overlay) => overlay === COMMENT_POPOVER_OVERLAY_ID ? undefined : overlay);
        publishCommentDraftSelection(undefined);
        root.unmount();
        if (container.parentNode)
            container.parentNode.removeChild(container);
    };
    activeCommentPopoverClose = handleClose;
    // Claim the shared overlay slot so other registered overlays (inline AI
    // dialog, context menu, field generators) close themselves.
    editContext.setCurrentOverlay?.(COMMENT_POPOVER_OVERLAY_ID);
    root.render(_jsx(CommentPopover, { editContext: editContext, position: position, onClose: handleClose, initialField: options?.field, initialRange: range }));
}
export function showCommentPopoverForTrigger(trigger, editContext, options) {
    const rect = trigger?.getBoundingClientRect();
    showCommentPopoverAt(rect
        ? { x: rect.left, y: rect.bottom }
        : { x: window.innerWidth / 2, y: window.innerHeight / 2 }, editContext, options);
}
//# sourceMappingURL=CommentPopover.js.map