<script lang="ts">
	import BookThumbnail from './book-thumbnail.svelte';

	import ChevronRight from '@lucide/svelte/icons/chevron-right';
	import ChevronLeft from '@lucide/svelte/icons/chevron-left';

	let { title, books } = $props();
	let scrollContainer = $state<HTMLElement>();
	let needsScroll = $state(false);
	let canScrollLeft = $state(false);
	let canScrollRight = $state(false);

	// Initialize after DOM is ready and handle resize
	$effect(() => {
		if (!scrollContainer) return;

		// Create resize observer
		const resizeObserver = new ResizeObserver(() => {
			// Add a small delay to ensure accurate measurements
			setTimeout(updateScrollState, 0);
		});

		// Start observing
		resizeObserver.observe(scrollContainer);

		// Measure synchronously. Reading scrollWidth/clientWidth forces layout, so
		// the numbers are already accurate here — deferring to a macrotask just
		// guaranteed one painted frame with the arrows in the wrong state.
		updateScrollState();

		// Cleanup
		return () => {
			resizeObserver.disconnect();
		};
	});

	const scrollLeft = () => {
		if (!scrollContainer) return;
		scrollContainer.scrollBy({ left: -scrollContainer.clientWidth, behavior: 'smooth' });
		// Update state after scroll
		setTimeout(updateScrollState, 100);
	};

	const scrollRight = () => {
		if (!scrollContainer) return;
		scrollContainer.scrollBy({ left: scrollContainer.clientWidth, behavior: 'smooth' });
		// Update state after scroll
		setTimeout(updateScrollState, 100);
	};

	// Update all scroll-related states
	function updateScrollState() {
		if (!scrollContainer) return;

		const scrollWidth = Math.ceil(scrollContainer.scrollWidth);
		const clientWidth = Math.ceil(scrollContainer.clientWidth);
		const scrollLeft = Math.ceil(scrollContainer.scrollLeft);

		needsScroll = scrollWidth > clientWidth;
		canScrollLeft = scrollLeft > 0;
		canScrollRight = scrollWidth - (scrollLeft + clientWidth) > 1; // Add small buffer for rounding
	}
</script>

{#if books.length > 0}
	<div class="flex w-full flex-col">
		<div class="flex items-center">
			<h1 class="ml-4 font-serif text-xl font-semibold">{title}</h1>
			<!--
				Always mounted, only hidden. `needsScroll` is measured after mount,
				so mounting on it made the arrows pop in a frame late and shift the
				header; `invisible` keeps the space reserved from the first paint.
			-->
			<div class="ml-auto {needsScroll ? '' : 'invisible'}" aria-hidden={!needsScroll}>
				<button
					type="button"
					disabled={!canScrollLeft}
					onclick={scrollLeft}
					class={`${canScrollLeft ? 'text-primary/70 hover:text-primary' : 'text-primary/30'}`}
					aria-label="Scroll Left"
				>
					<ChevronLeft size="20" strokeWidth="3" />
				</button>
				<button
					type="button"
					disabled={!canScrollRight}
					onclick={scrollRight}
					class={`${canScrollRight ? 'text-primary/70 hover:text-primary' : 'text-primary/30'}`}
					aria-label="Scroll Right"
				>
					<ChevronRight size="20" strokeWidth="3" />
				</button>
			</div>
		</div>
		<div
			bind:this={scrollContainer}
			onscroll={updateScrollState}
			class="scrollbar-none flex w-full gap-4 overflow-x-auto p-4"
		>
			{#each books as book (book.id)}
				<div class="w-40 flex-shrink-0">
					<BookThumbnail {book} />
				</div>
			{/each}
		</div>
	</div>
{/if}
