let bookData = null; let extensionName = null; let bookId = null; let bookSlug = null; let allChapters = []; let filteredChapters = []; let availableExtensions = []; let isLocal = false; const chapterPagination = Object.create(PaginationManager); chapterPagination.init(12, () => renderChapterTable()); document.addEventListener('DOMContentLoaded', () => { init(); setupModalClickOutside(); }); async function checkLocalLibraryEntry() { try { const res = await fetch(`/api/library/manga/${bookId}`); if (!res.ok) return; const data = await res.json(); if (data.matched) { isLocal = true; const pill = document.getElementById('local-pill'); if (pill) { pill.textContent = 'Local'; pill.style.display = 'inline-flex'; pill.style.background = 'rgba(34, 197, 94, 0.2)'; pill.style.color = '#22c55e'; pill.style.borderColor = 'rgba(34, 197, 94, 0.3)'; } } } catch (e) { console.error("Error checking local status:", e); } } function markAsLocal() { isLocal = true; const pill = document.getElementById('local-pill'); if (pill) { pill.textContent = 'Local'; pill.style.display = 'inline-flex'; pill.style.background = 'rgba(34, 197, 94, 0.2)'; pill.style.color = '#22c55e'; pill.style.borderColor = 'rgba(34, 197, 94, 0.3)'; } } async function init() { try { const urlData = URLUtils.parseEntityPath('book'); if (!urlData) { showError("Book Not Found"); return; } extensionName = urlData.extensionName; bookId = urlData.entityId; bookSlug = urlData.slug; await checkLocalLibraryEntry(); await loadBookMetadata(); await loadAvailableExtensions(); await loadChapters(); await setupAddToListButton(); } catch (err) { console.error("Metadata Error:", err); showError("Error loading book"); } } async function loadAvailableExtensions() { try { const res = await fetch('/api/extensions/book'); const data = await res.json(); availableExtensions = data.extensions || []; setupProviderFilter(); } catch (err) { console.error("Error fetching extensions:", err); } } async function loadBookMetadata() { const source = extensionName || 'anilist'; const fetchUrl = `/api/book/${bookId}?source=${source}`; const res = await fetch(fetchUrl); const data = await res.json(); if (data.error || !data) { showError("Book Not Found"); return; } const raw = Array.isArray(data) ? data[0] : data; bookData = raw; const metadata = MediaMetadataUtils.formatBookData(raw, !!extensionName); bookData.entry_type = metadata.format === 'MANGA' ? 'MANGA' : 'NOVEL'; updatePageTitle(metadata.title); updateMetadata(metadata); updateExtensionPill(); } function updatePageTitle(title) { document.title = `${title} | WaifuBoard Books`; const titleEl = document.getElementById('title'); if (titleEl) titleEl.innerText = title; } function updateMetadata(metadata) { const descEl = document.getElementById('description'); if (descEl) descEl.innerHTML = metadata.description; const scoreEl = document.getElementById('score'); if (scoreEl) { scoreEl.innerText = extensionName ? `${metadata.score}` : `${metadata.score}% Score`; } const pubEl = document.getElementById('published-date'); if (pubEl) pubEl.innerText = metadata.year; const statusEl = document.getElementById('status'); if (statusEl) statusEl.innerText = metadata.status; const formatEl = document.getElementById('format'); if (formatEl) formatEl.innerText = metadata.format; const chaptersEl = document.getElementById('chapters'); if (chaptersEl) chaptersEl.innerText = metadata.chapters; const genresEl = document.getElementById('genres'); if (genresEl) genresEl.innerText = metadata.genres; const posterEl = document.getElementById('poster'); if (posterEl) posterEl.src = metadata.poster; const heroBgEl = document.getElementById('hero-bg'); if (heroBgEl) heroBgEl.src = metadata.banner; } function updateExtensionPill() { const pill = document.getElementById('extension-pill'); if (!pill) return; if (extensionName) { pill.textContent = extensionName.charAt(0).toUpperCase() + extensionName.slice(1).toLowerCase(); pill.style.display = 'inline-flex'; } else { pill.style.display = 'none'; } } async function setupAddToListButton() { const btn = document.getElementById('add-to-list-btn'); if (!btn || !bookData) return; ListModalManager.currentData = bookData; const entryType = ListModalManager.getEntryType(bookData); const idForCheck = extensionName ? bookSlug : bookId; await ListModalManager.checkIfInList( idForCheck, extensionName || 'anilist', entryType ); updateCustomAddButton(); btn.onclick = () => ListModalManager.open(bookData, extensionName || 'anilist'); } function updateCustomAddButton() { const btn = document.getElementById('add-to-list-btn'); if (!btn) return; if (ListModalManager.isInList) { btn.innerHTML = ` In Your Library `; btn.style.background = 'rgba(34, 197, 94, 0.2)'; btn.style.color = '#22c55e'; btn.style.borderColor = 'rgba(34, 197, 94, 0.3)'; } else { btn.innerHTML = '+ Add to Library'; btn.style.background = null; btn.style.color = null; btn.style.borderColor = null; } } async function loadChapters(targetProvider = null) { const tbody = document.getElementById('chapters-body'); if (!tbody) return; if (!targetProvider) { const select = document.getElementById('provider-filter'); targetProvider = select ? select.value : (availableExtensions[0] || 'all'); } tbody.innerHTML = '