<script lang="ts">
	interface Props {
		id?: string;
		name?: string;
		value: string | undefined;
		suggestions: string[];
		placeholder?: string;
		class?: string;
	}

	let {
		id,
		name,
		value = $bindable(),
		suggestions,
		placeholder = '',
		class: className = ''
	}: Props = $props();

	let open = $state(false);
	let highlightIdx = $state(-1);
	let inputEl: HTMLInputElement | undefined = $state();
	let containerEl: HTMLDivElement | undefined = $state();

	const filtered = $derived.by(() => {
		const q = (value ?? '').trim().toLowerCase();
		if (!q) return suggestions;
		return suggestions.filter((s) => s.toLowerCase().includes(q));
	});

	function handleInput() {
		open = true;
		highlightIdx = -1;
	}

	function handleFocus() {
		open = true;
	}

	function selectItem(item: string) {
		value = item;
		open = false;
		inputEl?.focus();
	}

	function handleKeydown(e: KeyboardEvent) {
		if (!open || filtered.length === 0) {
			if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
				open = true;
				e.preventDefault();
			}
			return;
		}

		if (e.key === 'ArrowDown') {
			e.preventDefault();
			highlightIdx = (highlightIdx + 1) % filtered.length;
		} else if (e.key === 'ArrowUp') {
			e.preventDefault();
			highlightIdx = highlightIdx <= 0 ? filtered.length - 1 : highlightIdx - 1;
		} else if (e.key === 'Enter' && highlightIdx >= 0) {
			e.preventDefault();
			selectItem(filtered[highlightIdx]);
		} else if (e.key === 'Escape') {
			open = false;
		}
	}

	function handleClickOutside(e: MouseEvent) {
		if (containerEl && !containerEl.contains(e.target as Node)) {
			open = false;
		}
	}
</script>

<svelte:window onclick={handleClickOutside} />

<div class="relative" bind:this={containerEl}>
	<input
		{id}
		{name}
		type="text"
		bind:this={inputEl}
		bind:value
		oninput={handleInput}
		onfocus={handleFocus}
		onkeydown={handleKeydown}
		{placeholder}
		class={className}
		autocomplete="off"
	/>

	{#if open && filtered.length > 0}
		<div class="absolute left-0 top-full z-50 mt-1 max-h-48 w-full overflow-y-auto rounded-xl border border-border bg-card shadow-[var(--shadow-soft)]">
			{#each filtered as item, i (item)}
				<button
					type="button"
					onclick={() => selectItem(item)}
					class="flex w-full items-center px-3 py-1.5 text-left text-sm text-foreground transition-colors
						{i === highlightIdx ? 'bg-accent' : 'hover:bg-accent/50'}"
				>
					{item}
				</button>
			{/each}
		</div>
	{/if}
</div>
