import { useState, useEffect, useCallback } from "react";
function isRectInViewport(rect, iframe) {
    if (iframe?.contentWindow) {
        const iframeHeight = iframe.contentWindow.innerHeight;
        const iframeWidth = iframe.contentWindow.innerWidth;
        return (rect.top < iframeHeight &&
            rect.bottom > 0 &&
            rect.left < iframeWidth &&
            rect.right > 0);
    }
    return (rect.top < window.innerHeight &&
        rect.bottom > 0 &&
        rect.left < window.innerWidth &&
        rect.right > 0);
}
/**
 * Calculate position for selection within an input or textarea element.
 * Uses a hidden mirror element to measure text and determine cursor position.
 */
function getInputSelectionPosition(element, startOffset, endOffset) {
    try {
        const rect = element.getBoundingClientRect();
        const computedStyle = window.getComputedStyle(element);
        // Create a mirror div to measure text position
        const mirror = document.createElement('div');
        mirror.style.position = 'absolute';
        mirror.style.visibility = 'hidden';
        mirror.style.whiteSpace = element.tagName === 'INPUT' ? 'pre' : 'pre-wrap';
        mirror.style.wordWrap = element.tagName === 'TEXTAREA' ? 'break-word' : 'normal';
        mirror.style.font = computedStyle.font;
        mirror.style.fontSize = computedStyle.fontSize;
        mirror.style.fontFamily = computedStyle.fontFamily;
        mirror.style.fontWeight = computedStyle.fontWeight;
        mirror.style.letterSpacing = computedStyle.letterSpacing;
        mirror.style.padding = computedStyle.padding;
        mirror.style.border = computedStyle.border;
        mirror.style.boxSizing = computedStyle.boxSizing;
        mirror.style.width = element.tagName === 'TEXTAREA' ? `${element.offsetWidth}px` : 'auto';
        mirror.style.overflow = 'hidden';
        const value = element.value;
        const textBeforeSelection = value.substring(0, startOffset);
        const selectedText = value.substring(startOffset, endOffset);
        // Create text nodes and a span for the selection
        const textBefore = document.createTextNode(textBeforeSelection);
        const selectionSpan = document.createElement('span');
        selectionSpan.textContent = selectedText || '\u200b'; // Zero-width space if empty
        mirror.appendChild(textBefore);
        mirror.appendChild(selectionSpan);
        document.body.appendChild(mirror);
        // Get the position of the selection span
        const spanRect = selectionSpan.getBoundingClientRect();
        const mirrorRect = mirror.getBoundingClientRect();
        // Calculate relative position within the element
        const relativeLeft = spanRect.left - mirrorRect.left;
        const relativeTop = spanRect.top - mirrorRect.top;
        // Account for scroll position in textarea
        const scrollTop = element.tagName === 'TEXTAREA' ? element.scrollTop : 0;
        const scrollLeft = element.tagName === 'TEXTAREA' ? element.scrollLeft : 0;
        // Clean up
        document.body.removeChild(mirror);
        // Calculate absolute position
        const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;
        const paddingTop = parseFloat(computedStyle.paddingTop) || 0;
        const borderLeft = parseFloat(computedStyle.borderLeftWidth) || 0;
        const borderTop = parseFloat(computedStyle.borderTopWidth) || 0;
        const x = rect.left + paddingLeft + borderLeft + relativeLeft + (spanRect.width / 2) - scrollLeft;
        const y = rect.top + paddingTop + borderTop + relativeTop + spanRect.height - scrollTop;
        return { x, y };
    }
    catch {
        return null;
    }
}
/**
 * Hook to calculate the position for the inline AI trigger/dialog
 * based on the current text selection.
 */
export function useInlineAiPosition(selectedRange, containerRef) {
    const [position, setPosition] = useState({
        x: 0,
        y: 0,
        visible: false,
    });
    const calculatePosition = useCallback(() => {
        if (!selectedRange?.text) {
            setPosition({ x: 0, y: 0, visible: false });
            return;
        }
        try {
            // First, check if we have an element reference (for input/textarea fields)
            if (selectedRange.element) {
                const element = selectedRange.element;
                // Verify the element is still in the DOM and has the expected selection
                if (document.body.contains(element) && element.selectionStart !== null) {
                    const elementRect = element.getBoundingClientRect();
                    // Check if element is in viewport
                    if (!isRectInViewport(elementRect)) {
                        setPosition({ x: 0, y: 0, visible: false });
                        return;
                    }
                    const pos = getInputSelectionPosition(element, selectedRange.startOffset, selectedRange.endOffset);
                    if (pos) {
                        setPosition({
                            x: Math.max(20, Math.min(pos.x, window.innerWidth - 220)),
                            y: Math.min(pos.y + 8, window.innerHeight - 100),
                            visible: true,
                        });
                        return;
                    }
                }
            }
            const selection = window.getSelection();
            if (!selection || selection.isCollapsed) {
                // Try to get position from iframe
                const iframe = document.querySelector("iframe.page-iframe");
                if (iframe?.contentWindow) {
                    const iframeSelection = iframe.contentWindow.getSelection();
                    if (iframeSelection && !iframeSelection.isCollapsed) {
                        const range = iframeSelection.getRangeAt(0);
                        const rect = range.getBoundingClientRect();
                        // Check if selection is in iframe's viewport
                        if (!isRectInViewport(rect, iframe)) {
                            setPosition({ x: 0, y: 0, visible: false });
                            return;
                        }
                        const iframeRect = iframe.getBoundingClientRect();
                        // Position below the selection, centered horizontally
                        const x = iframeRect.left + rect.left + rect.width / 2;
                        const y = iframeRect.top + rect.bottom + 8;
                        setPosition({
                            x: Math.max(20, Math.min(x, window.innerWidth - 220)),
                            y: Math.min(y, window.innerHeight - 100),
                            visible: true,
                        });
                        return;
                    }
                }
                setPosition({ x: 0, y: 0, visible: false });
                return;
            }
            const range = selection.getRangeAt(0);
            const rect = range.getBoundingClientRect();
            // Check if selection is in viewport
            if (!isRectInViewport(rect)) {
                setPosition({ x: 0, y: 0, visible: false });
                return;
            }
            // Position below the selection, centered horizontally
            const x = rect.left + rect.width / 2;
            const y = rect.bottom + 8;
            setPosition({
                x: Math.max(20, Math.min(x, window.innerWidth - 220)),
                y: Math.min(y, window.innerHeight - 100),
                visible: true,
            });
        }
        catch {
            setPosition({ x: 0, y: 0, visible: false });
        }
    }, [selectedRange?.text, selectedRange?.element, selectedRange?.startOffset, selectedRange?.endOffset]);
    useEffect(() => {
        calculatePosition();
        // Recalculate on scroll/resize
        const handleUpdate = () => {
            if (selectedRange?.text) {
                calculatePosition();
            }
        };
        window.addEventListener("scroll", handleUpdate, true);
        window.addEventListener("resize", handleUpdate);
        const iframe = document.querySelector("iframe.page-iframe");
        const iframeWindow = iframe?.contentWindow;
        const iframeDoc = iframeWindow?.document;
        const scrollContainer = iframeDoc?.scrollingElement || iframeDoc?.body || null;
        if (iframeWindow) {
            iframeWindow.addEventListener("scroll", handleUpdate, true);
        }
        if (scrollContainer) {
            scrollContainer.addEventListener("scroll", handleUpdate, {
                passive: true,
            });
        }
        return () => {
            window.removeEventListener("scroll", handleUpdate, true);
            window.removeEventListener("resize", handleUpdate);
            if (iframeWindow) {
                iframeWindow.removeEventListener("scroll", handleUpdate, true);
            }
            if (scrollContainer) {
                scrollContainer.removeEventListener("scroll", handleUpdate);
            }
        };
    }, [selectedRange?.text, calculatePosition]);
    return position;
}
/**
 * Calculate optimal dialog position near the trigger
 */
export function calculateDialogPosition(triggerPosition, dialogWidth = 400, dialogHeight = 300) {
    const padding = 16;
    const viewportWidth = window.innerWidth;
    const viewportHeight = window.innerHeight;
    // Try to position centered below the trigger
    let x = triggerPosition.x - dialogWidth / 2;
    let y = triggerPosition.y + 8;
    // Adjust horizontal position if it goes off screen
    if (x < padding) {
        x = padding;
    }
    else if (x + dialogWidth > viewportWidth - padding) {
        x = viewportWidth - dialogWidth - padding;
    }
    // If dialog would go below viewport, position above the selection
    if (y + dialogHeight > viewportHeight - padding) {
        // Find the selection rect to position above it
        const selection = window.getSelection();
        if (selection && !selection.isCollapsed) {
            const range = selection.getRangeAt(0);
            const rect = range.getBoundingClientRect();
            y = rect.top - dialogHeight - 8;
        }
        else {
            y = triggerPosition.y - dialogHeight - 40;
        }
    }
    // Ensure y is not negative
    y = Math.max(padding, y);
    return { x, y };
}
export default useInlineAiPosition;
//# sourceMappingURL=useInlineAiPosition.js.map