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

	let {
		url,
		name = 'Document',
		onDelete = () => {},
		deleting = false
	}: {
		url: string;
		name?: string;
		onDelete?: () => void;
		deleting?: boolean;
	} = $props();

	let inlinePagesHost = $state<HTMLDivElement | null>(null);
	let pagesHost = $state<HTMLDivElement | null>(null);
	let loading = $state(true);
	let expandedLoading = $state(false);
	let error = $state('');
	let isExpanded = $state(false);
	let isInlineOpen = $state(false);
	let pageCount = $state(0);

	let pdfModulePromise: Promise<any> | null = null;
	let pdfDocumentPromise: Promise<any> | null = null;

	async function getPdfModule() {
		if (!pdfModulePromise) {
			pdfModulePromise = import('pdfjs-dist').then((mod) => {
				const pdfjs = mod.default ?? mod;
				if (!pdfjs.GlobalWorkerOptions.workerSrc) {
					pdfjs.GlobalWorkerOptions.workerSrc = new URL(
						'pdfjs-dist/build/pdf.worker.min.mjs',
						import.meta.url
					).toString();
				}
				return pdfjs;
			});
		}

		return pdfModulePromise;
	}

	async function getPdfDocument() {
		if (!pdfDocumentPromise) {
			pdfDocumentPromise = getPdfModule().then((pdfjs) =>
				pdfjs.getDocument({
					url,
					withCredentials: true
				}).promise
			);
		}

		return pdfDocumentPromise;
	}

	async function renderPageToCanvas(canvas: HTMLCanvasElement, pageNumber: number, width: number) {
		const pdf = await getPdfDocument();
		const page = await pdf.getPage(pageNumber);
		const baseViewport = page.getViewport({ scale: 1 });
		const scale = width / baseViewport.width;
		const viewport = page.getViewport({ scale });
		const context = canvas.getContext('2d');
		const pixelRatio = typeof window !== 'undefined' ? Math.max(window.devicePixelRatio || 1, 1) : 1;

		if (!context) return;

		canvas.width = Math.floor(viewport.width * pixelRatio);
		canvas.height = Math.floor(viewport.height * pixelRatio);
		canvas.style.width = `${viewport.width}px`;
		canvas.style.height = `${viewport.height}px`;
		context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);

		await page.render({
			canvasContext: context,
			viewport
		}).promise;
	}

	async function renderPages(host: HTMLDivElement, width: number, pageClass = 'expanded-page', canvasClass = 'expanded-canvas') {
		host.replaceChildren();

		const pdf = await getPdfDocument();
		pageCount = pdf.numPages;

		for (let pageNumber = 1; pageNumber <= pageCount; pageNumber += 1) {
			const wrapper = document.createElement('div');
			wrapper.className = pageClass;

			const label = document.createElement('div');
			label.className = 'expanded-page-label';
			label.textContent = `Page ${pageNumber}`;

			const canvas = document.createElement('canvas');
			canvas.className = canvasClass;

			wrapper.append(label, canvas);
			host.appendChild(wrapper);

			await renderPageToCanvas(canvas, pageNumber, width);
		}
	}

	async function renderInline() {
		if (!inlinePagesHost) return;

		loading = true;
		error = '';

		try {
			await renderPages(inlinePagesHost, 420, 'inline-page', 'inline-canvas');
		} catch (err) {
			console.error('PDF preview failed', err);
			error = 'Preview unavailable';
		} finally {
			loading = false;
		}
	}

	async function openInline() {
		isInlineOpen = true;
		await tick();
		await renderInline();
	}

	function closeInline() {
		isInlineOpen = false;
	}

	async function openExpanded() {
		isExpanded = true;
		expandedLoading = true;
		error = '';
		await tick();

		if (!pagesHost) {
			expandedLoading = false;
			return;
		}

		try {
			const hostWidth = Math.max(280, Math.min(860, pagesHost.clientWidth - 8 || 860));
			await renderPages(pagesHost, hostWidth);
		} catch (err) {
			console.error('Expanded PDF render failed', err);
			error = 'Unable to load PDF';
		} finally {
			expandedLoading = false;
		}
	}

	function closeExpanded() {
		isExpanded = false;
	}

	onMount(() => {
		renderInline();
	});
</script>

<div class="pdf-preview-shell">
	<div class="preview-frame">
		<!-- svelte-ignore a11y_no_static_element_interactions -->
		<div
			class="preview-head"
			role="button"
			tabindex="0"
			onclick={isInlineOpen ? closeInline : openInline}
			onkeydown={(e) => {
				if (e.key === 'Enter' || e.key === ' ') {
					e.preventDefault();
					if (isInlineOpen) closeInline();
					else openInline();
				}
			}}
		>
			<div class="preview-docline">
				<svg class="preview-docicon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>
				<div class="preview-name">{name}</div>
			</div>
			<div class="preview-head-actions">
				<button class="doc-delete" onclick={(e) => { e.stopPropagation(); onDelete(); }} disabled={deleting}>{deleting ? '…' : '×'}</button>
			</div>
		</div>

		{#if isInlineOpen}
			<div class="preview-topline">
				<div class="preview-badge">PDF preview</div>
				<div class="preview-actions">
					<button class="preview-action" onclick={openExpanded}>Full view</button>
					<a class="preview-action preview-link" href={url} target="_blank" rel="noreferrer">New tab</a>
				</div>
			</div>

			<div class="preview-card">
				{#if error}
					<div class="preview-state preview-error">{error}</div>
				{:else}
					<div class="preview-stage">
						<div bind:this={inlinePagesHost} class="inline-pages"></div>
						{#if loading}
							<div class="preview-loading">Rendering pages…</div>
						{/if}
					</div>
					<div class="preview-footer">
						<div class="preview-pages">{pageCount} page{pageCount === 1 ? '' : 's'}</div>
					</div>
				{/if}
			</div>
		{:else}
			<div class="preview-collapsed-meta">
				<div class="preview-pages">{pageCount > 0 ? `${pageCount} page${pageCount === 1 ? '' : 's'}` : 'PDF document'}</div>
				<a class="preview-inline-link" href={url} target="_blank" rel="noreferrer">New tab</a>
			</div>
		{/if}
	</div>
</div>

{#if isExpanded}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="expanded-overlay" onclick={closeExpanded}>
		<!-- svelte-ignore a11y_no_static_element_interactions -->
		<div class="expanded-sheet" onclick={(e: MouseEvent) => e.stopPropagation()}>
			<div class="expanded-head">
				<div class="expanded-copy">
					<div class="expanded-kicker">Inline document</div>
					<div class="expanded-title">{name}</div>
				</div>
				<div class="expanded-head-actions">
					<a class="preview-action preview-link" href={url} target="_blank" rel="noreferrer">Open</a>
					<button class="expanded-close" onclick={closeExpanded}>Close</button>
				</div>
			</div>

			<div class="expanded-body">
				{#if expandedLoading}
					<div class="expanded-state">Loading full document…</div>
				{:else if error}
					<div class="expanded-state preview-error">{error}</div>
				{/if}

				<div bind:this={pagesHost} class="expanded-pages"></div>
			</div>
		</div>
	</div>
{/if}

<style>
	.pdf-preview-shell {
		display: block;
	}

	.preview-frame {
		display: flex;
		flex-direction: column;
		gap: 10px;
		padding-top: 6px;
		border-top: 1px solid rgba(127, 101, 74, 0.12);
	}

	.preview-head {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 12px;
		padding: 0;
		border: none;
		background: none;
		cursor: pointer;
		text-align: left;
	}

	.preview-docline {
		display: flex;
		align-items: center;
		gap: 8px;
		min-width: 0;
	}

	.preview-docicon {
		width: 16px;
		height: 16px;
		flex-shrink: 0;
		color: rgba(111, 88, 64, 0.7);
	}

	.preview-head-actions {
		display: flex;
		align-items: center;
		gap: 8px;
	}

	.preview-topline {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 12px;
	}

	.preview-badge {
		font-size: 0.68rem;
		font-weight: 700;
		letter-spacing: 0.14em;
		text-transform: uppercase;
		color: rgba(122, 94, 66, 0.7);
	}

	.preview-actions {
		display: flex;
		align-items: center;
		gap: 8px;
	}

	.preview-action {
		padding: 7px 12px;
		border-radius: 999px;
		border: 1px solid rgba(123, 97, 71, 0.16);
		background: rgba(255, 251, 246, 0.9);
		color: #5d4737;
		font: inherit;
		font-size: 0.84rem;
		font-weight: 600;
		cursor: pointer;
		text-decoration: none;
	}

	.preview-card {
		display: flex;
		flex-direction: column;
		gap: 10px;
	}

	.preview-state {
		display: flex;
		align-items: center;
		justify-content: center;
		min-height: 240px;
		border-radius: 16px;
		background: rgba(247, 239, 229, 0.78);
		color: rgba(90, 71, 54, 0.8);
		font-size: 0.92rem;
	}

	.preview-stage {
		position: relative;
		border-radius: 16px;
		overflow: hidden;
		background: rgba(250, 243, 235, 0.72);
		border: 1px solid rgba(127, 101, 74, 0.14);
	}

	.preview-loading {
		position: absolute;
		inset: 0;
		display: flex;
		align-items: center;
		justify-content: center;
		background: rgba(247, 239, 229, 0.82);
		color: rgba(90, 71, 54, 0.8);
		font-size: 0.92rem;
	}

	.preview-error {
		color: #8c3c2d;
	}

	.inline-pages {
		display: flex;
		flex-direction: column;
		gap: 14px;
		max-height: 520px;
		overflow: auto;
		padding: 10px;
	}

	.preview-footer {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 10px;
	}

	.preview-name {
		font-size: 0.92rem;
		font-weight: 600;
		color: #2f2116;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.preview-pages {
		font-size: 0.82rem;
		color: rgba(93, 72, 55, 0.76);
	}

	.preview-collapsed-meta {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 10px;
	}

	.preview-inline-link {
		font-size: 0.82rem;
		font-weight: 600;
		color: #5d4737;
		text-decoration: none;
	}

	.doc-delete {
		background: none;
		border: none;
		color: rgba(112, 86, 62, 0.64);
		cursor: pointer;
		font-size: 1.1rem;
		padding: 2px 4px;
	}

	.doc-delete:hover {
		color: #8f3928;
	}

	.expanded-overlay {
		position: fixed;
		inset: 0;
		z-index: 85;
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 24px;
		background: rgba(19, 13, 10, 0.46);
		backdrop-filter: blur(10px);
	}

	.expanded-sheet {
		width: min(980px, 100%);
		max-height: min(92vh, 100%);
		display: flex;
		flex-direction: column;
		border-radius: 28px;
		overflow: hidden;
		background: linear-gradient(180deg, rgba(255, 250, 242, 0.98), rgba(247, 239, 229, 0.98));
		box-shadow: 0 28px 64px rgba(35, 24, 15, 0.28);
	}

	.expanded-head {
		display: flex;
		align-items: flex-start;
		justify-content: space-between;
		gap: 18px;
		padding: 22px 24px 18px;
		border-bottom: 1px solid rgba(123, 97, 71, 0.12);
	}

	.expanded-copy {
		display: flex;
		flex-direction: column;
		gap: 6px;
	}

	.expanded-kicker {
		font-size: 0.68rem;
		font-weight: 700;
		letter-spacing: 0.16em;
		text-transform: uppercase;
		color: rgba(122, 94, 66, 0.72);
	}

	.expanded-title {
		font-size: 1.4rem;
		font-weight: 600;
		letter-spacing: -0.03em;
		color: #27190f;
	}

	.expanded-head-actions {
		display: flex;
		align-items: center;
		gap: 8px;
	}

	.expanded-close {
		padding: 7px 12px;
		border-radius: 999px;
		border: 1px solid rgba(123, 97, 71, 0.16);
		background: rgba(255, 251, 246, 0.9);
		color: #5d4737;
		font: inherit;
		font-size: 0.84rem;
		font-weight: 600;
		cursor: pointer;
	}

	.expanded-body {
		flex: 1;
		overflow: auto;
		padding: 18px 24px 24px;
	}

	.expanded-state {
		padding: 24px;
		border-radius: 18px;
		background: rgba(247, 239, 229, 0.74);
		color: rgba(90, 71, 54, 0.8);
		text-align: center;
	}

	.expanded-pages {
		display: flex;
		flex-direction: column;
		gap: 20px;
	}

	:global(.inline-page) {
		display: flex;
		flex-direction: column;
		gap: 8px;
	}

	:global(.inline-canvas) {
		display: block;
		max-width: 100%;
		height: auto;
		border-radius: 14px;
		background: white;
		border: 1px solid rgba(111, 89, 65, 0.12);
		box-shadow: 0 10px 20px rgba(63, 42, 22, 0.05);
	}

	:global(.expanded-page) {
		display: flex;
		flex-direction: column;
		gap: 10px;
	}

	:global(.expanded-page-label) {
		font-size: 0.74rem;
		font-weight: 700;
		letter-spacing: 0.14em;
		text-transform: uppercase;
		color: rgba(122, 94, 66, 0.68);
	}

	:global(.expanded-canvas) {
		display: block;
		max-width: 100%;
		height: auto;
		border-radius: 18px;
		background: white;
		border: 1px solid rgba(111, 89, 65, 0.12);
		box-shadow: 0 14px 28px rgba(63, 42, 22, 0.06);
	}

	@media (max-width: 768px) {
		.preview-topline {
			align-items: flex-start;
			flex-direction: column;
		}

		.preview-actions {
			width: 100%;
		}

		.preview-action {
			flex: 1;
			text-align: center;
		}

		.expanded-overlay {
			padding: 10px;
		}

		.expanded-sheet {
			max-height: 96vh;
			border-radius: 22px;
		}

		.expanded-head,
		.expanded-body {
			padding-left: 16px;
			padding-right: 16px;
		}

		.expanded-head {
			flex-direction: column;
		}
	}
</style>
