<script lang="ts">
	import {
		FileDropZone,
		type FileDropZoneProps,
		displaySize
	} from '$lib/components/ui/file-drop-zone/index.js';
	import { Button } from '$lib/components/ui/button/index.js';
	import * as Field from '$lib/components/ui/field/index.js';
	import { Switch } from '$lib/components/ui/switch/index';
	import BookImage from '$lib/components/view/book-image.svelte';
	import { toast } from 'svelte-sonner';

	import { updateBookCover } from '$lib/api';
	import type { Book } from '$lib/schema';
	import { tick, untrack } from 'svelte';
	import { X } from '@lucide/svelte';

	let { book, open = $bindable() }: { book: Book; open: boolean } = $props();

	let formEl = $state<HTMLFormElement>();
	let coverImagePreview = $state(`/api/${book.cover_image}`);
	let autoUploadOnDrop = $state(true);

	const onUpload: FileDropZoneProps['onUpload'] = async (uploadedFiles) => {
		updateBookCover.fields.file.set(uploadedFiles[0]);
		updateCoverPreview();
		if (autoUploadOnDrop && updateBookCover.fields.file.value()) {
			await tick();
			formEl?.requestSubmit();
		}
	};

	function updateCoverPreview() {
		const file = updateBookCover.fields.file.value();
		if (file && file.type.startsWith('image/')) {
			const reader = new FileReader();
			reader.onloadend = () => {
				coverImagePreview = reader.result;
			};
			reader.readAsDataURL(file);
		}
	}

	const onFileRejected: FileDropZoneProps['onFileRejected'] = async ({ reason, file }) => {
		toast.error(`${file.name} failed to upload!`, { description: reason });
	};

	$effect(() => {
		book;
		untrack(() => {
			updateBookCover.fields.book_id.set(book.id);
		});
	});
</script>

<form
	bind:this={formEl}
	{...updateBookCover.enhance(async ({ submit, form }) => {
		try {
			await submit();
			form.reset();
			open = false;
			toast.success('Updated book cover!');
		} catch (error) {
			console.error('Failed to update book cover: ', error);
			toast.error('Failed to update cover.');
		}
	})}
	enctype="multipart/form-data"
	class="grid grid-cols-[1fr_2fr] gap-4 p-6"
>
	<input class="hidden" {...updateBookCover.fields.book_id.as('text')} />

	<div class="flex flex-col gap-2">
		<BookImage src={coverImagePreview} class="w-64 rounded" />
	</div>

	<div class="flex flex-col gap-2">
		<FileDropZone
			{onUpload}
			{onFileRejected}
			accept=".jpeg,.jpg,.png,.webp,image/*"
			label="Only JPEG, PNG, and WEBP images supported"
			maxFiles={1}
			fileCount={updateBookCover.fields.file.value() ? 1 : 0}
		/>
		<input class="hidden" {...updateBookCover.fields.file.as('file')} />
		<div class="flex flex-col gap-2">
			{#if updateBookCover.fields.file.value()}
				<div class="flex place-items-center justify-between gap-2">
					<div class="flex flex-col">
						<span>{updateBookCover.fields.file.value().name}</span>
						<span class="text-xs text-muted-foreground"
							>{displaySize(updateBookCover.fields.file.value().size)}</span
						>
					</div>
					<Button
						variant="outline"
						size="icon"
						onclick={() => {
							updateBookCover.fields.file.set(undefined);
							coverImagePreview = `/api/${book.cover_image}`;
						}}
					>
						<X />
					</Button>
				</div>
			{/if}
		</div>

		<div class="flex flex-row items-center space-x-2">
			<Switch bind:checked={autoUploadOnDrop} />
			<Field.Label for="auto-upload-on-drop">Auto upload on file drop</Field.Label>
			<Button type="submit" class="ml-auto w-fit" disabled={!updateBookCover.fields.file.value()}>Upload</Button>
		</div>
	</div>
</form>
