<script lang="ts">
import { tick } from 'svelte';
import { m } from '$lib/paraglide/messages.js';
import { clickOutside } from '$lib/shared/actions/clickOutside';
import type { components } from '$lib/generated/api';

type PersonHint = components['schemas']['PersonHint'];

let {
	persons,
	heading,
	showCue,
	onSelect
}: {
	persons: PersonHint[];
	heading: string;
	showCue: boolean;
	onSelect: (person: PersonHint) => void;
} = $props();

let open = $state(false);
let triggerEl = $state<HTMLButtonElement>();
let listEl = $state<HTMLUListElement>();

const panelId = 'disambiguation-panel';
const headingId = 'disambiguation-heading';
const names = $derived(persons.map((person) => person.displayName).join(', '));
const triggerLabel = $derived(
	persons.length === 1 ? heading : m.search_disambiguation_trigger_label()
);

async function openPicker() {
	open = true;
	await tick();
	listEl?.querySelector<HTMLButtonElement>('button')?.focus();
}

function closePicker() {
	open = false;
	triggerEl?.focus();
}

function toggle() {
	if (open) closePicker();
	else openPicker();
}

function select(person: PersonHint) {
	open = false;
	onSelect(person);
}

function onKeydown(event: KeyboardEvent) {
	if (event.key === 'Escape' && open) {
		event.stopPropagation();
		closePicker();
	}
}
</script>

<svelte:window onkeydown={onKeydown} />

<div class="relative inline-block" use:clickOutside onclickoutside={() => open && closePicker()}>
	<button
		bind:this={triggerEl}
		type="button"
		aria-haspopup="true"
		aria-expanded={open}
		aria-controls={panelId}
		aria-label={triggerLabel}
		onclick={toggle}
		class="inline-flex min-h-[44px] items-center gap-1.5 rounded-full border border-line bg-muted px-3 text-sm text-ink-2 outline-none focus-visible:ring-2 focus-visible:ring-brand-navy"
	>
		<span class="max-w-[8rem] truncate sm:max-w-[12rem]">{names}</span>
		{#if showCue}
			<span class="text-ink-3">{m.search_disambiguation_cue()}</span>
		{/if}
	</button>

	{#if open}
		<div
			id={panelId}
			class="absolute left-0 z-10 mt-1 min-w-[12rem] rounded-sm border border-line bg-surface py-1 shadow-md"
		>
			<p id={headingId} class="px-4 py-1.5 text-sm font-bold text-ink">{heading}</p>
			<ul bind:this={listEl} aria-labelledby={headingId}>
				{#each persons as person (person.id)}
					<li>
						<button
							type="button"
							aria-label={m.search_disambiguation_select_label({ name: person.displayName })}
							onclick={() => select(person)}
							class="flex min-h-[44px] w-full items-center px-4 text-left text-sm text-ink outline-none hover:bg-muted focus-visible:bg-muted focus-visible:ring-2 focus-visible:ring-brand-navy"
						>
							{person.displayName}
						</button>
					</li>
				{/each}
			</ul>
		</div>
	{/if}
</div>
