<script lang="ts">
import { m } from '$lib/paraglide/messages.js';
import { formatDate } from '$lib/utils/date';
import { diffWords } from 'diff';
import ExpandableText from '$lib/components/ExpandableText.svelte';
import PdfViewer from '$lib/components/PdfViewer.svelte';

let { data } = $props();

const doc = $derived(data.document);

let fileUrl = $state('');
let isLoading = $state(false);
let error = $state('');

$effect(() => {
	if (doc?.id && doc?.filePath) {
		loadFile(doc.id);
	}
});

async function loadFile(id: string) {
	isLoading = true;
	error = '';
	fileUrl = '';

	try {
		const response = await fetch(`/api/documents/${id}/file`);

		if (!response.ok) {
			if (response.status === 401) throw new Error('Nicht eingeloggt');
			throw new Error('Fehler beim Laden der Datei');
		}

		const blob = await response.blob();
		fileUrl = URL.createObjectURL(blob);
	} catch (e) {
		console.error(e);
		error = m.doc_file_error_preview();
	} finally {
		isLoading = false;
	}
}

// ── History panel ────────────────────────────────────────────────────────────

type VersionSummary = {
	id: string;
	savedAt: string;
	editorName: string;
	changedFields: string[];
};

type SnapshotDoc = {
	title?: string;
	documentDate?: string;
	location?: string;
	documentLocation?: string;
	transcription?: string;
	summary?: string;
	sender?: { id: string; firstName: string; lastName: string } | null;
	receivers?: { id: string; firstName: string; lastName: string }[];
	tags?: { id: string; name: string }[];
};

type DiffEntry =
	| {
			kind: 'text';
			field: string;
			label: string;
			parts: { value: string; added?: boolean; removed?: boolean }[];
	  }
	| { kind: 'scalar'; field: string; label: string; oldVal: string; newVal: string }
	| { kind: 'relation'; field: string; label: string; removed: string[]; added: string[] };

let historyOpen = $state(false);
let historyLoaded = $state(false);
let historyLoading = $state(false);
let versions = $state<VersionSummary[]>([]);

let compareMode = $state(false);
let compareA = $state('');
let compareB = $state('');

let selectedVersionId = $state<string | null>(null);
let diffEntries = $state<DiffEntry[]>([]);
let diffLoading = $state(false);
let noDiff = $state(false);

const fieldLabels: Record<string, () => string> = {
	title: m.history_field_title,
	documentDate: m.history_field_document_date,
	location: m.history_field_location,
	documentLocation: m.history_field_document_location,
	transcription: m.history_field_transcription,
	summary: m.history_field_summary,
	sender: m.history_field_sender,
	receivers: m.history_field_receivers,
	tags: m.history_field_tags
};

const TEXT_FIELDS = ['title', 'summary', 'transcription'] as const;
const SCALAR_FIELDS = ['documentDate', 'location', 'documentLocation'] as const;

function parseSnapshot(raw: string): SnapshotDoc {
	try {
		return JSON.parse(raw) as SnapshotDoc;
	} catch {
		return {};
	}
}

function personLabel(p: { firstName: string; lastName: string }): string {
	return `${p.firstName} ${p.lastName}`.trim();
}

const DIFF_CONTEXT_WORDS = 4;

type DiffPart = { value: string; added?: boolean; removed?: boolean };

function trimContextParts(parts: DiffPart[]): DiffPart[] {
	return parts.flatMap((part, i) => {
		if (part.added || part.removed) return [part];
		const tokens = part.value.split(/(\s+)/).filter(Boolean);
		const wordCount = tokens.filter((t) => /\S/.test(t)).length;
		if (wordCount <= DIFF_CONTEXT_WORDS * 2) return [part];

		function keepFirst(n: number): string {
			let count = 0;
			const out: string[] = [];
			for (const t of tokens) {
				out.push(t);
				if (/\S/.test(t) && ++count >= n) break;
			}
			return out.join('');
		}
		function keepLast(n: number): string {
			let count = 0;
			const out: string[] = [];
			for (const t of [...tokens].reverse()) {
				out.unshift(t);
				if (/\S/.test(t) && ++count >= n) break;
			}
			return out.join('');
		}

		const isFirst = i === 0;
		const isLast = i === parts.length - 1;
		if (isFirst) return [{ value: '… ' + keepLast(DIFF_CONTEXT_WORDS) }];
		if (isLast) return [{ value: keepFirst(DIFF_CONTEXT_WORDS) + ' …' }];
		return [{ value: keepFirst(DIFF_CONTEXT_WORDS) + ' … ' + keepLast(DIFF_CONTEXT_WORDS) }];
	});
}

function buildDiff(older: SnapshotDoc | null, newer: SnapshotDoc): DiffEntry[] {
	const entries: DiffEntry[] = [];

	for (const field of TEXT_FIELDS) {
		const a = older?.[field] ?? '';
		const b = newer[field] ?? '';
		if (a === b) continue;
		const parts = trimContextParts(diffWords(a, b));
		entries.push({ kind: 'text', field, label: fieldLabels[field](), parts });
	}

	for (const field of SCALAR_FIELDS) {
		const a = older?.[field] ?? '';
		const b = newer[field] ?? '';
		if (a === b) continue;
		entries.push({ kind: 'scalar', field, label: fieldLabels[field](), oldVal: a, newVal: b });
	}

	// sender
	const senderA = older?.sender ? personLabel(older.sender) : '';
	const senderB = newer.sender ? personLabel(newer.sender) : '';
	if (senderA !== senderB) {
		const removed = senderA ? [senderA] : [];
		const added = senderB ? [senderB] : [];
		entries.push({
			kind: 'relation',
			field: 'sender',
			label: fieldLabels['sender'](),
			removed,
			added
		});
	}

	// receivers
	const receiversA = new Set((older?.receivers ?? []).map(personLabel));
	const receiversB = new Set((newer.receivers ?? []).map(personLabel));
	const removedReceivers = [...receiversA].filter((r) => !receiversB.has(r));
	const addedReceivers = [...receiversB].filter((r) => !receiversA.has(r));
	if (removedReceivers.length > 0 || addedReceivers.length > 0) {
		entries.push({
			kind: 'relation',
			field: 'receivers',
			label: fieldLabels['receivers'](),
			removed: removedReceivers,
			added: addedReceivers
		});
	}

	// tags
	const tagsA = new Set((older?.tags ?? []).map((t) => t.name));
	const tagsB = new Set((newer.tags ?? []).map((t) => t.name));
	const removedTags = [...tagsA].filter((t) => !tagsB.has(t));
	const addedTags = [...tagsB].filter((t) => !tagsA.has(t));
	if (removedTags.length > 0 || addedTags.length > 0) {
		entries.push({
			kind: 'relation',
			field: 'tags',
			label: fieldLabels['tags'](),
			removed: removedTags,
			added: addedTags
		});
	}

	return entries;
}

async function fetchSnapshot(versionId: string): Promise<SnapshotDoc> {
	const res = await fetch(`/api/documents/${doc.id}/versions/${versionId}`);
	if (!res.ok) throw new Error('Failed to fetch version');
	const v = await res.json();
	return parseSnapshot(v.snapshot);
}

async function toggleHistory() {
	historyOpen = !historyOpen;
	if (historyOpen && !historyLoaded) {
		historyLoading = true;
		try {
			const res = await fetch(`/api/documents/${doc.id}/versions`);
			if (res.ok) {
				versions = await res.json();
			}
			historyLoaded = true;
		} catch {
			// ignore
		} finally {
			historyLoading = false;
		}
	}
}

async function selectVersion(versionId: string) {
	if (selectedVersionId === versionId) {
		selectedVersionId = null;
		diffEntries = [];
		noDiff = false;
		return;
	}
	selectedVersionId = versionId;
	diffEntries = [];
	noDiff = false;
	diffLoading = true;
	try {
		const idx = versions.findIndex((v) => v.id === versionId);
		const newerSnap = await fetchSnapshot(versionId);
		const olderSnap = idx > 0 ? await fetchSnapshot(versions[idx - 1].id) : null;
		const entries = buildDiff(olderSnap, newerSnap);
		if (entries.length === 0) {
			noDiff = true;
		} else {
			diffEntries = entries;
		}
	} catch {
		// ignore
	} finally {
		diffLoading = false;
	}
}

async function applyCompare() {
	if (!compareA || !compareB || compareA === compareB) return;
	selectedVersionId = null;
	diffEntries = [];
	noDiff = false;
	diffLoading = true;
	try {
		const [snapA, snapB] = await Promise.all([fetchSnapshot(compareA), fetchSnapshot(compareB)]);
		// compareA is the "older" baseline, compareB is "newer"
		const entries = buildDiff(snapA, snapB);
		if (entries.length === 0) {
			noDiff = true;
		} else {
			diffEntries = entries;
		}
	} catch {
		// ignore
	} finally {
		diffLoading = false;
	}
}

function formatDateTime(iso: string): string {
	try {
		return new Intl.DateTimeFormat('de-DE', {
			day: 'numeric',
			month: 'short',
			year: 'numeric',
			hour: '2-digit',
			minute: '2-digit'
		}).format(new Date(iso));
	} catch {
		return iso;
	}
}

function versionLabel(v: VersionSummary, index: number): string {
	return `Version ${index + 1} — ${v.editorName} — ${formatDateTime(v.savedAt)}`;
}
</script>

<div class="flex h-screen flex-col bg-white">
	<!-- Top Bar -->
	<div
		class="z-10 flex items-center justify-between border-b border-brand-sand bg-white px-6 py-4 shadow-sm"
	>
		<div class="flex items-center gap-6 overflow-hidden">
			<a
				href="/"
				class="group flex flex-shrink-0 items-center gap-2 font-sans text-sm font-medium text-gray-500 transition-colors hover:text-brand-navy"
			>
				<div
					class="flex h-8 w-8 items-center justify-center rounded-full bg-brand-sand transition-colors group-hover:bg-brand-mint"
				>
					<img
						src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Arrow/Arrow-Left-MD.svg"
						alt=""
						aria-hidden="true"
						class="h-4 w-4"
					/>
				</div>
				<span>{m.btn_back()}</span>
			</a>

			<div class="flex items-center gap-4 overflow-hidden border-l border-gray-200 pl-6">
				<h1 class="truncate font-serif text-xl text-brand-navy" title={doc.title}>
					{doc.title || doc.originalFilename}
				</h1>
				<span
					class="flex-shrink-0 rounded-full px-3 py-1 font-sans text-xs font-bold tracking-wide uppercase
                    {doc.status === 'UPLOADED'
						? 'border border-brand-mint bg-brand-mint/30 text-brand-navy'
						: 'border border-yellow-200 bg-yellow-100 text-yellow-800'}"
				>
					{doc.status}
				</span>
			</div>
		</div>

		<div class="ml-4 flex flex-shrink-0 items-center gap-3 font-sans">
			{#if data.canWrite}
				<a
					href="/documents/{doc.id}/edit"
					class="flex items-center gap-2 rounded border border-brand-navy bg-transparent px-4 py-2 text-sm font-medium text-brand-navy transition hover:bg-brand-navy hover:text-white"
				>
					<img
						src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Edit-Content-MD.svg"
						alt=""
						aria-hidden="true"
						class="h-4 w-4"
					/>
					{m.btn_edit()}
				</a>
			{/if}

			{#if doc.filePath}
				<a
					href={fileUrl}
					download={doc.originalFilename}
					class="rounded border border-transparent bg-brand-sand/50 p-2 text-brand-navy transition hover:bg-brand-mint"
					title={m.doc_download_title()}
				>
					<img
						src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Download-MD.svg"
						alt=""
						aria-hidden="true"
						class="h-5 w-5"
					/>
				</a>
			{/if}
		</div>
	</div>

	<!-- Content Area -->
	<div class="flex flex-1 overflow-hidden">
		<!-- LEFT SIDEBAR: METADATA -->
		<aside
			class="custom-scrollbar w-96 flex-shrink-0 overflow-y-auto border-r border-brand-sand bg-white p-8"
		>
			<div class="space-y-10">
				<!-- 1. DETAILS GROUP -->
				<div>
					<h3
						class="mb-4 border-b border-brand-sand pb-2 font-sans text-xs font-bold tracking-widest text-brand-navy uppercase"
					>
						{m.doc_section_details()}
					</h3>
					<div class="space-y-5">
						<!-- Date -->
						<div class="group flex items-start">
							<span class="mt-0.5 w-8 text-brand-mint">
								<img
									src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Calendar/Calendar-Add-MD.svg"
									alt=""
									aria-hidden="true"
									class="h-5 w-5"
								/>
							</span>
							<div>
								<span class="block font-serif text-lg text-brand-navy">
									{doc.documentDate ? formatDate(doc.documentDate) : '—'}
								</span>
								<span class="font-sans text-xs text-gray-500">{m.doc_label_document_date()}</span>
							</div>
						</div>

						<!-- Creation Location -->
						<div class="group flex items-start">
							<span class="mt-0.5 w-8 text-brand-mint">
								<img
									src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Location-MD.svg"
									alt=""
									aria-hidden="true"
									class="h-5 w-5"
								/>
							</span>
							<div>
								<span class="block font-serif text-lg text-brand-navy">
									{doc.location ? doc.location : '—'}
								</span>
								<span class="font-sans text-xs text-gray-500"
									>{m.doc_label_creation_location()}</span
								>
							</div>
						</div>

						<!-- Physical Archive Location -->
						{#if doc.documentLocation}
							<div class="group flex items-start">
								<span class="mt-0.5 w-8 text-brand-mint">
									<img
										src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Folder-MD.svg"
										alt=""
										aria-hidden="true"
										class="h-5 w-5"
									/>
								</span>
								<div>
									<span class="block font-serif text-lg text-brand-navy">
										{doc.documentLocation}
									</span>
									<span class="font-sans text-xs text-gray-500"
										>{m.doc_label_archive_location_original()}</span
									>
								</div>
							</div>
						{/if}

						<!-- TAGS / SCHLAGWORTE -->
						{#if doc.tags && doc.tags.length > 0}
							<div class="group flex items-start">
								<span class="mt-0.5 w-8 text-brand-mint">
									<img
										src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Bookmark/Bookmark-Outline-MD.svg"
										alt=""
										aria-hidden="true"
										class="h-5 w-5"
									/>
								</span>
								<div class="flex-1">
									<div class="mb-1 flex flex-wrap gap-2">
										{#each doc.tags as tag (tag.id)}
											<a
												href="/?tag={encodeURIComponent(tag.name)}"
												class="inline-flex items-center rounded bg-brand-sand/50 px-2 py-0.5 text-xs font-bold tracking-wide text-brand-navy uppercase transition-colors hover:bg-brand-navy hover:text-white"
												title={m.doc_tag_filter_title({ name: tag.name })}
											>
												{tag.name}
											</a>
										{/each}
									</div>
									<span class="font-sans text-xs text-gray-500">{m.form_label_tags()}</span>
								</div>
							</div>
						{/if}
					</div>
				</div>

				<!-- 2. PERSONEN GROUP -->
				<div>
					<h3
						class="mb-4 border-b border-brand-sand pb-2 font-sans text-xs font-bold tracking-widest text-brand-navy uppercase"
					>
						{m.doc_section_persons()}
					</h3>

					<div class="mb-6">
						<span class="mb-2 block font-sans text-xs text-gray-400 uppercase"
							>{m.form_label_sender()}</span
						>
						{#if doc.sender}
							<a
								href="/persons/{doc.sender.id}"
								class="group block rounded border border-brand-sand bg-brand-sand/20 p-3 transition hover:border-brand-mint hover:bg-brand-mint/10"
							>
								<div class="flex items-center gap-3">
									<div
										class="flex h-8 w-8 items-center justify-center rounded-full bg-brand-navy font-serif text-sm text-white"
									>
										{doc.sender.firstName[0]}{doc.sender.lastName[0]}
									</div>
									<div>
										<p
											class="font-serif text-brand-navy decoration-brand-mint underline-offset-2 group-hover:underline"
										>
											{doc.sender.firstName}
											{doc.sender.lastName}
										</p>
										{#if doc.sender.alias}
											<p class="font-sans text-xs text-gray-500">{doc.sender.alias}</p>
										{/if}
									</div>
								</div>
							</a>
						{:else}
							<span class="font-serif text-sm text-gray-400 italic"
								>{m.doc_sender_not_specified()}</span
							>
						{/if}
					</div>

					<div>
						<span class="mb-2 block font-sans text-xs text-gray-400 uppercase"
							>{m.form_label_receivers()}</span
						>
						{#if doc.receivers && doc.receivers.length > 0}
							<div class="space-y-2">
								{#each doc.receivers as receiver (receiver.id)}
									<div
										class="group flex items-center justify-between rounded border border-brand-sand bg-white p-3 transition hover:border-brand-navy"
									>
										<a href="/persons/{receiver.id}" class="flex min-w-0 flex-1 items-center gap-3">
											<div
												class="flex h-6 w-6 items-center justify-center rounded-full bg-gray-100 font-serif text-xs text-gray-500"
											>
												{receiver.firstName[0]}{receiver.lastName[0]}
											</div>
											<span
												class="truncate font-serif text-sm text-brand-navy group-hover:text-brand-navy"
											>
												{receiver.firstName}
												{receiver.lastName}
											</span>
										</a>

										{#if doc.sender}
											<a
												href="/conversations?senderId={doc.sender.id}&receiverId={receiver.id}"
												class="text-gray-300 transition hover:text-brand-mint"
												title={m.doc_conversation_title()}
											>
												<img
													src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Chat-MD.svg"
													alt=""
													aria-hidden="true"
													class="h-5 w-5"
												/>
											</a>
										{/if}
									</div>
								{/each}
							</div>
						{:else}
							<span class="font-serif text-sm text-gray-400 italic">{m.doc_no_receivers()}</span>
						{/if}
					</div>
				</div>

				<!-- 3. INHALT GROUP -->
				{#if doc.summary || doc.transcription}
					<div>
						<h3
							class="mb-4 border-b border-brand-sand pb-2 font-sans text-xs font-bold tracking-widest text-brand-navy uppercase"
						>
							{m.doc_section_content()}
						</h3>

						<div class="space-y-6">
							{#if doc.summary}
								<div>
									<span class="mb-2 block font-sans text-xs text-gray-400 uppercase"
										>{m.doc_label_summary()}</span
									>
									<ExpandableText text={doc.summary} />
								</div>
							{/if}

							{#if doc.transcription}
								<div>
									<span class="mb-2 block font-sans text-xs text-gray-400 uppercase"
										>{m.form_label_transcription()}</span
									>
									<ExpandableText text={doc.transcription} />
								</div>
							{/if}
						</div>
					</div>
				{/if}

				<!-- 4. HISTORY GROUP -->
				<div>
					<div class="flex items-center justify-between border-b border-brand-sand pb-2">
						<h3 class="font-sans text-xs font-bold tracking-widest text-brand-navy uppercase">
							{m.history_section_title()}
						</h3>
						<button
							onclick={toggleHistory}
							class="flex items-center gap-1 rounded p-1 text-gray-400 transition hover:bg-brand-sand/50 hover:text-brand-navy"
							aria-expanded={historyOpen}
							aria-label={m.history_section_title()}
						>
							<svg
								class="h-4 w-4 transition-transform duration-200 {historyOpen ? 'rotate-180' : ''}"
								viewBox="0 0 20 20"
								fill="currentColor"
								aria-hidden="true"
							>
								<path
									fill-rule="evenodd"
									d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
									clip-rule="evenodd"
								/>
							</svg>
						</button>
					</div>

					{#if historyOpen}
						<div class="mt-4 space-y-3">
							{#if historyLoading}
								<p class="font-sans text-xs text-gray-400">{m.history_loading()}</p>
							{:else if versions.length === 0}
								<p class="font-serif text-sm text-gray-400 italic">{m.history_empty()}</p>
							{:else}
								<!-- Compare mode toggle -->
								<div class="flex justify-end">
									<button
										onclick={() => {
											compareMode = !compareMode;
											diffEntries = [];
											noDiff = false;
											selectedVersionId = null;
										}}
										class="font-sans text-xs font-medium transition {compareMode
											? 'text-brand-navy underline'
											: 'text-gray-400 hover:text-brand-navy'}"
									>
										{m.history_compare_mode()}
									</button>
								</div>

								{#if compareMode}
									<!-- Compare selects -->
									<div class="space-y-2">
										<div>
											<label
												for="compare-a"
												class="mb-1 block font-sans text-[10px] text-gray-400 uppercase"
												>{m.history_compare_select_a()}</label
											>
											<select
												id="compare-a"
												bind:value={compareA}
												class="w-full rounded border border-brand-sand bg-white px-2 py-1 font-sans text-xs text-brand-navy focus:ring-1 focus:ring-brand-mint focus:outline-none"
											>
												<option value="">—</option>
												{#each versions as v, i (v.id)}
													<option value={v.id}>{versionLabel(v, i)}</option>
												{/each}
											</select>
										</div>
										<div>
											<label
												for="compare-b"
												class="mb-1 block font-sans text-[10px] text-gray-400 uppercase"
												>{m.history_compare_select_b()}</label
											>
											<select
												id="compare-b"
												bind:value={compareB}
												class="w-full rounded border border-brand-sand bg-white px-2 py-1 font-sans text-xs text-brand-navy focus:ring-1 focus:ring-brand-mint focus:outline-none"
											>
												<option value="">—</option>
												{#each versions as v, i (v.id)}
													<option value={v.id}>{versionLabel(v, i)}</option>
												{/each}
											</select>
										</div>
										<button
											onclick={applyCompare}
											disabled={!compareA || !compareB || compareA === compareB}
											class="w-full rounded bg-brand-navy px-3 py-1.5 font-sans text-xs font-medium text-white transition hover:bg-brand-navy/80 disabled:cursor-not-allowed disabled:opacity-40"
										>
											{m.history_compare_apply()}
										</button>
									</div>
								{:else}
									<!-- Version list -->
									<ul class="divide-y divide-brand-sand">
										{#each versions as v, i (v.id)}
											<li>
												<button
													onclick={() => selectVersion(v.id)}
													data-testid="history-version"
													class="w-full py-2 text-left transition hover:bg-brand-sand/30 {selectedVersionId ===
													v.id
														? 'border-l-2 border-brand-mint pl-2'
														: 'pl-0'}"
												>
													<div class="flex items-baseline justify-between gap-2">
														<span class="font-sans text-xs font-medium text-brand-navy">
															Version {i + 1}
														</span>
														<span class="font-sans text-[10px] text-gray-400">
															{formatDateTime(v.savedAt)}
														</span>
													</div>
													<span class="font-sans text-[11px] text-gray-500">{v.editorName}</span>
													{#if v.changedFields && v.changedFields.length > 0}
														<div class="mt-1 flex flex-wrap gap-1">
															{#each v.changedFields as field (field)}
																<span
																	class="rounded bg-brand-sand/50 px-1.5 py-0.5 font-sans text-[10px] tracking-wide text-gray-500 uppercase"
																>
																	{fieldLabels[field] ? fieldLabels[field]() : field}
																</span>
															{/each}
														</div>
													{/if}
												</button>
											</li>
										{/each}
									</ul>
								{/if}

								<!-- Diff panel -->
								{#if diffLoading}
									<p class="font-sans text-xs text-gray-400">{m.history_loading()}</p>
								{:else if noDiff}
									<div
										data-testid="history-diff"
										class="rounded-sm border border-brand-sand bg-white p-4 font-serif text-sm text-gray-400 italic"
									>
										{m.history_diff_no_changes()}
									</div>
								{:else if diffEntries.length > 0}
									<div
										data-testid="history-diff"
										class="space-y-4 rounded-sm border border-brand-sand bg-white p-4"
									>
										{#each diffEntries as entry (entry.field)}
											<div>
												<span
													class="mb-1.5 block font-sans text-[10px] font-bold tracking-wide text-gray-400 uppercase"
													>{entry.label}</span
												>
												{#if entry.kind === 'text'}
													<p class="font-serif text-sm leading-relaxed">
														{#each entry.parts as part, partIdx (partIdx)}
															{#if part.added}
																<span class="bg-green-50 text-green-700">{part.value}</span>
															{:else if part.removed}
																<span class="bg-red-50 text-red-600 line-through">{part.value}</span
																>
															{:else}
																<span>{part.value}</span>
															{/if}
														{/each}
													</p>
												{:else if entry.kind === 'scalar'}
													<div class="flex items-center gap-2 font-serif text-sm">
														<span class="text-red-600 line-through">{entry.oldVal || '—'}</span>
														<svg
															class="h-3 w-3 flex-shrink-0 text-gray-400"
															viewBox="0 0 20 20"
															fill="currentColor"
															aria-hidden="true"
														>
															<path
																fill-rule="evenodd"
																d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z"
																clip-rule="evenodd"
															/>
														</svg>
														<span class="text-green-700">{entry.newVal || '—'}</span>
													</div>
												{:else if entry.kind === 'relation'}
													<div class="flex flex-wrap gap-1.5">
														{#each entry.removed as item (item)}
															<span
																class="rounded bg-red-50 px-1.5 py-0.5 font-sans text-[11px] text-red-600 line-through"
																>{item}</span
															>
														{/each}
														{#each entry.added as item (item)}
															<span
																class="rounded bg-green-50 px-1.5 py-0.5 font-sans text-[11px] text-green-700"
																>{item}</span
															>
														{/each}
													</div>
												{/if}
											</div>
										{/each}
									</div>
								{/if}
							{/if}
						</div>
					{/if}
				</div>

				<!-- Footer -->
				<div class="border-t border-brand-sand pt-4 font-sans text-[10px] text-gray-400">
					<p class="truncate">ID: {doc.id}</p>
					<p class="mt-1 truncate">{doc.originalFilename}</p>
				</div>
			</div>
		</aside>

		<!-- RIGHT: PREVIEW AREA -->
		<main class="relative flex flex-1 flex-col items-center justify-center bg-[#2A2A2A]">
			{#if isLoading}
				<div class="flex flex-col items-center text-brand-mint">
					<svg
						class="mb-4 h-8 w-8 animate-spin"
						xmlns="http://www.w3.org/2000/svg"
						fill="none"
						viewBox="0 0 24 24"
					>
						<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"
						></circle>
						<path
							class="opacity-75"
							fill="currentColor"
							d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
						></path>
					</svg>
					<span class="font-sans text-sm tracking-wide">{m.doc_loading()}</span>
				</div>
			{:else if error}
				<div class="px-4 text-center text-gray-400">
					<p class="mb-2 font-serif">{error}</p>
					{#if doc.filePath}
						<a
							href={`/api/documents/${doc.id}/file`}
							target="_blank"
							class="text-sm underline hover:text-white"
						>
							{m.doc_download_link()}
						</a>
					{/if}
				</div>
			{:else if !doc.filePath}
				<div class="flex flex-col items-center text-gray-400">
					<div class="mb-6 rounded-full bg-white/5 p-8">
						<img
							src="/degruyter-icons/Simple/Medium-24px/SVG/Action/PDF-Document-MD.svg"
							alt=""
							aria-hidden="true"
							class="h-12 w-12 opacity-50 invert"
						/>
					</div>
					<p class="font-sans text-sm tracking-wide uppercase">{m.doc_no_scan()}</p>
				</div>
			{:else if fileUrl && doc.contentType?.startsWith('application/pdf')}
				<PdfViewer url={fileUrl} documentId={doc.id} canAnnotate={data.canAnnotate} />
			{:else if fileUrl}
				<div class="flex h-full w-full items-center justify-center overflow-auto p-8">
					<img
						src={fileUrl}
						alt={m.doc_image_alt()}
						class="max-h-full max-w-full object-contain shadow-2xl"
					/>
				</div>
			{/if}
		</main>
	</div>
</div>
