/**
 * Trap keyboard focus within a node and move focus to its first focusable
 * element on mount. Used by modal-style overlays such as the Stammbaum mobile
 * bottom sheet (#692, NFR-A11Y-004). Tab from the last focusable wraps to the
 * first and Shift+Tab from the first wraps to the last.
 */
const FOCUSABLE_SELECTOR = [
	'a[href]',
	'button:not([disabled])',
	'input:not([disabled])',
	'select:not([disabled])',
	'textarea:not([disabled])',
	'[tabindex]:not([tabindex="-1"])'
].join(',');

export function trapFocus(node: HTMLElement) {
	// Remember what had focus so it can be restored when the overlay closes
	// (WCAG 2.4.3 — don't strand keyboard/AT users at the top of the page).
	const previouslyFocused = document.activeElement as HTMLElement | null;
	const focusable = () => Array.from(node.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR));

	function onKeydown(event: KeyboardEvent) {
		if (event.key !== 'Tab') return;
		const items = focusable();
		if (items.length === 0) return;
		const first = items[0];
		const last = items[items.length - 1];
		const active = document.activeElement;
		if (event.shiftKey && active === first) {
			event.preventDefault();
			last.focus();
		} else if (!event.shiftKey && active === last) {
			event.preventDefault();
			first.focus();
		}
	}

	node.addEventListener('keydown', onKeydown);
	focusable()[0]?.focus();

	return {
		destroy() {
			node.removeEventListener('keydown', onKeydown);
			previouslyFocused?.focus?.();
		}
	};
}
