import React, { useEffect, useRef, useState, useId } from 'react';
import Icon from '../icons/Icon';
import { useEscape, useOnClickOutside } from './hooks';

/**
 * Dropdown menu (menu-button pattern).
 *
 * @param {Function} trigger  ({ ref, props }) => element — spread props on your button.
 * @param {Array}    items    [{ label, icon?, onSelect?, href?, danger?, disabled? } | { separator: true } | { heading: '…' }]
 * @param {'start'|'end'} [align='end']
 */
export default function DropdownMenu({ trigger, items = [], align = 'end', label }) {
	const [open, setOpen] = useState(false);
	const rootRef = useRef(null);
	const btnRef = useRef(null);
	const menuRef = useRef(null);
	const menuId = `bp-menu-${useId().replace(/:/g, '')}`;

	const close = (focus = true) => {
		setOpen(false);
		if (focus && btnRef.current) btnRef.current.focus();
	};
	useEscape(() => close(), open);
	useOnClickOutside(rootRef, () => setOpen(false), open);

	const focusItem = (dir) => {
		const list = menuRef.current ? Array.from(menuRef.current.querySelectorAll('[role="menuitem"]:not([aria-disabled="true"])')) : [];
		if (!list.length) return;
		const idx = list.indexOf(document.activeElement);
		let next;
		if (dir === 'first') next = 0;
		else if (dir === 'last') next = list.length - 1;
		else next = (idx + dir + list.length) % list.length;
		list[next].focus();
	};

	useEffect(() => {
		if (open) window.requestAnimationFrame(() => focusItem('first'));
	}, [open]);

	const onMenuKey = (e) => {
		if (e.key === 'ArrowDown') { e.preventDefault(); focusItem(1); }
		else if (e.key === 'ArrowUp') { e.preventDefault(); focusItem(-1); }
		else if (e.key === 'Home') { e.preventDefault(); focusItem('first'); }
		else if (e.key === 'End') { e.preventDefault(); focusItem('last'); }
		else if (e.key === 'Tab') setOpen(false);
	};

	const triggerProps = {
		'aria-haspopup': 'menu',
		'aria-expanded': open ? 'true' : 'false',
		'aria-controls': open ? menuId : undefined,
		onClick: () => setOpen((o) => !o),
		onKeyDown: (e) => {
			if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {
				e.preventDefault();
				setOpen(true);
			}
		},
	};

	return (
		<div ref={rootRef} style={{ position: 'relative', display: 'inline-flex' }}>
			{trigger({ ref: btnRef, props: triggerProps })}
			{open ? (
				<div
					ref={menuRef}
					id={menuId}
					role="menu"
					aria-label={label}
					className="bp-popover bp-menu"
					style={{ top: 'calc(100% + 4px)', [align === 'end' ? 'insetInlineEnd' : 'insetInlineStart']: 0 }}
					onKeyDown={onMenuKey}
				>
					{items.map((it, i) => {
						if (it.separator) return <div key={`sep-${i}`} className="bp-menu__sep" role="separator" />;
						if (it.heading) return <div key={`h-${i}`} className="bp-menu__label">{it.heading}</div>;
						const cls = ['bp-menu__item', it.danger ? 'bp-menu__item--danger' : ''].filter(Boolean).join(' ');
						const content = (
							<>
								{it.icon ? <Icon name={it.icon} /> : null}
								<span>{it.label}</span>
							</>
						);
						if (it.href) {
							return (
								<a key={i} role="menuitem" tabIndex={-1} className={cls} href={it.href} aria-disabled={it.disabled ? 'true' : undefined}>
									{content}
								</a>
							);
						}
						return (
							<button
								key={i}
								type="button"
								role="menuitem"
								tabIndex={-1}
								className={cls}
								aria-disabled={it.disabled ? 'true' : undefined}
								onClick={() => {
									if (it.disabled) return;
									close();
									if (it.onSelect) it.onSelect();
								}}
							>
								{content}
							</button>
						);
					})}
				</div>
			) : null}
		</div>
	);
}
