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

	interface Release {
		title: string; content_type: string; format: string; size: string;
		source: string; source_id: string; info_url: string; language: string;
		extra: { author?: string; preview?: string; publisher?: string; year?: string };
	}
	interface Download {
		id: string; title: string; author: string; format: string; source: string;
		status: string; status_message: string; progress: number; download_path: string;
		content_type: string; added_time: string;
	}
	interface Library { id: number; name: string; paths: { id: number; path: string }[]; }

	let query = $state('');
	let results = $state<Release[]>([]);
	let bookMeta = $state<{ title: string; authors: string[]; cover_url: string | null } | null>(null);
	let searching = $state(false);
	let searched = $state(false);
	let downloads = $state<Record<string, Download>>({});
	let libraries = $state<Library[]>([]);
	let defaultLibraryId = $state<number | null>(null);
	let downloadingIds = $state<Set<string>>(new Set());
	let importingIds = $state<Set<string>>(new Set());
	let importedIds = $state<Set<string>>(new Set());
	let perBookLibrary = $state<Record<string, number>>({});
	let prevCompleted = $state<Set<string>>(new Set());
	let activeView = $state<'search' | 'downloads'>('search');
	let poll: ReturnType<typeof setInterval> | null = null;

	// Kindle auto-send
	interface KindleTarget { id: string; label: string; email: string; }
	let kindleTargets = $state<KindleTarget[]>([]);
	let kindleConfigured = $state(false);
	let autoKindleTarget = $state<string>('none');
	let kindleSending = $state<Set<string>>(new Set());
	let kindleSent = $state<Set<string>>(new Set());

	const downloadCount = $derived(Object.keys(downloads).length);
	const activeDownloads = $derived(
		Object.values(downloads).filter(d => ['queued', 'downloading', 'locating', 'resolving'].includes(d.status))
	);

	async function search() {
		if (!query.trim()) return;
		searching = true; searched = true; results = []; bookMeta = null;
		try {
			const res = await fetch(`/api/books/releases?source=direct_download&query=${encodeURIComponent(query.trim())}&limit=40`, { credentials: 'include' });
			if (res.ok) { const data = await res.json(); results = data.releases || []; bookMeta = data.book || null; }
		} catch { /* silent */ }
		searching = false;
	}

	async function download(release: Release) {
		downloadingIds = new Set([...downloadingIds, release.source_id]);
		try {
			const res = await fetch('/api/books/releases/download', {
				method: 'POST', credentials: 'include',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ source: release.source, source_id: release.source_id, title: release.title, format: release.format, size: release.size, extra: release.extra })
			});
			if (res.ok) fetchStatus();
		} catch { /* silent */ }
	}

	async function cancelDownload(id: string) {
		try { await fetch(`/api/books/download/${id}/cancel`, { method: 'DELETE', credentials: 'include' }); fetchStatus(); } catch { /* silent */ }
	}

	async function retryDownload(id: string) {
		try { await fetch(`/api/books/download/${id}/retry`, { method: 'POST', credentials: 'include' }); fetchStatus(); } catch { /* silent */ }
	}

	function getLibraryId(key: string): number | null {
		return perBookLibrary[key] ?? defaultLibraryId;
	}

	async function importToBooklore(dl: Download, libraryId?: number | null) {
		const libId = libraryId ?? defaultLibraryId;
		if (!libId || importingIds.has(dl.id) || importedIds.has(dl.id)) return;
		const lib = libraries.find(l => l.id === libId);
		if (!lib || lib.paths.length === 0) return;
		importingIds = new Set([...importingIds, dl.id]);
		const fileName = dl.download_path?.split('/').pop() || dl.title;
		try {
			const res = await fetch('/api/booklore/import', {
				method: 'POST', credentials: 'include',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ fileName, libraryId: lib.id, pathId: lib.paths[0].id })
			});
			if (res.ok) {
				importedIds = new Set([...importedIds, dl.id]);
				// Auto-send to Kindle if configured
				if (autoKindleTarget !== 'none' && fileName && !kindleSent.has(dl.id)) {
					sendFileToKindle(dl.id, fileName, dl.title || fileName, autoKindleTarget);
				}
			}
		} catch { /* silent */ }
		const next = new Set(importingIds); next.delete(dl.id); importingIds = next;
	}

	async function sendFileToKindle(dlId: string, filename: string, title: string, target: string) {
		if (kindleSending.has(dlId) || kindleSent.has(dlId)) return;
		kindleSending = new Set([...kindleSending, dlId]);
		try {
			const res = await fetch('/api/kindle/send-file', {
				method: 'POST', credentials: 'include',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({ filename, title, target }),
			});
			if (res.ok) { kindleSent = new Set([...kindleSent, dlId]); }
		} catch { /* silent */ }
		const next = new Set(kindleSending); next.delete(dlId); kindleSending = next;
	}

	async function fetchStatus() {
		try {
			const res = await fetch('/api/books/status', { credentials: 'include' });
			if (res.ok) {
				const data = await res.json();
				const all: Record<string, Download> = {};
				for (const [groupName, group] of Object.entries(data) as [string, Record<string, Download>][]) {
					if (group && typeof group === 'object') {
						for (const [id, dl] of Object.entries(group)) {
							if (['complete', 'error', 'cancelled'].includes(groupName)) dl.status = groupName;
							else if (groupName === 'active') dl.status = dl.status_message?.toLowerCase().includes('download') ? 'downloading' : (dl.status || 'downloading');
							all[id] = dl;
						}
					}
				}
				if (defaultLibraryId) {
					for (const [id, dl] of Object.entries(all)) {
						if (dl.status === 'complete' && !prevCompleted.has(id) && !importingIds.has(id) && !importedIds.has(id)) {
							importToBooklore(dl, getLibraryId(id));
						}
					}
				}
				prevCompleted = new Set(Object.entries(all).filter(([_, d]) => d.status === 'complete').map(([id]) => id));
				downloads = all;
			}
		} catch { /* silent */ }
	}

	async function fetchLibraries() {
		try {
			const res = await fetch('/api/booklore/libraries', { credentials: 'include' });
			if (res.ok) {
				const data = await res.json();
				libraries = data.libraries || [];
				if (libraries.length > 0 && defaultLibraryId === null) defaultLibraryId = libraries[0].id;
			}
		} catch { /* silent */ }
	}

	function coverUrl(release: Release): string | null {
		const preview = release.extra?.preview;
		if (!preview) return null;
		if (preview.startsWith('/api/')) {
			return `/api/books${preview.slice(4)}`;
		}
		return preview;
	}

	function fmtBadge(fmt: string): string {
		const f = fmt?.toLowerCase();
		if (f === 'epub') return 'accent'; if (f === 'pdf') return 'error'; if (f === 'mobi' || f === 'azw3') return 'warning'; return 'muted';
	}

	function statusClass(s: string): string {
		if (s === 'complete') return 'success'; if (s === 'downloading' || s === 'locating' || s === 'resolving' || s === 'queued') return 'accent'; if (s === 'error') return 'error'; return 'muted';
	}

	onMount(async () => {
		await fetchLibraries();
		// 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 */ }
		const res = await fetch('/api/books/status', { credentials: 'include' }).catch(() => null);
		if (res?.ok) {
			const data = await res.json();
			const ids: string[] = [];
			for (const group of Object.values(data) as Record<string, Download>[]) {
				if (group && typeof group === 'object') { for (const [id, dl] of Object.entries(group)) { if (dl.status === 'complete') ids.push(id); } }
			}
			prevCompleted = new Set(ids);
		}
		fetchStatus();
		poll = setInterval(fetchStatus, 3000);
	});

	onDestroy(() => { if (poll) clearInterval(poll); });
</script>

<!-- Sub-tabs -->
<div class="sub-tabs">
	<button class="sub-tab" class:active={activeView === 'search'} onclick={() => activeView = 'search'}>Search</button>
	<button class="sub-tab" class:active={activeView === 'downloads'} onclick={() => activeView = 'downloads'}>
		Downloads
		{#if activeDownloads.length > 0}<span class="sub-badge">{activeDownloads.length}</span>{/if}
	</button>
</div>

{#if kindleConfigured && kindleTargets.length > 0}
	<div class="kindle-auto-row">
		<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>
		<span class="kindle-auto-label">After download, also send to</span>
		<select class="kindle-auto-select" bind:value={autoKindleTarget}>
			<option value="none">No one (just download)</option>
			{#each kindleTargets as t}
				<option value={t.id}>{t.label}</option>
			{/each}
		</select>
	</div>
{/if}

{#if activeView === 'search'}
	<!-- Search -->
	<div class="search-bar">
		<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 books, authors, ISBNs..." bind:value={query} onkeydown={(e) => { if (e.key === 'Enter') search(); }} />
			{#if query}
				<button class="s-clear" onclick={() => { query = ''; results = []; searched = false; bookMeta = null; }}>
					<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>
			{/if}
		</div>
		<button class="s-btn" onclick={search} disabled={searching || !query.trim()}>
			{#if searching}<span class="spinner"></span>{:else}Search{/if}
		</button>
	</div>

	{#if searching}
		<div class="empty">Searching Anna's Archive, Libgen, Z-Library...</div>
	{:else if searched && results.length === 0}
		<div class="empty">No results found for "{query}"</div>
	{:else if results.length > 0}
		{#if bookMeta}<div class="result-count">{results.length} releases found</div>{/if}
		<div class="results-grid">
			{#each results as release (release.source_id)}
				{@const cover = coverUrl(release)}
				{@const isDl = downloadingIds.has(release.source_id) || !!downloads[release.source_id]}
				<div class="r-card">
					<div class="r-cover">
						{#if cover}
							<img src={cover} alt="" loading="lazy" onerror={(e) => (e.currentTarget as HTMLImageElement).style.display='none'} />
						{/if}
						<span class="fmt-badge {fmtBadge(release.format)}">{release.format.toUpperCase()}</span>
					</div>
					<div class="r-info">
						<div class="r-title">{release.title}</div>
						{#if release.extra?.author}<div class="r-author">{release.extra.author}</div>{/if}
						<div class="r-meta">
							{#if release.extra?.year}<span>{release.extra.year}</span>{/if}
							{#if release.size}<span>{release.size}</span>{/if}
							{#if release.language}<span>{release.language.toUpperCase()}</span>{/if}
						</div>
					</div>
					<div class="r-actions">
						{#if libraries.length > 0}
							<select class="lib-select" value={perBookLibrary[release.source_id] ?? defaultLibraryId} onchange={(e) => { perBookLibrary[release.source_id] = Number((e.currentTarget as HTMLSelectElement).value); perBookLibrary = {...perBookLibrary}; }}>
								{#each libraries as lib}<option value={lib.id}>{lib.name}</option>{/each}
							</select>
						{/if}
						{#if isDl}
							{@const dl = downloads[release.source_id]}
							{#if dl}
								<span class="dl-badge {statusClass(dl.status)}">{dl.status}</span>
								{#if dl.progress > 0 && dl.progress < 100}
									<div class="dl-bar"><div class="dl-fill" style="width:{dl.progress}%"></div></div>
								{/if}
							{:else}
								<span class="dl-badge muted">Queued...</span>
							{/if}
						{:else}
							<button class="dl-btn" onclick={() => download(release)}>
								<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
								Download
							</button>
						{/if}
					</div>
				</div>
			{/each}
		</div>
	{:else}
		<div class="empty">
			<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" style="width:64px;height:64px;opacity:0.2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
			<div>Search for books</div>
			<div class="empty-sub">Anna's Archive, Libgen, Z-Library</div>
		</div>
	{/if}
{:else}
	<!-- Downloads -->
	{#if downloadCount === 0}
		<div class="empty">No downloads yet</div>
	{:else}
		<div class="dl-list">
			{#each Object.entries(downloads) as [id, dl] (id)}
				<div class="dl-row">
					<div class="dl-info">
						<div class="dl-title">{dl.title || id}</div>
						{#if dl.author}<div class="dl-author">{dl.author}</div>{/if}
						<div class="dl-meta-row">
							{#if dl.format}<span class="fmt-badge sm {fmtBadge(dl.format)}">{dl.format.toUpperCase()}</span>{/if}
							<span class="dl-badge {statusClass(dl.status)}">{dl.status}</span>
							{#if dl.status_message}<span class="dl-msg">{dl.status_message}</span>{/if}
						</div>
						{#if dl.status === 'downloading' && dl.progress > 0}
							<div class="dl-bar full"><div class="dl-fill" style="width:{dl.progress}%"></div></div>
						{/if}
					</div>
					<div class="dl-actions">
						{#if dl.status === 'complete'}
							{#if kindleSent.has(id)}
								<span class="dl-badge success">Sent to Kindle ✓</span>
							{:else if kindleSending.has(id)}
								<span class="dl-badge accent">Sending to Kindle...</span>
							{/if}
							{#if importedIds.has(id)}
								<span class="dl-badge success">Imported ✓</span>
							{:else if importingIds.has(id)}
								<span class="dl-badge accent">Importing...</span>
							{:else}
								{#if libraries.length > 0}
									<select class="lib-select" value={perBookLibrary[id] ?? defaultLibraryId} onchange={(e) => { perBookLibrary[id] = Number((e.currentTarget as HTMLSelectElement).value); perBookLibrary = {...perBookLibrary}; }}>
										{#each libraries as lib}<option value={lib.id}>{lib.name}</option>{/each}
									</select>
								{/if}
								<button class="action-btn" onclick={() => importToBooklore(dl, getLibraryId(id))}>Import</button>
							{/if}
						{:else if dl.status === 'error'}
							<button class="action-btn" onclick={() => retryDownload(id)}>Retry</button>
							<button class="action-btn danger" onclick={() => cancelDownload(id)}>Remove</button>
						{:else if ['queued', 'downloading', 'locating', 'resolving'].includes(dl.status)}
							<button class="action-btn danger" onclick={() => cancelDownload(id)}>Cancel</button>
						{:else}
							<button class="action-btn danger" onclick={() => cancelDownload(id)}>Remove</button>
						{/if}
					</div>
				</div>
			{/each}
		</div>
	{/if}
{/if}

<style>
	.sub-tabs { display: flex; gap: var(--sp-1); margin-bottom: var(--sp-4); }
	.sub-tab { 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); display: flex; align-items: center; gap: var(--sp-1.5); }
	.sub-tab:hover { color: var(--text-1); background: var(--card-hover); }
	.sub-tab.active { color: var(--text-1); background: var(--card); box-shadow: var(--shadow-xs); }
	.sub-badge { font-size: var(--text-xs); font-family: var(--mono); background: var(--accent); color: white; padding: 1px 6px; border-radius: var(--radius-xs); }

	.search-bar { display: flex; gap: var(--sp-2); margin-bottom: var(--sp-5); align-items: stretch; }
	.search-wrap { flex: 1; position: relative; }
	.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%; height: 42px; padding: 0 36px 0 40px; border-radius: var(--radius-md); border: 1px solid var(--border); background: var(--card); color: var(--text-1); font-size: var(--text-base); font-family: var(--font); transition: all var(--transition); box-sizing: border-box; }
	.s-input:focus { outline: none; border-color: var(--accent); }
	.s-input::placeholder { color: var(--text-4); }
	.s-clear { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; color: var(--text-4); padding: var(--sp-1); }
	.s-clear svg { width: 14px; height: 14px; }
	.s-btn { height: 42px; padding: 0 var(--sp-5); 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); white-space: nowrap; }
	.s-btn:disabled { opacity: 0.4; cursor: default; }
	.s-btn:hover:not(:disabled) { opacity: 0.9; }
	.spinner { width: 16px; height: 16px; border: 2px solid rgba(255,255,255,0.3); border-top-color: white; border-radius: 50%; animation: spin 0.6s linear infinite; display: inline-block; }
	@keyframes spin { to { transform: rotate(360deg); } }

	.empty { padding: var(--sp-12); text-align: center; color: var(--text-3); font-size: var(--text-base); display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); }
	.empty-sub { font-size: var(--text-sm); color: var(--text-4); }
	.result-count { font-size: var(--text-sm); color: var(--text-3); margin-bottom: var(--sp-3); }

	.results-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--sp-4); }
	.r-card { background: var(--card); border-radius: var(--radius); border: 1px solid var(--border); box-shadow: var(--shadow-sm); overflow: hidden; display: flex; flex-direction: column; }
	.r-cover { position: relative; width: 100%; aspect-ratio: 3/2; background: var(--surface-secondary); display: flex; align-items: center; justify-content: center; overflow: hidden; }
	.r-cover img { width: 100%; height: 100%; object-fit: cover; }
	.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.accent { background: var(--accent-dim); color: var(--accent); }
	.fmt-badge.error { background: var(--error-dim); color: var(--error); }
	.fmt-badge.warning { background: var(--warning-bg); color: var(--warning); }
	.fmt-badge.muted { background: var(--card-hover); color: var(--text-4); }
	.fmt-badge.sm { position: static; }
	.r-info { padding: var(--sp-3) var(--sp-4); flex: 1; }
	.r-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; }
	.r-author { font-size: var(--text-sm); color: var(--text-3); margin-top: 2px; }
	.r-meta { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-1); font-size: var(--text-xs); color: var(--text-4); }
	.r-actions { padding: var(--sp-2) var(--sp-4) var(--sp-3); display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
	.lib-select { padding: var(--sp-1) var(--sp-2); border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--card); color: var(--text-2); font-size: var(--text-xs); font-family: var(--font); cursor: pointer; max-width: 120px; }
	.dl-btn { display: flex; align-items: center; gap: var(--sp-1); padding: var(--sp-1.5) var(--sp-3); 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); }
	.dl-btn:hover { opacity: 0.9; }
	.dl-btn svg { width: 14px; height: 14px; }
	.dl-badge { font-size: var(--text-xs); font-weight: 600; padding: 2px var(--sp-2); border-radius: var(--radius-xs); text-transform: uppercase; }
	.dl-badge.success { background: var(--success-dim); color: var(--success); }
	.dl-badge.accent { background: var(--accent-dim); color: var(--accent); }
	.dl-badge.error { background: var(--error-dim); color: var(--error); }
	.dl-badge.muted { background: var(--card-hover); color: var(--text-4); }
	.dl-bar { width: 80px; height: 4px; background: var(--border); border-radius: 2px; overflow: hidden; }
	.dl-bar.full { width: 100%; margin-top: var(--sp-2); }
	.dl-fill { height: 100%; background: var(--accent); border-radius: 2px; transition: width 0.3s ease; }

	.dl-list { background: var(--card); border-radius: var(--radius); border: 1px solid var(--border); box-shadow: var(--shadow-sm); overflow: hidden; }
	.dl-row { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4); padding: var(--sp-4); border-bottom: 1px solid var(--border); }
	.dl-row:last-child { border-bottom: none; }
	.dl-info { flex: 1; min-width: 0; }
	.dl-title { font-size: var(--text-base); font-weight: 500; color: var(--text-1); }
	.dl-author { font-size: var(--text-sm); color: var(--text-3); margin-top: 2px; }
	.dl-meta-row { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2); flex-wrap: wrap; }
	.dl-msg { font-size: var(--text-xs); color: var(--text-4); }
	.dl-actions { display: flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; flex-wrap: wrap; }
	.action-btn { padding: var(--sp-1.5) var(--sp-3); border-radius: var(--radius-md); background: var(--accent); color: white; border: none; font-size: var(--text-sm); font-weight: 500; cursor: pointer; font-family: var(--font); }
	.action-btn.danger { background: none; border: 1px solid var(--error); color: var(--error); }
	.action-btn.danger:hover { background: var(--error-dim); }

	.kindle-auto-row {
		display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-4);
		padding: var(--sp-2) var(--sp-3); background: var(--surface-secondary); border-radius: var(--radius-md); border: 1px solid var(--border);
		flex-wrap: wrap; max-width: 100%; overflow: hidden;
	}
	.kindle-auto-row svg { width: 14px; height: 14px; color: var(--text-3); flex-shrink: 0; }
	.kindle-auto-label { font-size: var(--text-sm); color: var(--text-2); white-space: nowrap; flex-shrink: 1; min-width: 0; }
	.kindle-auto-select {
		height: 32px; padding: 0 var(--sp-3); border-radius: var(--radius-md); border: 1px solid var(--border);
		background: var(--card); color: var(--text-1); font-size: var(--text-sm); font-weight: 500; font-family: var(--font);
		cursor: pointer; -webkit-appearance: none; appearance: none;
		background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236b6b76' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
		background-repeat: no-repeat; background-position: right 8px center; padding-right: 24px;
	}

	@media (max-width: 768px) {
		.results-grid { grid-template-columns: 1fr; }
		.dl-row { flex-direction: column; }
		.dl-actions { width: 100%; }
	}
</style>
