/**
 * Menu primitive — flyout menu with viewport clamping, keyboard nav, submenus
 *
 * Items: [{ label, action, icon?, disabled?, divider?, children? }]
 * Directions: down-right (default), down-left, up-right, up-left
 */
const { html } = window;
const { useState, useEffect, useRef, useCallback } = hooks;

export function Menu({ items = [], anchor, open, direction = 'down-right', onSelect, onClose }) {
    const menuRef = useRef(null);
    const [pos, setPos] = useState(null);
    const [focusIdx, setFocusIdx] = useState(-1);
    const [submenu, setSubmenu] = useState(null);      // { item, anchorEl }
    const itemRefs = useRef({});                       // selIdx → DOM element

    const selectableItems = items.filter(i => !i.divider && !i.disabled);

    // Position relative to anchor
    useEffect(() => {
        if (!open || !anchor) return;
        const rect = typeof anchor.getBoundingClientRect === 'function'
            ? anchor.getBoundingClientRect()
            : anchor;
        const vw = window.innerWidth;
        const vh = window.innerHeight;

        let top, left;
        const [vDir, hDir] = direction.split('-');

        if (vDir === 'down') top = rect.bottom + 4;
        else top = rect.top - 4;

        if (hDir === 'right') left = rect.left;
        else left = rect.right;

        // Defer measurement to get menu size
        requestAnimationFrame(() => {
            const el = menuRef.current;
            if (!el) return;
            const mw = el.offsetWidth;
            const mh = el.offsetHeight;

            // Viewport clamp
            if (vDir === 'down' && top + mh > vh) top = Math.max(4, rect.top - mh - 4);
            if (vDir === 'up') { top = top - mh; if (top < 4) top = rect.bottom + 4; }
            if (hDir === 'right' && left + mw > vw) left = vw - mw - 4;
            if (hDir === 'left') { left = left - mw; if (left < 4) left = 4; }

            setPos({ top, left });
        });
        setPos({ top: -9999, left: -9999 }); // initial offscreen for measurement
        setFocusIdx(-1);
    }, [open, anchor, direction]);

    // Close on outside click
    useEffect(() => {
        if (!open) return;
        const handler = (e) => {
            if (menuRef.current && !menuRef.current.contains(e.target)) {
                if (onClose) onClose();
            }
        };
        document.addEventListener('mousedown', handler);
        return () => document.removeEventListener('mousedown', handler);
    }, [open, onClose]);

    // Keyboard navigation
    const onKeyDown = useCallback((e) => {
        const count = selectableItems.length;
        if (!count) return;

        switch (e.key) {
            case 'ArrowDown':
                e.preventDefault();
                setFocusIdx(i => (i + 1) % count);
                break;
            case 'ArrowUp':
                e.preventDefault();
                setFocusIdx(i => (i - 1 + count) % count);
                break;
            case 'Home':
                e.preventDefault();
                setFocusIdx(0);
                break;
            case 'End':
                e.preventDefault();
                setFocusIdx(count - 1);
                break;
            case 'Enter': {
                e.preventDefault();
                if (focusIdx >= 0 && focusIdx < count) {
                    const item = selectableItems[focusIdx];
                    if (item.children) setSubmenu({ item, anchorEl: itemRefs.current[focusIdx] });
                    else if (onSelect) { onSelect(item.action || item.label); if (onClose) onClose(); }
                }
                break;
            }
            case 'ArrowRight': {
                if (focusIdx >= 0 && selectableItems[focusIdx]?.children) {
                    setSubmenu({ item: selectableItems[focusIdx], anchorEl: itemRefs.current[focusIdx] });
                }
                break;
            }
            case 'ArrowLeft':
                if (submenu) setSubmenu(null);
                break;
            case 'Escape':
                if (submenu) setSubmenu(null);
                else if (onClose) onClose();
                break;
        }
    }, [selectableItems, focusIdx, submenu, onSelect, onClose]);

    // Focus menu on open
    useEffect(() => {
        if (open && menuRef.current) menuRef.current.focus();
    }, [open, pos]);

    if (!open) return null;

    let selIdx = 0;
    return html`
        <div class="sw-menu" ref=${menuRef} role="menu" tabindex="-1"
             style=${pos ? `position:fixed;top:${pos.top}px;left:${pos.left}px` : 'position:fixed;top:-9999px;left:-9999px'}
             onKeyDown=${onKeyDown}>
            ${items.map((item) => {
                if (item.divider) return html`<div class="sw-menu__divider" role="separator" />`;
                const mySelIdx = selIdx++;
                const focused = mySelIdx === focusIdx;
                return html`
                    <div class="sw-menu__item ${item.disabled ? 'sw-menu__item--disabled' : ''} ${focused ? 'sw-menu__item--focused' : ''}"
                         role="menuitem"
                         ref=${el => { if (el) itemRefs.current[mySelIdx] = el; }}
                         aria-disabled=${item.disabled || false}
                         onMouseEnter=${(e) => { setFocusIdx(mySelIdx); if (item.children) setSubmenu({ item, anchorEl: e.currentTarget }); }}
                         onClick=${() => {
                             if (item.disabled) return;
                             if (item.children) { setSubmenu({ item, anchorEl: itemRefs.current[mySelIdx] }); return; }
                             if (onSelect) onSelect(item.action || item.label);
                             if (onClose) onClose();
                         }}>
                        ${item.icon && html`<span class="sw-menu__icon">${item.icon}</span>`}
                        <span class="sw-menu__label">${item.label}</span>
                        ${item.children && html`<span class="sw-menu__arrow">\u25b6</span>`}
                    </div>
                `;
            })}
            ${submenu && html`
                <${Menu}
                    items=${submenu.item.children}
                    open
                    anchor=${submenu.anchorEl}
                    direction="down-right"
                    onSelect=${(action) => { if (onSelect) onSelect(action); if (onClose) onClose(); }}
                    onClose=${() => setSubmenu(null)}
                />
            `}
        </div>
    `;
}
