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 { useDropdownContext } from './DropdownContext.js';
import { useClickOutside } from '../../../hooks/useClickOutside.js';
import { useSelectPortal } from '../../../hooks/useSelectPortal.js';
import { useIsClient } from '../../../hooks/useIsClient.js';

/**
 * Hook to detect dark mode state from document
 */
const useDarkMode = () => {
    const [isDark, setIsDark] = useState(false);
    useEffect(() => {
        if (typeof document === "undefined")
            return;
        const checkDarkMode = () => {
            const hasDarkClass = document.documentElement.classList.contains("dark") ||
                document.body.classList.contains("dark") ||
                document.querySelector(".dark") !== null;
            setIsDark(hasDarkClass);
        };
        checkDarkMode();
        // Observe class changes on html and body
        const observer = new MutationObserver(checkDarkMode);
        observer.observe(document.documentElement, {
            attributes: true,
            attributeFilter: ["class"],
        });
        observer.observe(document.body, {
            attributes: true,
            attributeFilter: ["class"],
        });
        return () => observer.disconnect();
    }, []);
    return isDark;
};
/**
 * DropdownMenu component - renders the menu with keyboard navigation
 */
const DropdownMenu = React__default.forwardRef(({ children, className, animation = true, portal = true, horizontal = false, "aria-label": ariaLabel, ...props }, ref) => {
    const { isOpen, onOpenChange, triggerRef, menuRef, menuId, placement, offset, theme, } = useDropdownContext();
    // Detect dark mode for portal content
    const isDarkMode = useDarkMode();
    const isClient = useIsClient();
    const shouldReduceMotion = useReducedMotion();
    const localRef = useRef(null);
    const [focusedIndex, setFocusedIndex] = useState(-1);
    const [typeaheadString, setTypeaheadString] = useState("");
    const typeaheadTimeoutRef = useRef(null);
    // Use the positioning hook from Popover/Select
    const { position, cssVariables, contentRef: portalContentRef, } = useSelectPortal({
        triggerRef,
        isOpen: isOpen || false,
        placement,
        offset: offset || 4,
        autoWidth: false,
        stickyTracking: true,
    });
    // Get all menu items (not separators or sections)
    const getMenuItems = useCallback(() => {
        if (!localRef.current)
            return [];
        return Array.from(localRef.current.querySelectorAll('[role="menuitem"]:not([aria-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) => {
        var _a;
        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);
                // Return focus to trigger
                (_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.focus();
                break;
            case "Tab":
                // Close menu on Tab
                onOpenChange(false);
                break;
            default:
                // Type-ahead functionality
                if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
                    e.preventDefault();
                    // Clear previous timeout
                    if (typeaheadTimeoutRef.current) {
                        clearTimeout(typeaheadTimeoutRef.current);
                    }
                    // Add character to typeahead string
                    const newString = typeaheadString + e.key.toLowerCase();
                    setTypeaheadString(newString);
                    // Find matching item
                    const matchIndex = items.findIndex((item) => { var _a; return (_a = item.textContent) === null || _a === void 0 ? void 0 : _a.toLowerCase().startsWith(newString); });
                    if (matchIndex !== -1) {
                        focusItem(matchIndex);
                    }
                    // Clear typeahead string after 500ms
                    typeaheadTimeoutRef.current = setTimeout(() => {
                        setTypeaheadString("");
                    }, 500);
                }
                break;
        }
    }, [
        focusedIndex,
        focusItem,
        getMenuItems,
        onOpenChange,
        triggerRef,
        typeaheadString,
    ]);
    // Click outside to close
    useClickOutside(localRef, (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);
    });
    // Focus first item when menu opens
    useEffect(() => {
        if (isOpen) {
            // Focus first item after a small delay to allow render
            requestAnimationFrame(() => {
                const items = getMenuItems();
                if (items.length > 0) {
                    focusItem(0);
                }
            });
        }
        else {
            setFocusedIndex(-1);
            setTypeaheadString("");
        }
    }, [isOpen, getMenuItems, focusItem]);
    // Combine refs
    const handleRef = useCallback((el) => {
        localRef.current = el;
        if (typeof ref === "function") {
            ref(el);
        }
        else if (ref) {
            ref.current = el;
        }
        if (menuRef) {
            menuRef.current = el;
        }
        if (portalContentRef &&
            typeof portalContentRef === "object" &&
            "current" in portalContentRef) {
            portalContentRef.current =
                el;
        }
    }, [ref, menuRef, portalContentRef]);
    // Animation variants
    const menuVariants = {
        hidden: {
            opacity: 0,
            scale: 0.95,
            y: -10,
        },
        visible: {
            opacity: 1,
            scale: 1,
            y: 0,
        },
        exit: {
            opacity: 0,
            scale: 0.95,
            y: -10,
        },
    };
    // Extract DOM props to avoid type conflicts with Framer Motion
    const { onAnimationStart, onAnimationEnd, onDrag, onDragStart, onDragEnd, ...domProps } = props;
    const menuContent = (jsx(AnimatePresence, { children: isOpen && (jsx(motion.div, { ref: handleRef, className: cn("fixed z-50", theme.menuStyle, horizontal ? "flex-row p-1" : "flex-col p-1", className), style: {
                ...cssVariables,
                top: `${position.top}px`,
                left: `${position.left}px`,
            }, id: menuId, role: "menu", "aria-label": ariaLabel || "Menu", "aria-orientation": horizontal ? "horizontal" : "vertical", 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", "data-placement": placement, ...domProps, children: children })) }));
    // Use portal if specified - wrap with dark class for dark mode support
    if (portal && isClient) {
        return createPortal(jsx("div", { className: isDarkMode ? "dark" : undefined, children: menuContent }), document.body);
    }
    return menuContent;
});
DropdownMenu.displayName = "Dropdown.Menu";

export { DropdownMenu };
