"use client";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useCallback, useEffect } from "react";
import { Sparkles } from "lucide-react";
import { toast } from "sonner";
import { cn } from "../../lib/utils";
import { useEditContext } from "../client/editContext";
import { useInlineAiPosition, calculateDialogPosition, } from "./useInlineAiPosition";
import { InlineAiDialog } from "./InlineAiDialog";
/**
 * Floating trigger button that appears when text is selected.
 * Opens the InlineAiDialog when clicked.
 */
export function InlineAiTrigger({ className }) {
    const editContext = useEditContext();
    const selectedRange = editContext?.selectedRange;
    const position = useInlineAiPosition(selectedRange);
    const [dialogOpen, setDialogOpen] = useState(false);
    const [focusAllowsTrigger, setFocusAllowsTrigger] = useState(false);
    const [dialogPosition, setDialogPosition] = useState({ x: 0, y: 0 });
    const [dialogSelectionSnapshot, setDialogSelectionSnapshot] = useState(null);
    const shouldAllowTriggerForCurrentFocus = useCallback(() => {
        if (!selectedRange?.text || dialogOpen)
            return false;
        const activeEl = document.activeElement;
        if (!activeEl)
            return false;
        if (activeEl.closest(".agent-inline-trigger"))
            return true;
        const inAnyDialog = activeEl.closest('[role="dialog"]');
        if (inAnyDialog && !activeEl.closest(".agent-inline-dialog"))
            return false;
        if (selectedRange.element) {
            return (activeEl === selectedRange.element ||
                selectedRange.element.contains(activeEl));
        }
        const selectedFieldEl = activeEl.closest("[data-fieldid][data-itemid]");
        if (selectedFieldEl) {
            return (selectedFieldEl.getAttribute("data-fieldid") ===
                selectedRange.fieldId &&
                selectedFieldEl.getAttribute("data-itemid") === selectedRange.itemId);
        }
        return activeEl.classList.contains("page-iframe");
    }, [
        dialogOpen,
        selectedRange?.element,
        selectedRange?.fieldId,
        selectedRange?.itemId,
        selectedRange?.text,
    ]);
    // Hide trigger when dialog is open, no selection, or focus left the selected field
    const showTrigger = position.visible &&
        !!selectedRange?.text &&
        !dialogOpen &&
        focusAllowsTrigger;
    const openDialog = useCallback(() => {
        // Calculate dialog position - use selection position if available, otherwise use a default position
        let pos;
        if (selectedRange?.text && position.visible) {
            pos = calculateDialogPosition({ x: position.x, y: position.y }, 400, 350);
        }
        else {
            // Default position: center of viewport
            pos = {
                x: window.innerWidth / 2 - 210, // Half dialog width (420px / 2)
                y: window.innerHeight / 2 - 200, // Approximate center
            };
        }
        setDialogPosition(pos);
        setDialogSelectionSnapshot(selectedRange
            ? {
                itemId: selectedRange.itemId,
                fieldId: selectedRange.fieldId,
                startOffset: selectedRange.startOffset,
                endOffset: selectedRange.endOffset,
                text: selectedRange.text,
                contextBefore: selectedRange.contextBefore,
                contextAfter: selectedRange.contextAfter,
            }
            : null);
        setDialogOpen(true);
    }, [selectedRange, position.x, position.y, position.visible]);
    const handleClick = useCallback(() => {
        openDialog();
    }, [openDialog]);
    const handleAccept = useCallback((newText) => {
        if (editContext) {
            const hadSelectionWhenOpened = !!dialogSelectionSnapshot?.text;
            const currentSelection = editContext.selectedRange;
            const selectionStillValid = !!currentSelection &&
                !!dialogSelectionSnapshot?.text &&
                !!currentSelection.text &&
                currentSelection.text === dialogSelectionSnapshot.text &&
                currentSelection.itemId === dialogSelectionSnapshot.itemId &&
                currentSelection.fieldId === dialogSelectionSnapshot.fieldId &&
                currentSelection.startOffset ===
                    dialogSelectionSnapshot.startOffset &&
                currentSelection.endOffset === dialogSelectionSnapshot.endOffset;
            if (hadSelectionWhenOpened && !selectionStillValid) {
                toast.warning("Selection was lost while generating", {
                    description: "Result was not inserted to avoid changing an unexpected location. Re-select text and run again.",
                });
                return false;
            }
            if (hadSelectionWhenOpened && editContext.replaceSelectedText) {
                // Replace selected text
                editContext.replaceSelectedText(newText);
            }
            else if (editContext.insertTextAtCursor) {
                // Insert at cursor position when there's no selection
                editContext.insertTextAtCursor(newText);
            }
            else if (dialogSelectionSnapshot && editContext.replaceSelectedText) {
                // Fallback: try replaceSelectedText even without selected text (it should handle insertion)
                editContext.replaceSelectedText(newText);
            }
        }
        setDialogOpen(false);
        setDialogSelectionSnapshot(null);
        return true;
    }, [editContext, dialogSelectionSnapshot]);
    const handleClose = useCallback(() => {
        setDialogOpen(false);
        setDialogSelectionSnapshot(null);
    }, []);
    useEffect(() => {
        const updateTriggerVisibility = () => {
            setFocusAllowsTrigger(shouldAllowTriggerForCurrentFocus());
        };
        updateTriggerVisibility();
        const scheduleUpdate = () => {
            window.setTimeout(updateTriggerVisibility, 0);
        };
        document.addEventListener("focusin", scheduleUpdate, true);
        document.addEventListener("focusout", scheduleUpdate, true);
        return () => {
            document.removeEventListener("focusin", scheduleUpdate, true);
            document.removeEventListener("focusout", scheduleUpdate, true);
        };
    }, [shouldAllowTriggerForCurrentFocus]);
    // Handle keyboard shortcuts (Ctrl/Cmd + .)
    useEffect(() => {
        const handleKeyDown = (e) => {
            const isCtrlPeriod = (e.ctrlKey || e.metaKey) && e.key === ".";
            // Allow triggering even without selection
            if (isCtrlPeriod && !dialogOpen) {
                // Only trigger if we're in a text field or have a focused field
                const activeEl = document.activeElement;
                const isInTextField = activeEl &&
                    (activeEl.tagName === "INPUT" ||
                        activeEl.tagName === "TEXTAREA" ||
                        activeEl.getAttribute("contenteditable") === "true" ||
                        activeEl.closest('[contenteditable="true"]') ||
                        activeEl.closest(".slate-editable"));
                // Check if focus is in an iframe (which means we're editing content inside the iframe)
                const isInIframe = activeEl && activeEl.tagName === "IFRAME";
                // Allow triggering if:
                // 1. We're in a text field directly, OR
                // 2. We have a focused field in the edit context, OR
                // 3. We're in an iframe AND have a selected range (text selected in iframe field)
                if (isInTextField ||
                    editContext?.focusedField ||
                    (isInIframe && selectedRange?.text)) {
                    e.preventDefault();
                    e.stopPropagation();
                    openDialog();
                }
            }
        };
        document.addEventListener("keydown", handleKeyDown, true);
        return () => {
            document.removeEventListener("keydown", handleKeyDown, true);
        };
    }, [dialogOpen, openDialog, editContext?.focusedField, selectedRange?.text]);
    // Close dialog when the selection changes (user selected different text in the editor)
    useEffect(() => {
        if (!dialogOpen)
            return;
        // Only react to selection changes when focus is in the editor - this avoids closing
        // when the selection was cleared due to focus moving to the dialog on open
        const activeEl = document.activeElement;
        if (activeEl?.closest(".agent-inline-dialog") ||
            activeEl?.closest('[role="dialog"]')) {
            return;
        }
        const isInEditor = activeEl &&
            (activeEl.tagName === "INPUT" ||
                activeEl.tagName === "TEXTAREA" ||
                activeEl.getAttribute("contenteditable") === "true" ||
                activeEl.closest('[contenteditable="true"]') ||
                activeEl.closest(".slate-editable") ||
                activeEl.tagName === "IFRAME");
        if (!isInEditor && !editContext?.focusedField)
            return;
        const snapshotText = dialogSelectionSnapshot?.text ?? "";
        const currentText = selectedRange?.text ?? "";
        // Selection changed if the current selection differs from what we captured when opening
        if (currentText !== snapshotText) {
            setDialogOpen(false);
            setDialogSelectionSnapshot(null);
        }
    }, [
        dialogOpen,
        dialogSelectionSnapshot?.text,
        selectedRange?.text,
        editContext?.focusedField,
    ]);
    // Close dialog when focus is lost (but allow it to stay open even without selection)
    useEffect(() => {
        if (dialogOpen) {
            // Only close if focus moved away from text fields and dialog
            const timeout = setTimeout(() => {
                const activeEl = document.activeElement;
                const isInDialog = activeEl?.closest(".agent-inline-dialog") ||
                    activeEl?.closest('[role="dialog"]');
                const isInTextField = activeEl &&
                    (activeEl.tagName === "INPUT" ||
                        activeEl.tagName === "TEXTAREA" ||
                        activeEl.getAttribute("contenteditable") === "true" ||
                        activeEl.closest('[contenteditable="true"]') ||
                        activeEl.closest(".slate-editable"));
                // Don't close if focus is in dialog or text field
                if (!isInDialog && !isInTextField && !editContext?.focusedField) {
                    setDialogOpen(false);
                }
            }, 500);
            return () => clearTimeout(timeout);
        }
    }, [dialogOpen, editContext?.focusedField]);
    // Listen for custom event from context menu or keyboard shortcuts
    useEffect(() => {
        const handleInlineAiOpen = () => {
            if (!dialogOpen) {
                openDialog();
            }
        };
        document.addEventListener("inline-ai-open", handleInlineAiOpen);
        return () => {
            document.removeEventListener("inline-ai-open", handleInlineAiOpen);
        };
    }, [dialogOpen, openDialog]);
    return (_jsxs(_Fragment, { children: [showTrigger && (_jsx("button", { onClick: handleClick, tabIndex: 0, className: cn("agent-inline-trigger fixed z-[40] rounded-full p-1.5", "bg-highlight-100 hover:bg-highlight-100 text-white", "shadow-lg hover:shadow-xl", "transition-all duration-150 ease-out", "animate-in fade-in-0 zoom-in-95", "hover:scale-110", className), style: {
                    left: position.x - 14,
                    top: position.y,
                }, title: "AI Edit (Ctrl+.)", children: _jsx(Sparkles, { className: "h-4 w-4" }) })), dialogOpen && (_jsx(InlineAiDialog, { selectedText: dialogSelectionSnapshot?.text, contextBefore: dialogSelectionSnapshot?.contextBefore, contextAfter: dialogSelectionSnapshot?.contextAfter, onAccept: handleAccept, onClose: handleClose, position: dialogPosition }))] }));
}
export default InlineAiTrigger;
//# sourceMappingURL=InlineAiTrigger.js.map