import { jsx } from 'react/jsx-runtime';
import React__default, { useRef, useState, useCallback, useEffect } from 'react';
import { useReducedMotion, AnimatePresence, motion } from 'motion/react';
import { createPortal } from 'react-dom';
import { cn } from '../../../utils/cn.js';
import { useContextMenuContext } from './ContextMenuContext.js';
import { useIsClient } from '../../../hooks/useIsClient.js';

/**
 * ContextMenuBody - Renders the menu at cursor position with keyboard navigation
 */
const ContextMenuBody = React__default.forwardRef(({ children, className, animation = true, "aria-label": ariaLabel, ...props }, ref) => {
    const { isOpen, onOpenChange, cursorPosition, contentRef, triggerRef, theme, } = useContextMenuContext();
    const shouldReduceMotion = useReducedMotion();
    const isClient = useIsClient();
    const localRef = useRef(null);
    const [focusedIndex, setFocusedIndex] = useState(-1);
    // Initialize position from cursorPosition if available, otherwise use 0,0
    const [position, setPosition] = useState(() => cursorPosition || { x: 0, y: 0 });
    // Get all menu items (not separators or labels)
    const getMenuItems = useCallback(() => {
        if (!localRef.current)
            return [];
        return Array.from(localRef.current.querySelectorAll('[role="menuitem"]:not([data-disabled="true"])'));
    }, []);
    // Focus a menu item by index
    const focusItem = useCallback((index) => {
        var _a;
        const items = getMenuItems();
        if (index >= 0 && index < items.length) {
            (_a = items[index]) === null || _a === void 0 ? void 0 : _a.focus();
            setFocusedIndex(index);
        }
    }, [getMenuItems]);
    // Keyboard navigation handler
    const handleKeyDown = useCallback((e) => {
        const items = getMenuItems();
        const currentIndex = focusedIndex;
        switch (e.key) {
            case "ArrowDown":
                e.preventDefault();
                const nextIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0;
                focusItem(nextIndex);
                break;
            case "ArrowUp":
                e.preventDefault();
                const prevIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1;
                focusItem(prevIndex);
                break;
            case "Home":
                e.preventDefault();
                focusItem(0);
                break;
            case "End":
                e.preventDefault();
                focusItem(items.length - 1);
                break;
            case "Escape":
                e.preventDefault();
                onOpenChange(false);
                break;
            case "Tab":
                e.preventDefault();
                onOpenChange(false);
                break;
        }
    }, [focusedIndex, focusItem, getMenuItems, onOpenChange]);
    // Click outside to close - memoize handler to prevent unnecessary re-renders
    const handleClickOutside = useCallback((e) => {
        var _a;
        // Skip if clicking on the trigger element
        if (e.target === triggerRef.current ||
            ((_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) {
            return;
        }
        onOpenChange(false);
    }, [onOpenChange, triggerRef]);
    // Only attach click outside listener when menu is open
    useEffect(() => {
        if (!isOpen)
            return;
        const listener = (event) => {
            const el = localRef.current;
            if (!el || el.contains(event.target)) {
                return;
            }
            handleClickOutside(event);
        };
        // Small delay to prevent immediate closing from the same click that opened the menu
        const timeoutId = setTimeout(() => {
            document.addEventListener("mousedown", listener);
            document.addEventListener("touchstart", listener);
        }, 0);
        return () => {
            clearTimeout(timeoutId);
            document.removeEventListener("mousedown", listener);
            document.removeEventListener("touchstart", listener);
        };
    }, [isOpen, handleClickOutside]);
    // Update position when menu opens
    useEffect(() => {
        if (isOpen && cursorPosition) {
            // Get cursor position from trigger
            const { x, y } = cursorPosition;
            // Adjust position to keep menu in viewport
            const menuWidth = 220; // min-w-[220px]
            const menuHeight = 400; // max estimated height
            let adjustedX = x;
            let adjustedY = y;
            // Check right edge
            if (x + menuWidth > window.innerWidth) {
                adjustedX = window.innerWidth - menuWidth - 10;
            }
            // Check bottom edge
            if (y + menuHeight > window.innerHeight) {
                adjustedY = window.innerHeight - menuHeight - 10;
            }
            // Keep minimum padding from edges
            adjustedX = Math.max(10, adjustedX);
            adjustedY = Math.max(10, adjustedY);
            setPosition({ x: adjustedX, y: adjustedY });
            // Focus first item after a small delay
            requestAnimationFrame(() => {
                const items = getMenuItems();
                if (items.length > 0) {
                    focusItem(0);
                }
            });
        }
        else {
            setFocusedIndex(-1);
        }
    }, [isOpen, cursorPosition, getMenuItems, focusItem]);
    // Close menu on scroll
    useEffect(() => {
        if (!isOpen)
            return;
        const handleScroll = () => {
            onOpenChange(false);
        };
        // Use capture phase to catch all scroll events
        window.addEventListener("scroll", handleScroll, true);
        return () => window.removeEventListener("scroll", handleScroll, true);
    }, [isOpen, onOpenChange]);
    // Combine refs
    const handleRef = useCallback((el) => {
        localRef.current = el;
        if (typeof ref === "function") {
            ref(el);
        }
        else if (ref) {
            ref.current = el;
        }
        if (contentRef) {
            contentRef.current = el;
        }
    }, [ref, contentRef]);
    // Animation variants
    const menuVariants = {
        hidden: {
            opacity: 0,
            scale: 0.95,
        },
        visible: {
            opacity: 1,
            scale: 1,
        },
        exit: {
            opacity: 0,
            scale: 0.95,
        },
    };
    // Extract DOM props to avoid conflicts with Framer Motion
    const { onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, ...domProps } = props;
    // Detect dark mode from document
    const isDarkMode = typeof document !== "undefined" &&
        (document.documentElement.classList.contains("dark") ||
            document.body.classList.contains("dark") ||
            document.querySelector(".dark") !== null);
    const menuContent = (jsx(AnimatePresence, { children: isOpen && (jsx(motion.div, { ref: handleRef, className: cn("fixed z-50", isDarkMode && "dark", theme.contentStyle, className), style: {
                top: `${position.y}px`,
                left: `${position.x}px`,
            }, role: "menu", "aria-label": ariaLabel || "Context menu", tabIndex: -1, onKeyDown: handleKeyDown, variants: shouldReduceMotion || !animation ? {} : menuVariants, initial: shouldReduceMotion || !animation ? undefined : "hidden", animate: shouldReduceMotion || !animation ? undefined : "visible", exit: shouldReduceMotion || !animation ? undefined : "exit", transition: shouldReduceMotion || !animation
                ? { duration: 0 }
                : {
                    type: "spring",
                    stiffness: 500,
                    damping: 30,
                }, "data-state": isOpen ? "open" : "closed", ...domProps, children: children })) }));
    // Always use portal for context menus
    return isClient
        ? createPortal(menuContent, document.body)
        : null;
});
ContextMenuBody.displayName = "ContextMenu.Body";

export { ContextMenuBody };
