<!--
	Fase 19.2 — Emoji picker.

	Tabbed grid of ~280–360 emoji codepoints (see $lib/data/emoji-catalog).
	Header is a tablist with 4 category buttons; body is a single grid for
	the currently-selected tab. Switching tabs unmounts the previous grid
	and mounts the new one — lazy-render — so the DOM never holds more
	than `EMOJI_CATALOG[activeCategory].length` cells at once (the
	"objects" tab is the smallest; "animals" is the worst case at ~140).

	Props:
	- `selected`: the currently-active emoji string (highlights the
	  matching cell, if any).
	- `onSelect(emoji)`: fired on cell click. Caller owns the persistence
	  side-effect (update DB / Supabase row).

	Keyboard nav: arrow keys move focus between cells in the active grid.
	Cells are `tabindex={index === 0 ? 0 : -1}` (roving focus) per WAI-ARIA
	grid pattern — the parent tab order has a single entry into the grid,
	and arrow keys then walk it cell-by-cell. Tab order is consistent with
	existing modals on the host pages (settings, onboarding, manage,
	CreateCollectiveModal).
-->
<script lang="ts">
	import {
		EMOJI_CATALOG,
		CATEGORY_LABELS,
		type EmojiCategory
	} from '$lib/data/emoji-catalog';

	type Props = {
		selected: string | null;
		onSelect: (emoji: string) => void;
		onClose?: () => void;
	};

	const { selected, onSelect }: Props = $props();

	const CATEGORIES: EmojiCategory[] = ['faces', 'food', 'animals', 'objects'];

	let activeCategory = $state<EmojiCategory>('faces');
	const activeList = $derived(EMOJI_CATALOG[activeCategory]);

	let gridEl: HTMLDivElement | null = $state(null);

	function selectTab(cat: EmojiCategory) {
		activeCategory = cat;
	}

	function pick(emoji: string) {
		onSelect(emoji);
	}

	// Roving-focus keyboard nav. We resolve cells from the live DOM each
	// keystroke (instead of caching the array) so the grid swap on tab
	// change doesn't strand stale references.
	function onGridKeydown(e: KeyboardEvent) {
		const target = e.target as HTMLElement | null;
		if (!target || !gridEl) return;
		const cells = Array.from(
			gridEl.querySelectorAll<HTMLElement>('[role="gridcell"]')
		);
		const idx = cells.indexOf(target);
		if (idx < 0) return;

		let next = -1;
		const cols = 8;
		if (e.key === 'ArrowRight') next = Math.min(idx + 1, cells.length - 1);
		else if (e.key === 'ArrowLeft') next = Math.max(idx - 1, 0);
		else if (e.key === 'ArrowDown') next = Math.min(idx + cols, cells.length - 1);
		else if (e.key === 'ArrowUp') next = Math.max(idx - cols, 0);
		else if (e.key === 'Home') next = 0;
		else if (e.key === 'End') next = cells.length - 1;
		else return;

		e.preventDefault();
		cells[next]?.focus();
	}
</script>

<div class="emoji-picker" data-testid="emoji-picker">
	<!-- Tablist header. Each button toggles `activeCategory` and Svelte
	     re-renders the grid below from `EMOJI_CATALOG[activeCategory]`. -->
	<div role="tablist" class="mb-2 flex gap-1">
		{#each CATEGORIES as cat (cat)}
			<button
				type="button"
				role="tab"
				aria-selected={activeCategory === cat}
				aria-controls="emoji-picker-grid"
				data-testid={`emoji-picker-tab-${cat}`}
				onclick={() => selectTab(cat)}
				class="flex-1 rounded-md px-2 py-1 text-xs font-medium transition-colors
					{activeCategory === cat
					? 'bg-slate-900 text-white dark:bg-slate-50 dark:text-slate-900'
					: 'border border-slate-300 text-slate-600 hover:bg-slate-50 dark:border-slate-600 dark:text-slate-400 dark:hover:bg-slate-700'}"
			>
				{CATEGORY_LABELS[cat]}
			</button>
		{/each}
	</div>

	<!-- Active grid. Only one category mounted at a time. Cells have
	     fixed 32×32 footprint (h-9/w-9 with text-xl) — same size as the
	     legacy single-row picker so caller layouts don't reflow. -->
	<div
		id="emoji-picker-grid"
		bind:this={gridEl}
		role="grid"
		tabindex="-1"
		aria-label={CATEGORY_LABELS[activeCategory]}
		data-testid="emoji-picker-grid"
		data-category={activeCategory}
		onkeydown={onGridKeydown}
		class="grid max-h-64 grid-cols-8 gap-1 overflow-y-auto sm:grid-cols-10"
	>
		{#each activeList as e, i (e)}
			<button
				type="button"
				role="gridcell"
				tabindex={i === 0 ? 0 : -1}
				data-testid={`emoji-picker-cell-${e}`}
				aria-label={e}
				aria-selected={selected === e}
				onclick={() => pick(e)}
				class="flex h-9 w-9 items-center justify-center rounded-md text-xl transition-colors
					{selected === e
					? 'bg-slate-900 dark:bg-slate-100'
					: 'hover:bg-slate-100 dark:hover:bg-slate-700'}"
			>{e}</button>
		{/each}
	</div>
</div>
