<script lang="ts">
	import { onMount } from 'svelte';

	interface BookloreBook {
		id: number; title: string; authors: string[]; libraryId: number; libraryName: string;
		categories: string[]; pageCount: number | null; publisher: string | null; addedOn: string;
		isbn13: string | null; isbn10: string | null; googleId: string | null; format: string | null;
	}
	interface Library { id: number; name: string; }

	interface KindleTarget { id: string; label: string; email: string; }

	let books = $state<BookloreBook[]>([]);
	let libraries = $state<Library[]>([]);
	let loading = $state(true);
	let searchQuery = $state('');
	let selectedLibrary = $state<number | null>(null);

	// Detail / Kindle
	let selectedBook = $state<BookloreBook | null>(null);
	let kindleTargets = $state<KindleTarget[]>([]);
	let kindleConfigured = $state(false);
	let sendingKindle = $state(false);
	let kindleResult = $state<string | null>(null);

	const filtered = $derived(() => {
		let list = books;
		if (selectedLibrary !== null) list = list.filter(b => b.libraryId === selectedLibrary);
		if (searchQuery) {
			const q = searchQuery.toLowerCase();
			list = list.filter(b => b.title.toLowerCase().includes(q) || b.authors.some(a => a.toLowerCase().includes(q)));
		}
		return list;
	});

	onMount(async () => {
		try {
			const [booksRes, libsRes] = await Promise.all([
				fetch('/api/booklore/books', { credentials: 'include' }),
				fetch('/api/booklore/libraries', { credentials: 'include' }),
			]);
			if (booksRes.ok) { const data = await booksRes.json(); books = data.books || []; }
			if (libsRes.ok) { const data = await libsRes.json(); libraries = (data.libraries || []).map((l: any) => ({ id: l.id, name: l.name })); }
		} catch { /* silent */ }
		loading = false;

		// Lazy-resolve covers for books without ISBNs
		const needsCover = books.filter(b => !b.isbn13 && !b.isbn10 && !b.googleId);
		if (needsCover.length > 0) resolveCoversLazy(needsCover);

		// Load Kindle targets
		try {
			const kRes = await fetch('/api/kindle/targets', { credentials: 'include' });
			if (kRes.ok) {
				const kData = await kRes.json();
				kindleTargets = kData.targets || [];
				kindleConfigured = kData.configured || false;
			}
		} catch { /* silent */ }
	});

	function openBook(book: BookloreBook) {
		selectedBook = book;
		kindleResult = null;
	}

	function closeBook() {
		selectedBook = null;
		kindleResult = null;
	}

	let lastKindleSendTime = 0;
	async function sendToKindle(targetId: string) {
		const now = Date.now();
		if (!selectedBook || sendingKindle || now - lastKindleSendTime < 5000) return;
		lastKindleSendTime = now;
		sendingKindle = true;
		kindleResult = null;
		try {
			const res = await fetch(`/api/booklore/books/${selectedBook.id}/send-to-kindle`, {
				method: 'POST', credentials: 'include',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ target: targetId }),
			});
			const data = await res.json();
			if (res.ok && data.success) {
				kindleResult = `Sent "${data.title}" (${data.format}) to ${data.sentTo}`;
			} else {
				kindleResult = `Error: ${data.error || 'Failed to send'}`;
			}
		} catch {
			kindleResult = 'Network error';
		}
		sendingKindle = false;
	}

	// Cover cache: bookId → cover URL, persisted in localStorage
	const COVER_CACHE_KEY = 'booklore_covers';
	const COVER_CACHE_MISS = 'booklore_covers_miss'; // IDs we already tried and found nothing

	function loadCoverCache(): Record<string, string> {
		try { return JSON.parse(localStorage.getItem(COVER_CACHE_KEY) || '{}'); } catch { return {}; }
	}
	function loadMissCache(): Record<string, boolean> {
		try { return JSON.parse(localStorage.getItem(COVER_CACHE_MISS) || '{}'); } catch { return {}; }
	}
	function saveCoverCache(cache: Record<string, string>) {
		try { localStorage.setItem(COVER_CACHE_KEY, JSON.stringify(cache)); } catch { /* silent */ }
	}
	function saveMissCache(cache: Record<string, boolean>) {
		try { localStorage.setItem(COVER_CACHE_MISS, JSON.stringify(cache)); } catch { /* silent */ }
	}

	let resolvedCovers = $state<Record<string, string>>(loadCoverCache());
	let missCache = loadMissCache();

	function coverUrl(book: BookloreBook): string | null {
		const isbn = book.isbn13 || book.isbn10;
		if (isbn) return `https://covers.openlibrary.org/b/isbn/${isbn}-M.jpg`;
		if (book.googleId) return `https://books.google.com/books/content?id=${book.googleId}&printsec=frontcover&img=1&zoom=1`;
		if (resolvedCovers[book.id]) return resolvedCovers[book.id];
		return null;
	}

	async function resolveCoversLazy(booksToResolve: BookloreBook[]) {
		// Filter out books we already cached or tried
		const todo = booksToResolve.filter(b => !resolvedCovers[b.id] && !missCache[b.id]);
		if (todo.length === 0) return;

		for (let i = 0; i < todo.length; i += 5) {
			const batch = todo.slice(i, i + 5);
			await Promise.all(batch.map(async (book) => {
				try {
					const q = encodeURIComponent(book.title);
					const author = book.authors[0] ? `&author=${encodeURIComponent(book.authors[0])}` : '';
					const res = await fetch(`https://openlibrary.org/search.json?title=${q}${author}&limit=1&fields=isbn,cover_edition_key`);
					if (res.ok) {
						const data = await res.json();
						const doc = data.docs?.[0];
						if (doc) {
							const isbn = doc.isbn?.[0];
							if (isbn) {
								resolvedCovers = { ...resolvedCovers, [book.id]: `https://covers.openlibrary.org/b/isbn/${isbn}-M.jpg` };
								saveCoverCache(resolvedCovers);
								return;
							}
							const olid = doc.cover_edition_key;
							if (olid) {
								resolvedCovers = { ...resolvedCovers, [book.id]: `https://covers.openlibrary.org/b/olid/${olid}-M.jpg` };
								saveCoverCache(resolvedCovers);
								return;
							}
						}
					}
					// No cover found — mark as miss so we don't retry
					missCache[book.id] = true;
					saveMissCache(missCache);
				} catch { /* silent */ }
			}));
		}
	}
</script>

<div class="filter-row">
	<div class="search-wrap">
		<svg class="s-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
		<input class="s-input" type="text" placeholder="Search your library..." bind:value={searchQuery} />
	</div>
	{#if libraries.length > 1}
		<div class="lib-pills">
			<button class="lib-pill" class:active={selectedLibrary === null} onclick={() => selectedLibrary = null}>All ({books.length})</button>
			{#each libraries as lib}
				<button class="lib-pill" class:active={selectedLibrary === lib.id} onclick={() => selectedLibrary = selectedLibrary === lib.id ? null : lib.id}>{lib.name}</button>
			{/each}
		</div>
	{/if}
</div>

{#if loading}
	<div class="book-grid">
		{#each Array(8) as _}
			<div class="book-card"><div class="book-cover skeleton"></div><div class="book-info"><div class="skeleton" style="width:80%;height:14px"></div><div class="skeleton" style="width:60%;height:12px;margin-top:6px"></div></div></div>
		{/each}
	</div>
{:else if filtered().length === 0}
	<div class="empty">{searchQuery ? `No books found for "${searchQuery}"` : 'No books in library'}</div>
{:else}
	<div class="book-grid">
		{#each filtered() as book (book.id)}
			{@const cover = coverUrl(book)}
			<!-- svelte-ignore a11y_no_static_element_interactions -->
			<div class="book-card" onclick={() => openBook(book)}>
				<div class="book-cover">
					{#if cover}
						<img src={cover} alt="" loading="lazy" onerror={(e) => { (e.currentTarget as HTMLImageElement).style.display = 'none'; (e.currentTarget as HTMLImageElement).nextElementSibling?.removeAttribute('style'); }} />
						<span class="book-letter" style="display:none">{book.title.charAt(0)}</span>
					{:else}
						<span class="book-letter">{book.title.charAt(0)}</span>
					{/if}
					{#if book.format}
						<span class="fmt-badge {book.format === 'EPUB' ? 'epub' : book.format === 'PDF' ? 'pdf' : 'other'}">{book.format}</span>
					{/if}
				</div>
				<div class="book-info">
					<div class="book-title">{book.title}</div>
					<div class="book-author">{book.authors.join(', ') || 'Unknown'}</div>
					<div class="book-meta-row">
						<span class="book-lib">{book.libraryName}</span>
						{#if book.pageCount}<span class="book-pages">{book.pageCount}p</span>{/if}
					</div>
				</div>
			</div>
		{/each}
	</div>
{/if}

<!-- Book detail modal -->
{#if selectedBook}
	{@const cover = coverUrl(selectedBook)}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="modal-overlay" onclick={closeBook}>
		<!-- svelte-ignore a11y_no_static_element_interactions -->
		<div class="modal-sheet" onclick={(e) => e.stopPropagation()}>
			<div class="modal-header">
				<div class="modal-title">Book Details</div>
				<button class="modal-close" onclick={closeBook}>
					<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
				</button>
			</div>
			<div class="modal-body">
				<div class="detail-top">
					{#if cover}
						<img class="detail-cover" src={cover} alt="" />
					{:else}
						<div class="detail-cover-placeholder">{selectedBook.title.charAt(0)}</div>
					{/if}
					<div class="detail-info">
						<div class="detail-title">{selectedBook.title}</div>
						<div class="detail-author">{selectedBook.authors.join(', ') || 'Unknown'}</div>
						<div class="detail-meta">
							{#if selectedBook.publisher}<span>{selectedBook.publisher}</span>{/if}
							{#if selectedBook.pageCount}<span>{selectedBook.pageCount} pages</span>{/if}
						</div>
						<div class="detail-badges">
							{#if selectedBook.format}
								<span class="fmt-badge-inline {selectedBook.format === 'EPUB' ? 'epub' : selectedBook.format === 'PDF' ? 'pdf' : 'other'}">{selectedBook.format}</span>
							{/if}
							<span class="detail-lib">{selectedBook.libraryName}</span>
							{#if selectedBook.categories.length > 0}
								{#each selectedBook.categories.slice(0, 2) as cat}
									<span class="detail-cat">{cat}</span>
								{/each}
							{/if}
						</div>
					</div>
				</div>

				{#if kindleConfigured && kindleTargets.length > 0}
					<div class="kindle-section">
						<div class="kindle-label">Send to Kindle</div>
						<div class="kindle-actions">
							{#each kindleTargets as target}
								<button class="kindle-btn" onclick={() => sendToKindle(target.id)} disabled={sendingKindle}>
									<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>
									{sendingKindle ? 'Sending...' : target.label}
								</button>
							{/each}
						</div>
						{#if kindleResult}
							<div class="kindle-result" class:error={kindleResult.startsWith('Error')}>{kindleResult}</div>
						{/if}
					</div>
				{/if}
			</div>
		</div>
	</div>
{/if}

<style>
	.filter-row { margin-bottom: var(--sp-5); }
	.search-wrap { position: relative; margin-bottom: var(--sp-3); }
	.s-icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--text-4); pointer-events: none; }
	.s-input { width: 100%; padding: 10px 14px 10px 40px; border-radius: var(--radius); border: 1.5px solid var(--border); background: var(--card); color: var(--text-1); font-size: var(--text-md); font-family: var(--font); }
	.s-input:focus { outline: none; border-color: var(--accent); }
	.s-input::placeholder { color: var(--text-4); }

	.lib-pills { display: flex; flex-wrap: wrap; gap: var(--sp-1); }
	.lib-pill { padding: var(--sp-2) 14px; border-radius: var(--radius-md); font-size: var(--text-base); font-weight: 500; color: var(--text-3); background: none; border: none; cursor: pointer; font-family: var(--font); transition: all var(--transition); }
	.lib-pill:hover { color: var(--text-1); background: var(--card-hover); }
	.lib-pill.active { color: var(--text-1); background: var(--card); box-shadow: var(--shadow-xs); }

	.book-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--module-gap); }
	.book-card { background: var(--card); border-radius: var(--radius); border: 1px solid var(--border); box-shadow: var(--shadow-sm); overflow: hidden; transition: all var(--transition); }
	.book-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
	.book-cover { width: 100%; aspect-ratio: 2/3; background: var(--surface-secondary); display: flex; align-items: center; justify-content: center; overflow: hidden; }
	.book-cover img { width: 100%; height: 100%; object-fit: cover; }
	.book-letter { font-size: var(--text-3xl); font-weight: 300; color: var(--text-4); user-select: none; }
	.book-info { padding: var(--sp-3) 14px 14px; }
	.book-title { font-size: var(--text-base); font-weight: 600; color: var(--text-1); line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
	.book-author { font-size: var(--text-sm); color: var(--text-3); margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
	.book-meta-row { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2); }
	.book-lib { font-size: var(--text-xs); font-weight: 500; padding: 2px var(--sp-2); border-radius: var(--radius-full); background: var(--accent-dim); color: var(--accent); }
	.book-pages { font-size: var(--text-xs); color: var(--text-4); font-family: var(--mono); }

	.empty { padding: var(--sp-12); text-align: center; color: var(--text-3); font-size: var(--text-base); }

	.skeleton { background: linear-gradient(90deg, var(--card) 25%, var(--card-hover) 50%, var(--card) 75%); background-size: 200% 100%; animation: shimmer 1.5s infinite; border-radius: var(--radius-xs); }
	@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

	.book-card { cursor: pointer; }
	.book-cover { position: relative; }
	.fmt-badge { position: absolute; top: var(--sp-2); right: var(--sp-2); font-size: var(--text-xs); font-weight: 700; padding: 2px var(--sp-2); border-radius: var(--radius-xs); text-transform: uppercase; letter-spacing: 0.03em; }
	.fmt-badge.epub { background: var(--accent-dim); color: var(--accent); }
	.fmt-badge.pdf { background: var(--error-dim); color: var(--error); }
	.fmt-badge.other { background: var(--card-hover); color: var(--text-3); }
	.fmt-badge-inline { font-size: var(--text-xs); font-weight: 700; padding: 2px var(--sp-2); border-radius: var(--radius-xs); text-transform: uppercase; }
	.fmt-badge-inline.epub { background: var(--accent-dim); color: var(--accent); }
	.fmt-badge-inline.pdf { background: var(--error-dim); color: var(--error); }
	.fmt-badge-inline.other { background: var(--card-hover); color: var(--text-3); }

	/* Modal */
	.modal-overlay { position: fixed; inset: 0; background: var(--overlay); z-index: 70; display: flex; align-items: center; justify-content: center; animation: fadeIn 150ms ease; }
	@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
	.modal-sheet { width: 480px; max-width: 92vw; background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow-xl); animation: slideUp 200ms ease; }
	@keyframes slideUp { from { transform: translateY(12px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
	.modal-header { display: flex; align-items: center; justify-content: space-between; padding: var(--sp-4) var(--sp-5); border-bottom: 1px solid var(--border); }
	.modal-title { font-size: var(--text-md); font-weight: 600; color: var(--text-1); }
	.modal-close { background: none; border: none; cursor: pointer; color: var(--text-3); padding: var(--sp-1); border-radius: var(--radius-sm); }
	.modal-close:hover { color: var(--text-1); background: var(--card-hover); }
	.modal-close svg { width: 18px; height: 18px; }
	.modal-body { padding: var(--sp-5); }

	.detail-top { display: flex; gap: var(--sp-4); }
	.detail-cover { width: 100px; height: 150px; border-radius: var(--radius-md); object-fit: cover; flex-shrink: 0; }
	.detail-cover-placeholder { width: 100px; height: 150px; border-radius: var(--radius-md); background: var(--surface-secondary); display: flex; align-items: center; justify-content: center; font-size: var(--text-3xl); font-weight: 300; color: var(--text-4); flex-shrink: 0; }
	.detail-info { flex: 1; min-width: 0; }
	.detail-title { font-size: var(--text-lg); font-weight: 600; color: var(--text-1); line-height: 1.3; }
	.detail-author { font-size: var(--text-sm); color: var(--text-3); margin-top: var(--sp-1); }
	.detail-meta { display: flex; gap: var(--sp-3); margin-top: var(--sp-2); font-size: var(--text-xs); color: var(--text-4); }
	.detail-badges { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin-top: var(--sp-3); }
	.detail-lib { font-size: var(--text-xs); font-weight: 500; padding: 2px var(--sp-2); border-radius: var(--radius-full); background: var(--accent-dim); color: var(--accent); }
	.detail-cat { font-size: var(--text-xs); padding: 2px var(--sp-2); border-radius: var(--radius-full); background: var(--card-hover); color: var(--text-3); }

	.kindle-section { margin-top: var(--sp-5); padding-top: var(--sp-4); border-top: 1px solid var(--border); }
	.kindle-label { font-size: var(--text-sm); font-weight: 600; color: var(--text-3); margin-bottom: var(--sp-3); text-transform: uppercase; letter-spacing: 0.04em; }
	.kindle-actions { display: flex; gap: var(--sp-2); }
	.kindle-btn { display: flex; align-items: center; gap: var(--sp-1.5); padding: var(--sp-2) var(--sp-4); border-radius: var(--radius-md); background: var(--accent); color: white; border: none; font-size: var(--text-sm); font-weight: 600; cursor: pointer; font-family: var(--font); transition: opacity var(--transition); }
	.kindle-btn:disabled { opacity: 0.5; cursor: default; }
	.kindle-btn:hover:not(:disabled) { opacity: 0.9; }
	.kindle-btn svg { width: 14px; height: 14px; }
	.kindle-result { font-size: var(--text-sm); margin-top: var(--sp-3); color: var(--success); font-weight: 500; }
	.kindle-result.error { color: var(--error); }

	@media (max-width: 1024px) { .book-grid { grid-template-columns: repeat(3, 1fr); } }
	@media (max-width: 768px) {
		.book-grid { grid-template-columns: repeat(2, 1fr); }
		.detail-top { flex-direction: column; align-items: center; text-align: center; }
		.detail-info { text-align: center; }
		.detail-badges { justify-content: center; }
		.kindle-actions { flex-direction: column; }
	}
</style>
