<!--
	⌘K command palette. Jump to any section, heap, folder, or tag category,
	plus a few global actions (dark mode, shortcut overlay). Data comes from
	the same TanStack queries the sidebar already keeps warm (['heaps'],
	['folders', …]), so opening the palette costs no extra fetches once the
	app has booted. bits-ui's Command owns filtering and keyboard selection.
-->
<script lang="ts">
	import { goto } from '$app/navigation';
	import { Command, Dialog } from 'bits-ui';
	import { createQuery } from '@tanstack/svelte-query';
	import { toggleMode } from 'mode-watcher';
	import {
		Archive,
		EyeOff,
		Folder,
		Image,
		Keyboard,
		Layers,
		ListChecks,
		Moon,
		NotebookPen,
		Tags,
		Users
	} from 'lucide-svelte';
	import { listFolders, listHeaps, type PpAlbum, type PpFolder } from '$lib/services/photoprism';
	import { isAuthenticated, userLibraryBase } from '$lib/stores/session.svelte';
	import { closePalette, toggleShortcuts, view } from '$lib/stores/view.svelte';

	const heapsQuery = createQuery<PpAlbum[]>(() => ({
		queryKey: ['heaps'],
		queryFn: listHeaps,
		enabled: isAuthenticated() && view.paletteOpen
	}));
	const foldersQuery = createQuery<PpFolder[]>(() => ({
		queryKey: ['folders', userLibraryBase()],
		queryFn: listFolders,
		staleTime: 30_000,
		enabled: isAuthenticated() && view.paletteOpen
	}));

	function run(fn: () => void) {
		closePalette();
		fn();
	}

	const go = (path: string) => () => run(() => void goto(path));

	interface Entry {
		label: string;
		icon: typeof Image;
		action: () => void;
	}

	const SECTIONS: Entry[] = [
		{ label: 'All photos', icon: Image, action: go('/') },
		{ label: 'Review queue', icon: ListChecks, action: go('/review') },
		{ label: 'Archive', icon: Archive, action: go('/?section=archive') },
		{ label: 'Hidden', icon: EyeOff, action: go('/?section=hidden') },
		{ label: 'Notes', icon: NotebookPen, action: go('/notes') },
		{ label: 'Tags', icon: Tags, action: go('/tags/labels') },
		{ label: 'People', icon: Users, action: go('/tags/people') },
		{ label: 'Duplicates', icon: Layers, action: go('/review?tab=stacks') }
	];

	const ACTIONS: Entry[] = [
		{ label: 'Toggle dark mode', icon: Moon, action: () => run(toggleMode) },
		{ label: 'Keyboard shortcuts', icon: Keyboard, action: () => run(toggleShortcuts) }
	];

	// Folders can number in the hundreds; the palette lists them all and
	// lets Command's fuzzy filter narrow. Sorted shallow-first so top-level
	// folders surface before deep ones on an empty query.
	const folderEntries = $derived(
		[...(foldersQuery.data ?? [])]
			.sort(
				(a, b) =>
					a.Path.split('/').length - b.Path.split('/').length || a.Path.localeCompare(b.Path)
			)
			.slice(0, 400)
	);
</script>

<Dialog.Root
	open={view.paletteOpen}
	onOpenChange={(o) => {
		if (!o) closePalette();
	}}
>
	<Dialog.Portal>
		<Dialog.Overlay class="fixed inset-0 z-[80] bg-black/50 backdrop-blur-sm" />
		<Dialog.Content
			class="fixed left-1/2 top-24 z-[81] w-[min(560px,92vw)] -translate-x-1/2 overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl"
			aria-label="Command palette"
		>
			<Command.Root class="flex max-h-[60vh] flex-col">
				<Command.Input
					class="w-full border-b border-border bg-transparent px-4 py-3 text-sm outline-none placeholder:text-muted-foreground"
					placeholder="Jump to a view, heap, or folder…"
				/>
				<Command.List class="overflow-y-auto p-1.5">
					<Command.Viewport>
						<Command.Empty class="px-3 py-6 text-center text-xs text-muted-foreground">
							No matches.
						</Command.Empty>

						<Command.Group>
							<Command.GroupHeading
								class="px-2 pb-1 pt-2 text-[10px] uppercase tracking-wide text-muted-foreground"
							>
								Go to
							</Command.GroupHeading>
							<Command.GroupItems>
								{#each SECTIONS as s (s.label)}
									<Command.Item
										value={s.label}
										onSelect={s.action}
										class="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-xs data-selected:bg-accent"
									>
										<s.icon class="h-3.5 w-3.5 text-muted-foreground" />
										{s.label}
									</Command.Item>
								{/each}
							</Command.GroupItems>
						</Command.Group>

						{#if (heapsQuery.data ?? []).length > 0}
							<Command.Group>
								<Command.GroupHeading
									class="px-2 pb-1 pt-2 text-[10px] uppercase tracking-wide text-muted-foreground"
								>
									Heaps
								</Command.GroupHeading>
								<Command.GroupItems>
									{#each heapsQuery.data ?? [] as heap (heap.UID)}
										<Command.Item
											value={`heap ${heap.Title}`}
											onSelect={go(`/?section=heap&heap=${heap.UID}`)}
											class="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-xs data-selected:bg-accent"
										>
											<Layers class="h-3.5 w-3.5 text-muted-foreground" />
											{heap.Title}
											{#if heap.PhotoCount}
												<span class="ml-auto text-[10px] text-muted-foreground">
													{heap.PhotoCount}
												</span>
											{/if}
										</Command.Item>
									{/each}
								</Command.GroupItems>
							</Command.Group>
						{/if}

						{#if folderEntries.length > 0}
							<Command.Group>
								<Command.GroupHeading
									class="px-2 pb-1 pt-2 text-[10px] uppercase tracking-wide text-muted-foreground"
								>
									Folders
								</Command.GroupHeading>
								<Command.GroupItems>
									{#each folderEntries as folder (folder.Path)}
										<Command.Item
											value={`folder ${folder.Path}`}
											onSelect={go(`/?folder=${encodeURIComponent(folder.Path)}`)}
											class="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-xs data-selected:bg-accent"
										>
											<Folder class="h-3.5 w-3.5 text-muted-foreground" />
											<span class="truncate">{folder.Path}</span>
										</Command.Item>
									{/each}
								</Command.GroupItems>
							</Command.Group>
						{/if}

						<Command.Group>
							<Command.GroupHeading
								class="px-2 pb-1 pt-2 text-[10px] uppercase tracking-wide text-muted-foreground"
							>
								Actions
							</Command.GroupHeading>
							<Command.GroupItems>
								{#each ACTIONS as a (a.label)}
									<Command.Item
										value={a.label}
										onSelect={a.action}
										class="flex cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-xs data-selected:bg-accent"
									>
										<a.icon class="h-3.5 w-3.5 text-muted-foreground" />
										{a.label}
									</Command.Item>
								{/each}
							</Command.GroupItems>
						</Command.Group>
					</Command.Viewport>
				</Command.List>
			</Command.Root>
		</Dialog.Content>
	</Dialog.Portal>
</Dialog.Root>
