<script lang="ts">
import PersonTypeahead from '$lib/components/PersonTypeahead.svelte';
import { goto, invalidateAll } from '$app/navigation';
import TagInput from '$lib/components/TagInput.svelte';
import { slide } from 'svelte/transition';
import { untrack } from 'svelte';
import { SvelteURLSearchParams } from 'svelte/reactivity';
import { m } from '$lib/paraglide/messages.js';
import { formatDate } from '$lib/utils/date';

let { data } = $props();

let q = $state(untrack(() => data.filters?.q || ''));
let qFocused = $state(false);
let from = $state(untrack(() => data.filters?.from || ''));
let to = $state(untrack(() => data.filters?.to || ''));
let senderId = $state(untrack(() => data.filters?.senderId || ''));
let receiverId = $state(untrack(() => data.filters?.receiverId || ''));
let tagNames = $state<string[]>(untrack(() => data.filters?.tags || []));

const ACCEPTED_TYPES = ['application/pdf', 'image/jpeg', 'image/png', 'image/tiff'];

let isDragging = $state(false);
let isUploading = $state(false);
let uploadMessages = $state<{ text: string; isError: boolean }[]>([]);
let fileInput: HTMLInputElement;

let searchTimer: ReturnType<typeof setTimeout>;

const hasAdvancedFilters = (filters: typeof data.filters) =>
	(filters?.tags?.length ?? 0) > 0 ||
	!!filters?.senderId ||
	!!filters?.receiverId ||
	!!filters?.from ||
	!!filters?.to;

let showAdvanced = $state(untrack(() => hasAdvancedFilters(data.filters)));

function handleDragOver(e: DragEvent) {
	e.preventDefault();
	isDragging = true;
}

function handleDragLeave() {
	isDragging = false;
}

async function handleDrop(e: DragEvent) {
	e.preventDefault();
	isDragging = false;
	const files = Array.from(e.dataTransfer?.files ?? []);
	await uploadFiles(files);
}

async function handleFileSelect(e: Event) {
	const input = e.target as HTMLInputElement;
	const files = Array.from(input.files ?? []);
	input.value = '';
	await uploadFiles(files);
}

async function uploadFiles(files: File[]) {
	if (files.length === 0) return;

	const messages: { text: string; isError: boolean }[] = [];

	// Client-side type validation
	const valid: File[] = [];
	for (const file of files) {
		if (!ACCEPTED_TYPES.includes(file.type)) {
			messages.push({ text: m.upload_invalid_type({ filename: file.name }), isError: true });
		} else {
			valid.push(file);
		}
	}

	if (valid.length === 0) {
		uploadMessages = messages;
		return;
	}

	isUploading = true;
	try {
		const formData = new FormData();
		for (const file of valid) {
			formData.append('files', file);
		}

		const res = await fetch('/api/documents/quick-upload', {
			method: 'POST',
			body: formData
		});

		if (res.ok) {
			const result = await res.json();
			if (result.created?.length > 0) {
				messages.push({ text: m.upload_success({ count: result.created.length }), isError: false });
			}
			for (const err of result.errors ?? []) {
				messages.push({ text: err, isError: true });
			}
			await invalidateAll();
		} else {
			for (const file of valid) {
				messages.push({ text: m.upload_error({ filename: file.name }), isError: true });
			}
		}
	} finally {
		isUploading = false;
		uploadMessages = messages;
	}
}

function triggerSearch() {
	const params = new SvelteURLSearchParams();

	if (q) params.set('q', q);
	if (from) params.set('from', from);
	if (to) params.set('to', to);
	if (senderId) params.set('senderId', senderId);
	if (receiverId) params.set('receiverId', receiverId);
	if (tagNames) tagNames.forEach((tag) => params.append('tag', tag));

	goto(`/?${params.toString()}`, {
		keepFocus: true,
		noScroll: true
	});
}

function handleTextSearch() {
	clearTimeout(searchTimer);
	searchTimer = setTimeout(() => {
		triggerSearch();
	}, 500);
}

// Trigger search when tags change
let prevTagStr = untrack(() => tagNames.join(','));
$effect(() => {
	const cur = tagNames.join(',');
	if (cur !== prevTagStr) {
		prevTagStr = cur;
		triggerSearch();
	}
});

// Sync local state with server data after navigation.
// Guard q: skip overwrite while the user is actively typing in the search field.
$effect(() => {
	if (!qFocused) q = data.filters?.q || '';
	from = data.filters?.from || '';
	to = data.filters?.to || '';
	senderId = data.filters?.senderId || '';
	receiverId = data.filters?.receiverId || '';
	tagNames = data.filters?.tags || [];
	if (hasAdvancedFilters(data.filters)) showAdvanced = true;
});
</script>

<!-- Outer Container: Matches the 'Sand' background of the layout -->
<main class="mx-auto max-w-7xl py-8 font-sans sm:px-6 lg:px-8">
	<!-- SEARCH & FILTER CARD -->
	<div class="mb-8 rounded-sm border border-line bg-surface p-6 shadow-sm">
		<!-- ROW 1: Main Search (One Line) -->
		<div class="flex items-center gap-4">
			<!-- Full Text Search -->
			<div class="relative flex-1">
				<input
					type="text"
					bind:value={q}
					oninput={handleTextSearch}
					onfocus={() => (qFocused = true)}
					onblur={() => (qFocused = false)}
					placeholder={m.docs_search_placeholder()}
					class="block w-full border-line py-2.5 pr-10 pl-3 placeholder-ink-3 shadow-sm focus:border-ink focus:ring-ink"
				/>
				<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3">
					<img
						src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Mag-Glass-MD.svg"
						alt=""
						aria-hidden="true"
						class="h-4 w-4 opacity-40"
					/>
				</div>
			</div>

			<!-- Toggle Advanced Button -->
			<button
				onclick={() => (showAdvanced = !showAdvanced)}
				class="flex items-center gap-2 border border-line bg-muted px-4 py-2.5 text-sm font-bold tracking-wide text-ink-2 uppercase transition hover:bg-muted hover:text-ink"
			>
				<img
					src="/degruyter-icons/Simple/Small-16px/SVG/Action/Chevron/Chevron-Down-SM.svg"
					alt=""
					aria-hidden="true"
					class="h-4 w-4 transform transition-transform duration-200 {showAdvanced ? 'rotate-180' : ''}"
				/>
				{m.docs_btn_filter()}
			</button>

			<!-- Reset Button -->
			<a
				href="/"
				class="flex items-center justify-center border border-transparent px-3 py-2.5 text-ink-3 transition hover:text-red-500"
				title={m.docs_btn_reset_title()}
			>
				<img
					src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Close-MD.svg"
					alt=""
					aria-hidden="true"
					class="h-5 w-5 opacity-40"
				/>
			</a>
		</div>

		<!-- ROW 2: Advanced Filters (Collapsible) -->
		{#if showAdvanced}
			<div
				transition:slide
				class="mt-6 grid grid-cols-1 gap-6 border-t border-line-2 pt-6 md:grid-cols-12"
			>
				<!-- Tag Filter -->
				<div class="md:col-span-12">
					<p class="mb-2 block text-xs font-bold tracking-widest text-ink-2 uppercase">
						{m.docs_filter_label_tags()}
					</p>
					<TagInput bind:tags={tagNames} allowCreation={false} />
				</div>

				<!-- Sender -->
				<div class="md:col-span-3">
					<div
						class="[&_input]:border-line [&_input]:py-2.5 [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-ink-2 [&_label]:uppercase"
					>
						<PersonTypeahead
							name="senderId"
							label={m.docs_filter_label_sender()}
							bind:value={senderId}
							initialName={data.initialValues?.senderName}
							onchange={triggerSearch}
						/>
					</div>
				</div>

				<!-- Receiver -->
				<div class="md:col-span-3">
					<div
						class="[&_input]:border-line [&_input]:py-2.5 [&_label]:mb-2 [&_label]:text-xs [&_label]:font-bold [&_label]:tracking-widest [&_label]:text-ink-2 [&_label]:uppercase"
					>
						<PersonTypeahead
							name="receiverId"
							label={m.docs_filter_label_receivers()}
							bind:value={receiverId}
							initialName={data.initialValues?.receiverName}
							onchange={triggerSearch}
						/>
					</div>
				</div>

				<!-- Dates -->
				<div class="grid grid-cols-2 gap-4 md:col-span-6">
					<div>
						<label
							for="from"
							class="mb-2 block text-xs font-bold tracking-widest text-ink-2 uppercase"
							>{m.docs_filter_label_from()}</label
						>
						<input
							type="date"
							id="from"
							bind:value={from}
							onchange={triggerSearch}
							class="block w-full border-line py-2.5 text-sm shadow-sm"
						/>
					</div>
					<div>
						<label
							for="to"
							class="mb-2 block text-xs font-bold tracking-widest text-ink-2 uppercase"
							>{m.docs_filter_label_to()}</label
						>
						<input
							type="date"
							id="to"
							bind:value={to}
							onchange={triggerSearch}
							class="block w-full border-line py-2.5 text-sm shadow-sm"
						/>
					</div>
				</div>
			</div>
		{/if}
	</div>

	{#if data.canWrite}
		<!-- UPLOAD DROP ZONE -->
		<div
			role="button"
			tabindex="0"
			class="mb-4 flex cursor-pointer items-center justify-center gap-3 border border-dashed px-6 py-3 text-sm transition-colors duration-150 {isDragging
				? 'border-accent bg-accent/5 text-accent'
				: 'border-line-2 text-ink-3 hover:border-accent hover:text-accent'}"
			ondragover={handleDragOver}
			ondragleave={handleDragLeave}
			ondrop={handleDrop}
			onclick={() => fileInput.click()}
			onkeydown={(e) => e.key === 'Enter' && fileInput.click()}
		>
			<img
				src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Upload/Upload-MD.svg"
				alt=""
				aria-hidden="true"
				class="h-4 w-4 shrink-0 opacity-50"
			/>
			<span class="font-sans font-medium">
				{isUploading ? '…' : m.upload_drop_hint()}
			</span>
			<span class="font-sans text-xs text-ink-3">{m.upload_accepted_types()}</span>
		</div>

		{#if uploadMessages.length > 0}
			<div class="mb-4 flex flex-col gap-1">
				{#each uploadMessages as msg, i (i)}
					<p class="font-sans text-sm {msg.isError ? 'text-red-600' : 'text-green-700'}">
						{msg.text}
					</p>
				{/each}
			</div>
		{/if}
	{/if}

	<!-- DOCUMENT LIST HEADER -->
	<div class="mb-2 flex justify-end">
		{#if data.canWrite}
			<a
				href="/documents/new"
				class="inline-flex items-center gap-1 text-sm font-medium text-ink/60 transition-colors hover:text-ink"
			>
				<img
					src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Add/Add-General-MD.svg"
					alt=""
					aria-hidden="true"
					class="h-4 w-4"
				/>
				{m.docs_btn_new()}
			</a>
		{/if}
	</div>

	<!-- DOCUMENT LIST -->
	<div class="border border-line bg-surface shadow-sm">
		{#if data.error}
			<div class="bg-red-50 p-8 text-center text-red-600">
				{data.error}
			</div>
		{:else if data.documents && data.documents.length > 0}
			<ul class="divide-y divide-line-2">
				{#each data.documents as doc (doc.id)}
					<li class="group transition-colors duration-200 hover:bg-muted/50">
						<!-- LINK TO DETAIL PAGE -->
						<a href="/documents/{doc.id}" class="block p-6">
							<div class="flex flex-col gap-6 sm:flex-row">
								<!-- Main Info -->
								<div class="flex-1">
									<div class="mb-2 flex items-baseline justify-between">
										<!-- Title: Serif & Brand Navy -->
										<h3
											class="font-serif text-xl font-medium text-ink decoration-brand-mint decoration-2 underline-offset-4 group-hover:underline"
										>
											{doc.title || doc.originalFilename}
										</h3>
									</div>

									<!-- Metadata Row -->
									<div class="mb-4 flex flex-wrap gap-6 font-sans text-sm text-ink-2">
										<div class="flex items-center">
											<img
												src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Calendar/Calendar-Add-MD.svg"
												alt=""
												aria-hidden="true"
												class="mr-1.5 h-4 w-4"
											/>
											{doc.documentDate ? formatDate(doc.documentDate) : '—'}
										</div>
										{#if doc.location}
											<div class="flex items-center">
												<img
													src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Location-MD.svg"
													alt=""
													aria-hidden="true"
													class="mr-1.5 h-4 w-4"
												/>
												{doc.location}
											</div>
										{/if}
									</div>

									<!-- Sender/Receiver Info -->
									<div class="grid grid-cols-1 gap-4 font-serif text-sm sm:grid-cols-2">
										<div class="flex items-baseline">
											<span
												class="w-10 font-sans text-xs font-bold tracking-wide text-ink-3 uppercase"
												>{m.docs_list_from()}</span
											>
											{#if doc.sender}
												<span class="text-ink">{doc.sender.firstName} {doc.sender.lastName}</span>
											{:else}
												<span class="text-ink-3 italic">{m.docs_list_unknown()}</span>
											{/if}
										</div>
										<div class="flex items-baseline">
											<span
												class="w-10 font-sans text-xs font-bold tracking-wide text-ink-3 uppercase"
												>{m.docs_list_to()}</span
											>
											{#if doc.receivers && doc.receivers.length > 0}
												<span class="text-ink">
													{doc.receivers.map((p) => p.firstName + ' ' + p.lastName).join(', ')}
												</span>
											{:else}
												<span class="text-ink-3 italic">{m.docs_list_unknown()}</span>
											{/if}
										</div>
									</div>

									<!-- Tags Display -->
									{#if doc.tags && doc.tags.length > 0}
										<div class="mt-4 flex flex-wrap gap-2 pt-3">
											{#each doc.tags as tag (tag.id)}
												<button
													type="button"
													class="relative z-10 inline-flex cursor-pointer items-center rounded bg-muted px-2 py-1 text-[10px] font-bold tracking-widest text-ink uppercase transition-colors hover:bg-primary hover:text-white"
													onclick={(e) => { e.preventDefault(); e.stopPropagation(); goto(`/?tag=${encodeURIComponent(tag.name)}`); }}
												>
													{tag.name}
												</button>
											{/each}
										</div>
									{/if}
								</div>

								<!-- Arrow Icon -->
								<div
									class="hidden items-center text-ink-3 transition-colors group-hover:text-accent sm:flex"
								>
									<img
										src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Arrow/Arrow-Right-MD.svg"
										alt=""
										aria-hidden="true"
										class="h-6 w-6"
									/>
								</div>
							</div>
						</a>
					</li>
				{/each}
			</ul>
		{:else}
			<!-- Empty State -->
			<div class="p-16 text-center">
				<div class="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full bg-muted">
					<img
						src="/degruyter-icons/Simple/Medium-24px/SVG/Action/Mag-Glass-MD.svg"
						alt=""
						aria-hidden="true"
						class="h-6 w-6"
					/>
				</div>
				<h3 class="font-serif text-lg font-medium text-ink">{m.docs_empty_heading()}</h3>
				<p class="mt-1 font-sans text-sm text-ink-2">
					{m.docs_empty_text()}
				</p>
				<button
					onclick={() => goto('/')}
					class="mt-6 text-sm font-bold tracking-wide text-accent uppercase transition hover:text-ink"
				>
					{m.docs_empty_btn_clear()}
				</button>
			</div>
		{/if}
	</div>
	<input
		bind:this={fileInput}
		type="file"
		multiple
		accept=".pdf,.jpg,.jpeg,.png,.tif,.tiff"
		class="sr-only"
		onchange={handleFileSelect}
	/>
</main>
