<script lang="ts">
import { enhance } from '$app/forms';
import { invalidate } from '$app/navigation';
import { onMount, onDestroy, untrack } from 'svelte';
import type { Snippet } from 'svelte';
import { createFileLoader } from '$lib/hooks/useFileLoader.svelte';
import { m } from '$lib/paraglide/messages.js';
import { countRequiredFilled } from '$lib/utils/requiredFields';
import { validateFile } from '$lib/utils/validateFile';
import DocumentViewer from '$lib/components/DocumentViewer.svelte';
import UploadZone from '$lib/components/document/UploadZone.svelte';
import WhoWhenSection from '$lib/components/document/WhoWhenSection.svelte';
import DescriptionSection from '$lib/components/document/DescriptionSection.svelte';
import type { Tag } from '$lib/components/TagInput.svelte';
import type { components } from '$lib/generated/api';

type Person = components['schemas']['Person'];
type Doc = components['schemas']['Document'];

let {
	doc,
	formId,
	formAction,
	formError = null,
	tags = $bindable<Tag[]>([]),
	senderId = $bindable(''),
	selectedReceivers = $bindable<Person[]>([]),
	dateIso = $bindable(''),
	currentTitle = $bindable(''),
	topbar,
	actionbar
}: {
	doc: Doc;
	formId: string;
	formAction: string;
	formError?: string | null;
	tags?: Tag[];
	senderId?: string;
	selectedReceivers?: Person[];
	dateIso?: string;
	currentTitle?: string;
	topbar: Snippet;
	actionbar: Snippet;
} = $props();

tags = untrack(() => (doc.tags as Tag[]) ?? []);
senderId = untrack(() => doc.sender?.id ?? '');
selectedReceivers = untrack(() => (doc.receivers as Person[]) ?? []);
dateIso = untrack(() => doc.documentDate ?? '');
currentTitle = untrack(() => doc.title ?? '');

const fileLoader = createFileLoader();
let navHeight = $state(0);
onMount(() => {
	navHeight = document.querySelector('header')?.getBoundingClientRect().height ?? 0;
});
let activeAnnotationId = $state<string | null>(null);

$effect(() => {
	if (doc?.id && doc?.filePath) {
		fileLoader.loadFile(`/api/documents/${doc.id}/file`);
	}
});
onDestroy(() => fileLoader.destroy());

const requiredFilled = $derived(countRequiredFilled(currentTitle, dateIso, senderId));
const requiredPct = $derived((requiredFilled / 3) * 100);

let isUploading = $state(false);
let isDragging = $state(false);
let uploadError = $state<string | null>(null);
let abortController = $state<AbortController | null>(null);

async function handleFile(file: File) {
	uploadError = null;
	isUploading = true;
	const controller = new AbortController();
	abortController = controller;
	try {
		const formData = new FormData();
		formData.append('file', file);
		const res = await fetch(`/api/documents/${doc.id}/file`, {
			method: 'POST',
			body: formData,
			signal: controller.signal
		});
		if (!res.ok) throw new Error('Upload fehlgeschlagen');
		await invalidate('app:document');
	} catch (e) {
		if ((e as Error).name === 'AbortError') return;
		uploadError = m.error_file_upload_failed();
	} finally {
		isUploading = false;
		abortController = null;
	}
}

function cancelUpload() {
	abortController?.abort();
	isUploading = false;
}

async function handleReplaceFile(e: Event) {
	const file = (e.currentTarget as HTMLInputElement).files?.[0];
	if (!file) return;
	const validationError = validateFile(file);
	if (validationError === 'type') {
		uploadError = m.error_unsupported_file_type();
		return;
	}
	if (validationError === 'size') {
		uploadError = m.error_file_too_large();
		return;
	}
	await handleFile(file);
}
</script>

<div class="fixed inset-x-0 bottom-0 flex flex-col" style="top: {navHeight}px">
	<!-- Top bar — caller-supplied via snippet -->
	<div class="flex items-center justify-between border-b border-line bg-surface px-6 py-3">
		{@render topbar()}
	</div>

	<!-- Required-fields progress bar -->
	<div class="flex items-center gap-3 border-b border-line bg-surface px-6 py-1.5">
		<span class="text-xs font-bold tracking-widest text-ink-3 uppercase"
			>{m.label_required_fields()}</span
		>
		<div
			class="h-0.5 flex-1 rounded-full bg-line"
			role="progressbar"
			aria-valuenow={requiredFilled}
			aria-valuemin={0}
			aria-valuemax={3}
			aria-label={m.label_required_fields()}
		>
			<div
				class="h-full rounded-full bg-brand-navy transition-all duration-300"
				style="width:{requiredPct}%"
			></div>
		</div>
		<span class="text-xs font-bold text-brand-navy">{requiredFilled} / 3</span>
	</div>

	<!-- Main content -->
	<div class="flex flex-1 overflow-hidden">
		<!-- Left: PDF preview / upload zone (60%) -->
		<div class="relative flex flex-[6] flex-col overflow-hidden border-r border-line">
			{#if !doc.filePath}
				<UploadZone
					filename={doc.originalFilename ?? ''}
					isUploading={isUploading}
					bind:isDragging={isDragging}
					error={uploadError}
					onFile={handleFile}
					onCancel={cancelUpload}
				/>
			{:else}
				<!-- Datei ersetzen toolbar -->
				<div class="flex shrink-0 items-center border-b border-line bg-surface px-4 py-1.5">
					<label
						class="ml-auto flex min-h-[44px] cursor-pointer items-center text-xs font-bold tracking-widest text-ink-3 uppercase transition-colors hover:text-ink"
					>
						{m.doc_file_replace_label()}
						<input type="file" class="sr-only" onchange={handleReplaceFile} />
					</label>
				</div>
				<div class="relative flex-1 overflow-hidden">
					<DocumentViewer
						doc={doc}
						fileUrl={fileLoader.fileUrl}
						isLoading={fileLoader.isLoading}
						error={fileLoader.fileError}
						bind:activeAnnotationId={activeAnnotationId}
						onAnnotationClick={() => {}}
					/>
				</div>
			{/if}
		</div>

		<!-- Right: form (40%) -->
		<div class="flex flex-[4] flex-col overflow-hidden">
			{#if formError}
				<div class="border-b border-red-200 bg-red-50 px-6 py-3 text-sm text-red-700">
					{formError}
				</div>
			{/if}

			<form
				id={formId}
				method="POST"
				action={formAction}
				enctype="multipart/form-data"
				use:enhance
				class="flex-1 space-y-5 overflow-y-auto p-6"
			>
				<WhoWhenSection
					bind:senderId={senderId}
					bind:selectedReceivers={selectedReceivers}
					bind:dateIso={dateIso}
					initialDateIso={doc.documentDate ?? ''}
					initialLocation={doc.location ?? ''}
					initialSenderName={doc.sender?.displayName ?? ''}
				/>
				<DescriptionSection
					bind:tags={tags}
					bind:currentTitle={currentTitle}
					initialTitle={doc.title ?? ''}
					initialArchiveBox={doc.archiveBox ?? ''}
					initialArchiveFolder={doc.archiveFolder ?? ''}
					initialSummary={doc.summary ?? ''}
					titleRequired={true}
				/>
			</form>

			<!-- Action bar — caller-supplied via snippet -->
			<div class="flex items-center justify-between gap-3 border-t border-line bg-surface p-4">
				{@render actionbar()}
			</div>
		</div>
	</div>
</div>
