<script lang="ts">
	import {
		bibleBooks,
		type BibleBook,
		type BibleSection,
		type Testament,
	} from "$lib/types/bible";
	import { SvelteSet } from "svelte/reactivity";

	let {
		searchQuery = $bindable(""),
		guessedIds,
		submitGuess,
		guessCount = 0,
	}: {
		searchQuery: string;
		guessedIds: SvelteSet<string>;
		submitGuess: (id: string) => void;
		guessCount: number;
	} = $props();

	type DisplayMode = "simple" | "testament" | "sections";

	const displayMode = $derived<DisplayMode>(
		guessCount >= 9 ? "sections" : guessCount >= 3 ? "testament" : "simple",
	);

	const filteredBooks = $derived(
		bibleBooks.filter((book) =>
			book.name.toLowerCase().includes(searchQuery.toLowerCase()),
		),
	);

	type SimpleGroup = { books: BibleBook[] };

	type TestamentGroup = {
		testament: Testament;
		label: string;
		books: BibleBook[];
	};

	type SectionGroup = {
		testament: Testament;
		testamentLabel: string;
		showTestamentHeader: boolean;
		section: BibleSection;
		books: BibleBook[];
	};

	const simpleGroup = $derived.by<SimpleGroup>(() => {
		const sorted = [...filteredBooks].sort((a, b) =>
			a.name.localeCompare(b.name),
		);
		return { books: sorted };
	});

	const testamentGroups = $derived.by<TestamentGroup[]>(() => {
		const old = filteredBooks
			.filter((b) => b.testament === "old")
			.sort((a, b) => a.name.localeCompare(b.name));
		const newT = filteredBooks
			.filter((b) => b.testament === "new")
			.sort((a, b) => a.name.localeCompare(b.name));
		const groups: TestamentGroup[] = [];
		if (old.length > 0) {
			groups.push({
				testament: "old",
				label: "Old Testament",
				books: old,
			});
		}
		if (newT.length > 0) {
			groups.push({
				testament: "new",
				label: "New Testament",
				books: newT,
			});
		}
		return groups;
	});

	const sectionGroups = $derived.by<SectionGroup[]>(() => {
		// Build an ordered list of (testament, section) pairs by iterating bibleBooks once
		const seenKeys: Record<string, true> = {};
		const orderedPairs: { testament: Testament; section: BibleSection }[] =
			[];

		for (const book of bibleBooks) {
			const key = `${book.testament}:${book.section}`;
			if (!seenKeys[key]) {
				seenKeys[key] = true;
				orderedPairs.push({
					testament: book.testament,
					section: book.section,
				});
			}
		}

		const groups: SectionGroup[] = [];
		let lastTestament: Testament | null = null;

		for (const pair of orderedPairs) {
			const books = filteredBooks.filter(
				(b) =>
					b.testament === pair.testament &&
					b.section === pair.section,
			);
			if (books.length === 0) continue;

			const showTestamentHeader = pair.testament !== lastTestament;
			lastTestament = pair.testament;

			groups.push({
				testament: pair.testament,
				testamentLabel:
					pair.testament === "old"
						? "Old Testament"
						: "New Testament",
				showTestamentHeader,
				section: pair.section,
				books,
			});
		}

		return groups;
	});

	// First book in display order for Enter key submission
	const firstBookId = $derived.by<string | null>(() => {
		if (filteredBooks.length === 0) return null;
		if (displayMode === "simple") {
			return simpleGroup.books[0]?.id ?? null;
		}
		if (displayMode === "testament") {
			return testamentGroups[0]?.books[0]?.id ?? null;
		}
		return sectionGroups[0]?.books[0]?.id ?? null;
	});

	function handleKeydown(e: KeyboardEvent) {
		if (e.key === "Enter" && firstBookId) {
			submitGuess(firstBookId);
		}
	}

	// const showBanner = $derived(guessCount >= 3);
	const showBanner = false;
	const bannerIsIndigo = $derived(guessCount >= 9);
</script>

{#if showBanner}
	<p
		class="mb-3 text-xs font-medium text-gray-500 dark:text-gray-400"
		role="status"
		aria-live="polite"
	>
		{#if bannerIsIndigo}
			Testament &amp; section groups now visible
		{:else}
			Old &amp; New Testament groups now visible
		{/if}
	</p>
{/if}

<div class="relative">
	<div class="relative">
		<svg
			class="absolute left-4 sm:left-6 top-1/2 -translate-y-1/2 w-5 h-5 sm:w-6 sm:h-6 text-gray-400"
			fill="none"
			stroke="currentColor"
			viewBox="0 0 24 24"
			xmlns="http://www.w3.org/2000/svg"
			aria-hidden="true"
		>
			<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
			bind:value={searchQuery}
			placeholder="Type to guess a book (e.g. 'Genesis', 'John')..."
			class="w-full pl-12 sm:pl-16 p-4 sm:p-6 border-2 border-gray-500 dark:border-gray-600 rounded-2xl text-base sm:text-lg md:text-xl focus:outline-none focus:border-blue-600 dark:focus:border-blue-400 focus:ring-4 focus:ring-blue-200 dark:focus:ring-blue-900/50 transition-all bg-white dark:bg-gray-800 dark:text-gray-100 dark:placeholder-gray-400"
			onkeydown={handleKeydown}
			autocomplete="off"
		/>
		{#if searchQuery}
			<button
				class="absolute right-4 sm:right-6 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 transition-colors"
				onclick={() => (searchQuery = "")}
				aria-label="Clear search"
			>
				<svg
					class="w-5 h-5 sm:w-6 sm:h-6"
					fill="none"
					stroke="currentColor"
					viewBox="0 0 24 24"
					xmlns="http://www.w3.org/2000/svg"
					aria-hidden="true"
				>
					<path
						stroke-linecap="round"
						stroke-linejoin="round"
						stroke-width="2"
						d="M6 18L18 6M6 6l12 12"
					/>
				</svg>
			</button>
		{/if}
	</div>

	{#if searchQuery && filteredBooks.length > 0}
		<ul
			class="mt-4 max-h-60 sm:max-h-80 overflow-y-auto bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-2xl shadow-xl"
			role="listbox"
		>
			{#if displayMode === "simple"}
				{#each simpleGroup.books as book (book.id)}
					<li role="option" aria-selected={guessedIds.has(book.id)}>
						<button
							class="w-full px-5 py-4 text-left border-b border-gray-100 last:border-b-0 flex items-center transition-all
                {guessedIds.has(book.id)
								? 'opacity-50 cursor-not-allowed pointer-events-none'
								: 'hover:bg-blue-50 hover:text-blue-700'}"
							onclick={() => submitGuess(book.id)}
							tabindex={guessedIds.has(book.id) ? -1 : 0}
						>
							<span
								class="font-semibold dark:text-gray-100 {guessedIds.has(
									book.id,
								)
									? 'line-through text-gray-400 dark:text-gray-500'
									: ''}"
							>
								{book.name}
							</span>
						</button>
					</li>
				{/each}
			{:else if displayMode === "testament"}
				{#each testamentGroups as group (group.testament)}
					<li role="presentation">
						<div
							class="px-5 py-2 flex items-center gap-3 bg-gray-50 dark:bg-gray-700/50 border-b border-gray-100 dark:border-gray-700"
						>
							<span
								class="text-xs font-semibold uppercase tracking-wider text-gray-400 dark:text-gray-400"
							>
								{group.label}
							</span>
							<div
								class="flex-1 h-px bg-gray-200 dark:bg-gray-600"
							></div>
						</div>
						<ul>
							{#each group.books as book (book.id)}
								<li
									role="option"
									aria-selected={guessedIds.has(book.id)}
								>
									<button
										class="w-full px-5 py-4 text-left border-b border-gray-100 dark:border-gray-700 last:border-b-0 flex items-center transition-all dark:text-gray-200
                      {guessedIds.has(book.id)
											? 'opacity-50 cursor-not-allowed pointer-events-none'
											: 'hover:bg-blue-50 dark:hover:bg-blue-900/40 hover:text-blue-700 dark:hover:text-blue-300'}"
										onclick={() => submitGuess(book.id)}
										tabindex={guessedIds.has(book.id)
											? -1
											: 0}
									>
										<span
											class="font-semibold {guessedIds.has(
												book.id,
											)
												? 'line-through text-gray-400 dark:text-gray-500'
												: ''}"
										>
											{book.name}
										</span>
									</button>
								</li>
							{/each}
						</ul>
					</li>
				{/each}
			{:else}
				{#each sectionGroups as group (`${group.testament}:${group.section}`)}
					<li role="presentation">
						{#if group.showTestamentHeader}
							<div
								class="px-5 pt-3 pb-1 flex items-center gap-3 bg-gray-50 dark:bg-gray-700/50 border-b border-gray-100 dark:border-gray-700"
							>
								<span
									class="text-xs font-bold uppercase tracking-wider text-gray-500 dark:text-gray-400"
								>
									{group.testamentLabel}
								</span>
								<div
									class="flex-1 h-px bg-gray-200 dark:bg-gray-600"
								></div>
							</div>
						{/if}
						<div
							class="px-7 py-1.5 flex items-center gap-3 bg-gray-50/50 dark:bg-gray-700/30 border-b border-gray-100 dark:border-gray-700"
						>
							<span
								class="text-[11px] font-medium uppercase tracking-wider text-gray-400 dark:text-gray-500"
							>
								{group.section}
							</span>
							<div
								class="flex-1 h-px bg-gray-100 dark:bg-gray-600"
							></div>
						</div>
						<ul>
							{#each group.books as book (book.id)}
								<li
									role="option"
									aria-selected={guessedIds.has(book.id)}
								>
									<button
										class="w-full px-5 py-4 text-left border-b border-gray-100 dark:border-gray-700 last:border-b-0 flex items-center transition-all dark:text-gray-200
                      {guessedIds.has(book.id)
											? 'opacity-50 cursor-not-allowed pointer-events-none'
											: 'hover:bg-blue-50 dark:hover:bg-blue-900/40 hover:text-blue-700 dark:hover:text-blue-300'}"
										onclick={() => submitGuess(book.id)}
										tabindex={guessedIds.has(book.id)
											? -1
											: 0}
									>
										<span
											class="font-semibold {guessedIds.has(
												book.id,
											)
												? 'line-through text-gray-400 dark:text-gray-500'
												: ''}"
										>
											{book.name}
										</span>
									</button>
								</li>
							{/each}
						</ul>
					</li>
				{/each}
			{/if}
		</ul>
	{:else if searchQuery}
		<p class="mt-4 text-center text-gray-500 dark:text-gray-400 p-8">
			No books found
		</p>
	{/if}
</div>
