<script lang="ts">
	import { Badge, badgeVariants } from '$lib/components/ui/badge/index.js';
	import { CollapsibleText } from '$lib/components/ui/collapsible-text/index.js';
	import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index';
	import * as Tooltip from '$lib/components/ui/tooltip/index';
	import * as Field from '$lib/components/ui/field/index.js';
	import { Checkbox } from '$lib/components/ui/checkbox/index.js';
	import { Button, buttonVariants } from '$lib/components/ui/button/index.js';
	import BookImage from '$lib/components/view/book-image.svelte';
	import type { BookFile } from '$lib/schema';
	import {
		Album,
		BookOpenCheck,
		BookOpenText,
		CalendarDays,
		Download,
		Link,
		NotebookPen,
		NotebookText,
		Pencil,
		PlusIcon,
		Tags,
		Trash2
	} from '@lucide/svelte';
	import { formatFileSize, getFileType } from '$lib/utils.js';
	import { getBookOperationsState } from '$lib/state/bookOperations.svelte.js';
	import { getBookshelfState } from '$lib/state/bookshelf.svelte.js';
	import { getLibraryState } from '$lib/state/library.svelte.js';
	import { Progress } from '$lib/components/ui/progress/index.js';
	import * as Accordion from '$lib/components/ui/accordion/index.js';
	import * as Table from '$lib/components/ui/table/index.js';
	import * as AlertDialog from '$lib/components/ui/alert-dialog/index.js';
	import ShelfCreateDialog from '$lib/components/forms/shelf-create-dialog.svelte';

	let { data } = $props();

	let book = $state(data.book);

	$effect(() => {
		book = data.book;
	});

	const bookOps = getBookOperationsState();
	const libraryState = getLibraryState();
	const bookshelfState = getBookshelfState();

	let deleteFiles = $state(true);
	let fileDeleteDialogOpen = $state(false);
	let fileToDelete = $state<number>();
	let createShelfDialogOpen = $state(false)

	function openBookInReader(file: BookFile) {
		if (getFileType(file.filename) === 'EPUB')
			window.open(`/book/${book.id}/read/epub/${file.id}`, '_blank', 'noopener,noreferrer');

		if (getFileType(file.filename) === 'PDF')
			window.open(`/book/${book.id}/read/pdf/${file.id}`, '_blank', 'noopener,noreferrer');
	}
</script>

<div class="mt-4 flex flex-1 flex-col items-center">
	<div class="ml-8 grid max-w-[900px] grid-cols-[minmax(250px,1fr)_2.5fr] gap-8">
		<!-- Cover image and action buttons -->
		<aside class="flex flex-col gap-4">
			<a href="/book/{book.id}" class="w-full rounded shadow-lg drop-shadow-lg">
				<BookImage
					src="/api/{book.cover_image}"
					class="h-full w-full overflow-hidden rounded object-cover"
				/>

				{#if book?.progress?.percentage}
					<Progress
						value={book?.progress.percentage}
						max={1}
						color={book?.progress.completed ? 'bg-green-600' : 'bg-yellow-500'}
						class="mt-[-8px] h-2 rounded {book?.progress.completed
							? '[&>div]:bg-green-600'
							: '[&>div]:bg-yellow-500'}"
					/>
				{/if}
			</a>

			<div class="grid grid-cols-[2fr_1fr] gap-2">
				<!-- If there are multiple files to choose from -->
				{#if book.files.length > 1}
					<!-- Read button -->
					<DropdownMenu.Root>
						<DropdownMenu.Trigger class="{buttonVariants({ variant: 'accent' })} drop-shadow-lg">
							<BookOpenText />
							Read
						</DropdownMenu.Trigger>
						<DropdownMenu.Content>
							<DropdownMenu.Group>
								<DropdownMenu.GroupHeading>File formats:</DropdownMenu.GroupHeading>
								<DropdownMenu.Separator />
								{#each book.files as file}
									<DropdownMenu.Item onclick={() => openBookInReader(file)}
										>{getFileType(file.filename)}</DropdownMenu.Item
									>
								{/each}
							</DropdownMenu.Group>
						</DropdownMenu.Content>
					</DropdownMenu.Root>

					<!-- Download Button -->
					<Tooltip.Provider>
						<Tooltip.Root ignoreNonKeyboardFocus>
							<Tooltip.Trigger>
								{#snippet child({ props })}
									<DropdownMenu.Root>
										<DropdownMenu.Trigger
											{...props}
											class="w-full {buttonVariants({
												variant: 'outline',
												size: 'icon'
											})} drop-shadow-lg"
										>
											<Download />
										</DropdownMenu.Trigger>
										<DropdownMenu.Content>
											<DropdownMenu.Group>
												<DropdownMenu.GroupHeading>File formats:</DropdownMenu.GroupHeading>
												<DropdownMenu.Separator />
												{#each book.files as file}
													<!--  Download a single file -->
													<DropdownMenu.Item
														onclick={() =>
															bookOps.downloadBookFile(book.id, file.id, file.filename)}
														>{getFileType(file.filename)}</DropdownMenu.Item
													>
												{/each}
												<!-- Download all files as zip -->
												<DropdownMenu.Separator />
												<DropdownMenu.Item
													onclick={() => {
														bookOps.downloadBooks([book.id], `${book.title}.zip`);
													}}
												>
													All (ZIP)
												</DropdownMenu.Item>
											</DropdownMenu.Group>
										</DropdownMenu.Content>
									</DropdownMenu.Root>
								{/snippet}
							</Tooltip.Trigger>
							<Tooltip.Content side="bottom">
								<p>Download</p>
							</Tooltip.Content>
						</Tooltip.Root>
					</Tooltip.Provider>
				{:else}
					<!-- There is only a single file, render simple buttons -->

					<!-- Read button -->
					<Button
						class="w-full {buttonVariants({ variant: 'accent' })} drop-shadow-lg"
						onclick={() => openBookInReader(book.files[0])}
					>
						<BookOpenText class="mr-2 size-4" />
						Read
					</Button>

					<!-- Download button -->
					<Tooltip.Provider>
						<Tooltip.Root ignoreNonKeyboardFocus>
							<Tooltip.Trigger
								class="{buttonVariants({ variant: 'outline', size: 'icon' })} w-full drop-shadow-lg"
								onclick={() =>
									bookOps.downloadBookFile(book.id, book.files[0].id, book.files[0].filename)}
							>
								<Download />
							</Tooltip.Trigger>
							<Tooltip.Content side="bottom">
								<p>Download</p>
							</Tooltip.Content>
						</Tooltip.Root>
					</Tooltip.Provider>
				{/if}
			</div>

			<div class="grid grid-cols-[1fr_1fr_1fr_1fr] gap-2">
				<!-- Mark as finished button -->
				<Tooltip.Provider>
					<Tooltip.Root>
						<Tooltip.Trigger
							class=" {buttonVariants({
								variant: 'outline',
								size: 'icon'
							})} w-full drop-shadow-lg {book?.progress?.completed === true
								? 'text-green-500'
								: ''}"
							onclick={async () => {
								if (book?.progress?.completed === true)
									await bookOps.markBooksAsIncomplete([book.id]);
								else await bookOps.markBooksAsComplete([book.id]);
							}}
						>
							<BookOpenCheck />
						</Tooltip.Trigger>
						<Tooltip.Content side="bottom">
							{#if !book?.progress?.completed}
								<p>Mark as finished</p>
							{:else}
								<p>Mark as not finished</p>
							{/if}
						</Tooltip.Content>
					</Tooltip.Root>
				</Tooltip.Provider>

				<!-- Add to shelf button -->
				<Tooltip.Provider>
					<Tooltip.Root ignoreNonKeyboardFocus>
						<Tooltip.Trigger>
							{#snippet child({ props })}
								<DropdownMenu.Root>
									<DropdownMenu.Trigger
										{...props}
										class="{buttonVariants({
											variant: 'outline',
											size: 'icon'
										})} w-full drop-shadow-lg"
									>
										<Album />
									</DropdownMenu.Trigger>
									<DropdownMenu.Content>
										<DropdownMenu.Group>
											<DropdownMenu.GroupHeading>Shelves</DropdownMenu.GroupHeading>
											<DropdownMenu.Separator />
											{#each bookshelfState.getBookshelves(libraryState.activeLibrary!.id) ?? [] as shelf}
												<DropdownMenu.CheckboxItem
													checked={book.lists.findIndex((sh) => sh.id === shelf.id) !== -1}
													onclick={async () => {
														if (book.lists.find((sh) => sh.id === shelf.id)) {
															await bookshelfState.removeBooksFromShelf(shelf.id, [book.id]);
															book.lists = book.lists.filter((sh) => sh.id !== shelf.id);
														} else {
															await bookshelfState.addBooksToShelf(shelf.id, [book.id]);
															book.lists.push(shelf);
														}
													}}
												>
													{shelf.title}
												</DropdownMenu.CheckboxItem>
											{/each}
										</DropdownMenu.Group>
										<DropdownMenu.Separator />
										<DropdownMenu.Item 
										onclick={() => createShelfDialogOpen = true}
										class="text-muted-foreground ">
											<PlusIcon class="size-4" />
											New Shelf
										</DropdownMenu.Item>
									</DropdownMenu.Content>
								</DropdownMenu.Root>
							{/snippet}
						</Tooltip.Trigger>
						<Tooltip.Content side="bottom">
							<p>Add to shelf</p>
						</Tooltip.Content>
					</Tooltip.Root>
				</Tooltip.Provider>

				<!-- Edit button -->
				<Tooltip.Provider>
					<Tooltip.Root ignoreNonKeyboardFocus>
						<Tooltip.Trigger
							onclick={() => {
								bookOps.bookToEdit = book;
								bookOps.editDialogOpen = true;
							}}
							class="{buttonVariants({ variant: 'outline', size: 'icon' })} w-full drop-shadow-lg"
						>
							<Pencil />
						</Tooltip.Trigger>
						<Tooltip.Content side="bottom">
							<p>Edit</p>
						</Tooltip.Content>
					</Tooltip.Root>
				</Tooltip.Provider>

				<!-- Delete button -->
				<Tooltip.Provider>
					<Tooltip.Root ignoreNonKeyboardFocus>
						<Tooltip.Trigger
							class="{buttonVariants({ variant: 'outline', size: 'icon' })} w-full drop-shadow-lg"
							onclick={() => {
								bookOps.deleteDialogTitle = `Delete book?`;
								bookOps.deleteFn = async (deleteFiles: boolean) => {
									await bookOps.deleteBooks([book.id], deleteFiles, false);
									libraryState.activeLibrary!.total!--
									bookshelfState.deletedBooks([book])
									await history.back();
								};
								bookOps.deleteDialogOpen = true;
							}}
						>
							<Trash2 />
						</Tooltip.Trigger>
						<Tooltip.Content side="bottom">
							<p>Delete</p>
						</Tooltip.Content>
					</Tooltip.Root>
				</Tooltip.Provider>
			</div>
		</aside>

		<main class="flex flex-col gap-1">
			<!-- Title, subtitle, and authors -->
			<h1 class="text-2xl font-semibold">{book.title}</h1>

			{#if book?.subtitle}
				<h2 class="text-lg">{book.subtitle}</h2>
			{/if}

			{#if book.series}
				<h2 class="text-base text-muted-foreground">
					{book.series.title}
					{book.series_position ? `#${book.series_position}` : ''}
				</h2>
			{/if}

			{#if book.authors && book.authors.length > 0}
				<h2 class="line-clamp-1 w-full text-lg">
					By
					{#each book.authors as author}
						<a
							href="/library/{libraryState.activeLibrary!.id}/view?authors={author.id}"
							class="cs-list hover:underline">{author.name}</a
						> &thinsp;
					{/each}
				</h2>
			{/if}

			<div class="mt-6 flex flex-col gap-4 text-sm">
				<!-- Tags -->
				{#if book?.tags.length > 0}
					<div class="flex items-center gap-2">
						<Tags size="20" />
						<span class="mr-2 text-sm">Tags: </span>
						{#each book.tags as tag (tag.id)}
							<a href="/tag/{tag.id}" class={badgeVariants({ variant: 'default' })}>{tag.name}</a>
						{/each}
					</div>
				{/if}

				<!-- Identifiers -->
				{#if book.identifiers && Object.keys(book.identifiers).length > 0}
					<div class="flex items-center gap-2">
						<Link size="18" />
						<span class="mr-2">Identifiers: </span>
						{#each Object.entries(book.identifiers) as [name, value] (name)}
							<Badge>{name}</Badge>
						{/each}
					</div>
				{/if}

				<!-- Publisher -->
				{#if book.publisher}
					<div class="flex items-center gap-2">
						<NotebookPen size="18" />
						<span class="mr-2">Publisher: </span>
						<span>{book.publisher.name}</span>
					</div>
				{/if}

				<!-- Published date -->
				{#if book.published_date}
					<div class="flex items-center gap-2">
						<CalendarDays size="18" />
						<span class="mr-2">Date published: </span>
						<span class="text-sm">{book.published_date}</span>
					</div>
				{/if}

				<!-- Page count -->
				{#if book.pages}
					<div class="flex items-center gap-2">
						<NotebookText size="18" />
						<span class="mr-2">Pages: </span>
						<span>{book.pages}</span>
					</div>
				{/if}

				<!-- Description -->
				{#if book.description}
					<CollapsibleText text={book.description} maxLength={500} />
				{/if}

				<!-- Book files -->
				<Accordion.Root
					type="single"
					class="mt-4 w-full rounded-lg bg-muted px-4 shadow-lg drop-shadow "
				>
					<!-- <Separator></Separator> -->
					<Accordion.Item value="item-1">
						<Accordion.Trigger>
							<div class="ml-2 flex gap-4">
								Library Files
								<Badge>{book.files.length}</Badge>
							</div>
						</Accordion.Trigger>
						<Accordion.Content>
							<Table.Root>
								<Table.Header>
									<Table.Row>
										<Table.Head class="w-[300px]">Filename</Table.Head>
										<Table.Head>Size</Table.Head>
										<Table.Head>File type</Table.Head>
										<Table.Head class="text-right">Actions</Table.Head>
									</Table.Row>
								</Table.Header>
								<Table.Body>
									{#each book.files as file (file.id)}
										<Table.Row>
											<Table.Cell class="max-w-[300px] min-w-0 overflow-hidden">
												<div class="wrap-break-word whitespace-normal">{file.filename}</div>
											</Table.Cell>
											<Table.Cell>{formatFileSize(file.size)}</Table.Cell>
											<Table.Cell>{getFileType(file.filename)}</Table.Cell>
											<Table.Cell class="text-right">
												<div class="flex justify-end gap-1">
													<!-- Read button -->
													{#if getFileType(file.filename) == 'EPUB' || getFileType(file.filename) == 'PDF'}
														<Tooltip.Provider>
															<Tooltip.Root ignoreNonKeyboardFocus>
																<Tooltip.Trigger
																	class="{buttonVariants({
																		variant: 'default',
																		size: 'icon'
																	})} scale-90"
																>
																	<BookOpenText />
																</Tooltip.Trigger>
																<Tooltip.Content side="bottom">
																	<p>Read</p>
																</Tooltip.Content>
															</Tooltip.Root>
														</Tooltip.Provider>
													{/if}

													<!-- Download button -->
													<Tooltip.Provider>
														<Tooltip.Root ignoreNonKeyboardFocus>
															<Tooltip.Trigger
																class="{buttonVariants({
																	variant: 'default',
																	size: 'icon'
																})} scale-90"
																onclick={async () => {
																	await bookOps.downloadBookFile(book.id, file.id, file.filename);
																}}
															>
																<Download />
															</Tooltip.Trigger>
															<Tooltip.Content side="bottom">
																<p>Download</p>
															</Tooltip.Content>
														</Tooltip.Root>
													</Tooltip.Provider>

													<!-- Delete button -->

													<Tooltip.Provider>
														<Tooltip.Root ignoreNonKeyboardFocus>
															<Tooltip.Trigger
																onclick={() => {
																	fileToDelete = file.id;
																	fileDeleteDialogOpen = true;
																}}
																class="{buttonVariants({
																	variant: 'destructive',
																	size: 'icon'
																})} scale-90"
															>
																<Trash2 />
															</Tooltip.Trigger>
															<Tooltip.Content side="bottom">Delete File</Tooltip.Content>
														</Tooltip.Root>
													</Tooltip.Provider>
												</div>
											</Table.Cell>
										</Table.Row>
									{/each}
								</Table.Body>
							</Table.Root>
						</Accordion.Content>
					</Accordion.Item>
				</Accordion.Root>
			</div>
		</main>
	</div>
</div>

<AlertDialog.Root bind:open={fileDeleteDialogOpen}>
	<AlertDialog.Content>
		<AlertDialog.Header>
			<AlertDialog.Title>Are you absolutely sure?</AlertDialog.Title>
			<AlertDialog.Description>
				This action cannot be undone. This will permanently delete the record from the database and
				the file from the filesystem.
			</AlertDialog.Description>
		</AlertDialog.Header>
		<div class="flex items-center gap-2">
			<Checkbox bind:checked={deleteFiles} />
			<Field.Label class="font-normal">Delete files from the filesystem</Field.Label>
		</div>
		<AlertDialog.Footer>
			<AlertDialog.Cancel>Cancel</AlertDialog.Cancel>
			<AlertDialog.Action
				onclick={async () => {
					await bookOps.deleteBookFiles(book.id, [fileToDelete!], deleteFiles);
					fileDeleteDialogOpen = false;
				}}
				class={buttonVariants({ variant: 'destructive' })}>Delete</AlertDialog.Action
			>
		</AlertDialog.Footer>
	</AlertDialog.Content>
</AlertDialog.Root>

<ShelfCreateDialog 
	bind:open={createShelfDialogOpen} 
	onSubmit={async (name: string) => {
		const bookshelf = await bookshelfState.addBookshelf(name, libraryState.activeLibrary!.id, [book.id])
		book.lists.push(bookshelf)
		createShelfDialogOpen = false
	}}
/>
