<script lang="ts">
	import { createEventDispatcher, onMount } from 'svelte';

	interface Option {
		id: string;
		label: string;
	}

	const dispatch = createEventDispatcher<{ change: string[] }>();

	export let label = '';
	export let options: Option[] = [];
	export let selected: string[] = [];
	export let placeholder = 'Select options';
	export let disabled = false;

	let open = false;
	let container: HTMLDivElement | null = null;

	function updateSelection(values: string[]) {
		selected = values;
		dispatch('change', selected);
	}

	function toggleValue(id: string) {
		const values = selected.includes(id)
			? selected.filter((value) => value !== id)
			: [...selected, id];
		updateSelection(values);
	}

	function removeValue(id: string) {
		const values = selected.filter((value) => value !== id);
		updateSelection(values);
	}

	function handleOutsideClick(event: MouseEvent) {
		if (container && !container.contains(event.target as Node)) {
			open = false;
		}
	}

	onMount(() => {
		document.addEventListener('click', handleOutsideClick);
		return () => document.removeEventListener('click', handleOutsideClick);
	});
</script>

<div class="flex flex-col gap-1.5" bind:this={container}>
	{#if label}
		<label class="text-xs font-semibold text-gray-500 uppercase tracking-wide">{label}</label>
	{/if}
	<div class="relative">
		<button
			type="button"
			class={`w-full rounded-md border bg-white px-3 py-[0.4375rem] text-sm flex items-center justify-between gap-2 transition focus:outline-none focus:ring-2 focus:ring-indigo-500/20 ${disabled ? 'border-gray-200 text-gray-400 cursor-not-allowed' : 'border-gray-300 text-gray-900 shadow-sm hover:border-indigo-400'}`}
			aria-haspopup="listbox"
			aria-expanded={open}
			on:click|stopPropagation={() => {
				if (disabled) return;
				open = !open;
			}}
		>
			<div class="flex-1 flex flex-wrap gap-1.5 items-center min-h-[1.375rem]">
				{#if selected.length === 0}
					<span class="text-sm text-gray-400">{placeholder}</span>
				{:else}
					{#each selected as id}
						<span class="inline-flex items-center gap-1 rounded border border-indigo-200 bg-indigo-50 px-2 py-0.5 text-xs font-medium text-indigo-800 whitespace-nowrap">
							{options.find((option) => option.id === id)?.label ?? id}
							<button
								type="button"
								class="text-indigo-400 hover:text-indigo-700 focus:outline-none ml-0.5"
								on:click|preventDefault|stopPropagation={() => removeValue(id)}
							>
								×
							</button>
						</span>
					{/each}
				{/if}
			</div>
			<span class="text-gray-400 shrink-0">▾</span>
		</button>
		{#if open}
			<div
				class="absolute z-10 mt-1 w-full max-h-60 overflow-auto rounded-md border border-gray-200 bg-white shadow-lg"
				on:click|stopPropagation
			>
				{#if options.length === 0}
					<p class="px-3 py-2 text-sm text-gray-500">No options available</p>
				{:else}
					{#each options as option}
						<label class="flex items-center gap-3 px-3 py-2 text-sm text-gray-900 hover:bg-gray-50 cursor-pointer">
							<input
								type="checkbox"
								checked={selected.includes(option.id)}
								on:change={() => toggleValue(option.id)}
								class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
							/>
							<span>{option.label}</span>
						</label>
					{/each}
				{/if}
			</div>
		{/if}
	</div>
</div>
