<script lang="ts">
	import { resolve } from '$app/paths';
	import { page } from '$app/state';
	import * as Collapsible from '$lib/components/ui/collapsible/index.js';
	import * as Sidebar from '$lib/components/ui/sidebar/index.js';
	import { Badge } from '$lib/components/ui/badge/index.js';
	import { useSidebar } from '$lib/components/ui/sidebar/index.js';
	import { getBookshelfState } from '$lib/state/bookshelf.svelte';
	import { getLibraryState } from '$lib/state/library.svelte';
	import { House, LibraryBig, Rows3, ChevronRightIcon } from '@lucide/svelte';

	const libraryState = getLibraryState();
	const bookshelfState = getBookshelfState();
	const sidebar = useSidebar();

	// Owned here so the collapsed rail can force it open when it expands the
	// sidebar. Previously open={isActive}, which was always false — the Shelves
	// item has no route of its own, so pathname never matched.
	let shelvesOpen = $state(false);

	// Deliberately a plain const, not $derived. These objects hold component
	// references, and `<item.icon />` is a dynamic component — if the array were
	// rebuilt on every navigation the icons would remount, flashing and shifting
	// layout. Only the url and active state need to be reactive, so they are
	// computed per-item in the markup instead.
	//
	// Active state is matched on route id rather than pathname. resolve() returns
	// an absolute path on the client but a relative one during SSR, so comparing
	// it to page.url.pathname would be false on the server and true after
	// hydration — the highlight would flash in.
	const items = [
		{
			title: 'Home',
			icon: House,
			routeId: '/(root)/(library)/library/[libraryId]',
			path: (id?: number) =>
				resolve('/(root)/(library)/library/[libraryId]', { libraryId: String(id ?? '') })
		},
		{
			title: 'Library',
			icon: LibraryBig,
			routeId: '/(root)/(library)/library/[libraryId]/view',
			path: (id?: number) =>
				resolve('/(root)/(library)/library/[libraryId]/view', { libraryId: String(id ?? '') })
		},
		{ title: 'Shelves', icon: Rows3, routeId: null, path: () => '#', shelves: [] }
	];
</script>

{#snippet shelvesTrigger(item: { title: string; icon: typeof House })}
	<item.icon class="scale-125" />
	<span class="text-md ml-2">{item.title}</span>
	<ChevronRightIcon
		class="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90"
	/>
{/snippet}

<Sidebar.Group>
	<Sidebar.Menu>
		{#each items as item (item.title)}
			{@const url = item.path(libraryState.activeLibrary?.id)}
			{@const isActive = item.routeId !== null && page.route.id === item.routeId}
			{#if 'shelves' in item}
				<Collapsible.Root bind:open={shelvesOpen} class="group/collapsible">
					{#snippet child({ props })}
						<Sidebar.MenuItem {...props}>
							{#if sidebar.state === 'collapsed'}
								<!--
                                    Sidebar.MenuSub is group-data-[collapsible=icon]:hidden, so
                                    toggling in the rail opens a list nobody can see. Expand the
                                    sidebar and open the section instead of toggling.
                                -->
								<Sidebar.MenuButton
									tooltipContent={item.title}
									class="h-10"
									onclick={() => {
										sidebar.setOpen(true);
										shelvesOpen = true;
									}}
								>
									{@render shelvesTrigger(item)}
								</Sidebar.MenuButton>
							{:else}
								<Collapsible.Trigger>
									{#snippet child({ props })}
										<Sidebar.MenuButton {...props} tooltipContent={item.title} class="h-10">
											{@render shelvesTrigger(item)}
										</Sidebar.MenuButton>
									{/snippet}
								</Collapsible.Trigger>
							{/if}
							<Collapsible.Content>
								<Sidebar.MenuSub class="w-full">
									{#each bookshelfState.getBookshelves(libraryState.activeLibrary!.id) ?? [] as shelf (shelf.id)}
										<Sidebar.MenuSubItem>
											<Sidebar.MenuSubButton>
												{#snippet child({ props })}
													<a
														href="{resolve('/(root)/(library)/library/[libraryId]/view', {
															libraryId: String(libraryState.activeLibrary!.id)
														})}?shelves={shelf.id}"
														{...props}
													>
														<Badge
															variant="outline"
															class="mr-1 scale-90 bg-sidebar-primary font-semibold text-sidebar-primary-foreground"
														>
															{shelf.total}
														</Badge>
														<span>{shelf.title}</span>
													</a>
												{/snippet}
											</Sidebar.MenuSubButton>
										</Sidebar.MenuSubItem>
									{/each}
								</Sidebar.MenuSub>
							</Collapsible.Content>
						</Sidebar.MenuItem>
					{/snippet}
				</Collapsible.Root>
			{:else}
				<Sidebar.MenuItem>
					<Sidebar.MenuButton {isActive} tooltipContent={item.title} class="h-10">
						{#snippet child({ props })}
							<!-- item.path() calls resolve(); the rule cannot trace the variable. -->
							<!-- eslint-disable-next-line svelte/no-navigation-without-resolve -->
							<a href={url} {...props}>
								{#if item.icon}
									<item.icon class="scale-125" />
								{/if}
								<span class="text-md pl-2">{item.title}</span>
							</a>
						{/snippet}
					</Sidebar.MenuButton>
				</Sidebar.MenuItem>
			{/if}
		{/each}
	</Sidebar.Menu>
</Sidebar.Group>
