<script lang="ts">
	import { SvelteSet } from 'svelte/reactivity';
	import { EVENT_TYPE_CATEGORIES } from '$lib/data/eventTypes';

	interface Props {
		selected: string[];
	}

	let { selected = $bindable([]) }: Props = $props();

	let searchFilter = $state('');
	let selectedSet = new SvelteSet<string>(selected);
	let expandedCategories = new SvelteSet<string>();

	// Sync external changes to internal set
	$effect(() => {
		// Only sync if the arrays are actually different
		const currentValues = [...selectedSet];
		const isSame =
			currentValues.length === selected.length && currentValues.every((v) => selected.includes(v));
		if (!isSame) {
			selectedSet.clear();
			for (const v of selected) {
				selectedSet.add(v);
			}
		}
	});

	// Sync internal set back to parent
	$effect(() => {
		const newSelected = [...selectedSet];
		// Only update if actually changed to avoid infinite loops
		if (newSelected.length !== selected.length || !newSelected.every((v) => selected.includes(v))) {
			selected = newSelected;
		}
	});

	// Filter categories by search
	let filteredCategories = $derived(
		EVENT_TYPE_CATEGORIES.map((cat) => ({
			...cat,
			types: cat.types.filter(
				(t) =>
					t.label.toLowerCase().includes(searchFilter.toLowerCase()) ||
					t.value.toLowerCase().includes(searchFilter.toLowerCase())
			)
		})).filter((cat) => cat.types.length > 0)
	);

	function toggle(value: string) {
		if (selectedSet.has(value)) {
			selectedSet.delete(value);
		} else {
			selectedSet.add(value);
		}
	}

	function selectAllInCategory(categoryName: string) {
		const category = filteredCategories.find((c) => c.name === categoryName);
		if (category) {
			for (const type of category.types) {
				selectedSet.add(type.value);
			}
		}
	}

	function selectNoneInCategory(categoryName: string) {
		const category = filteredCategories.find((c) => c.name === categoryName);
		if (category) {
			for (const type of category.types) {
				selectedSet.delete(type.value);
			}
		}
	}

	function selectAll() {
		for (const cat of filteredCategories) {
			for (const type of cat.types) {
				selectedSet.add(type.value);
			}
		}
	}

	function selectNone() {
		selectedSet.clear();
	}

	function toggleCategory(categoryName: string) {
		if (expandedCategories.has(categoryName)) {
			expandedCategories.delete(categoryName);
		} else {
			expandedCategories.add(categoryName);
		}
	}

	function getSelectedCountInCategory(categoryName: string): number {
		const category = EVENT_TYPE_CATEGORIES.find((c) => c.name === categoryName);
		if (!category) return 0;
		return category.types.filter((t) => selectedSet.has(t.value)).length;
	}
</script>

<div class="space-y-3">
	<div class="flex items-center justify-between">
		<span class="text-sm font-medium text-theme">
			Event Types <span class="text-error-500">*</span>
			<span class="ml-1 text-primary-500">({selectedSet.size} selected)</span>
		</span>
		<div class="flex gap-3">
			<button
				type="button"
				onclick={selectAll}
				class="text-xs font-medium text-primary-600 hover:underline dark:text-primary-400"
			>
				Select All
			</button>
			<button
				type="button"
				onclick={selectNone}
				class="text-xs font-medium text-theme-muted hover:underline"
			>
				Clear
			</button>
		</div>
	</div>

	<!-- Search -->
	<div class="relative">
		<svg
			class="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-theme-muted"
			style="fill: none"
			stroke="currentColor"
			viewBox="0 0 24 24"
		>
			<path
				stroke-linecap="round"
				stroke-linejoin="round"
				stroke-width="2"
				d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
			/>
		</svg>
		<input
			type="text"
			bind:value={searchFilter}
			placeholder="Search event types..."
			class="placeholder-theme-muted w-full rounded-lg border border-theme bg-theme py-2 pr-3 pl-9 text-sm text-theme focus:border-primary-500 focus:ring-1 focus:ring-primary-500"
		/>
	</div>

	<!-- Category Groups -->
	<div class="max-h-72 space-y-1 overflow-y-auto rounded-lg border border-theme bg-theme-card">
		{#each filteredCategories as category (category.name)}
			{@const selectedCount = getSelectedCountInCategory(category.name)}
			{@const totalCount = category.types.length}
			{@const isExpanded = expandedCategories.has(category.name)}

			<div class="border-b border-theme last:border-b-0">
				<!-- Category Header -->
				<button
					type="button"
					onclick={() => toggleCategory(category.name)}
					class="flex w-full items-center justify-between interactive px-3 py-2.5 text-left"
				>
					<span class="flex items-center gap-2">
						<svg
							class="h-4 w-4 text-theme-muted transition-transform {isExpanded ? 'rotate-90' : ''}"
							style="fill: none"
							viewBox="0 0 24 24"
							stroke="currentColor"
						>
							<path
								stroke-linecap="round"
								stroke-linejoin="round"
								stroke-width="2"
								d="M9 5l7 7-7 7"
							/>
						</svg>
						<span class="text-sm font-medium text-theme">{category.label}</span>
					</span>
					<span
						class="rounded-full px-2 py-0.5 text-xs font-semibold {selectedCount > 0
							? 'bg-primary-500 text-white'
							: 'bg-gray-200 text-gray-500 dark:bg-gray-700 dark:text-gray-400'}"
					>
						{selectedCount}/{totalCount}
					</span>
				</button>

				<!-- Category Content -->
				{#if isExpanded}
					<div class="border-t border-theme bg-black/5 dark:bg-white/5">
						<!-- Category Actions -->
						<div class="flex items-center gap-4 px-3 py-1.5">
							<button
								type="button"
								onclick={() => selectAllInCategory(category.name)}
								class="text-xs font-medium text-primary-600 hover:underline dark:text-primary-400"
							>
								Select All
							</button>
							<button
								type="button"
								onclick={() => selectNoneInCategory(category.name)}
								class="text-xs font-medium text-theme-muted hover:underline"
							>
								Select None
							</button>
						</div>

						<!-- Event Types -->
						<div class="space-y-0.5 px-3 pb-2">
							{#each category.types as eventType (eventType.value)}
								<label
									class="flex cursor-pointer items-center gap-2 rounded interactive px-2 py-1.5"
								>
									<input
										type="checkbox"
										checked={selectedSet.has(eventType.value)}
										onchange={() => toggle(eventType.value)}
										class="border-theme-muted h-4 w-4 rounded text-primary-500 focus:ring-primary-500"
									/>
									<span class="text-sm text-theme">{eventType.label}</span>
								</label>
							{/each}
						</div>
					</div>
				{/if}
			</div>
		{/each}

		{#if filteredCategories.length === 0}
			<p class="px-3 py-4 text-center text-sm text-theme-muted italic">
				No event types match "{searchFilter}"
			</p>
		{/if}
	</div>

	{#if selectedSet.size === 0}
		<p class="text-xs text-error-500">Please select at least one event type</p>
	{/if}
</div>
