<script lang="ts">
import { goto } from '$app/navigation';
import { m } from '$lib/paraglide/messages.js';
import DocumentRow from '$lib/document/DocumentRow.svelte';
import { SvelteMap } from 'svelte/reactivity';
import type { components } from '$lib/generated/api';

type DocumentListItem = components['schemas']['DocumentListItem'];

type SortMode = 'DATE' | 'TITLE' | 'SENDER' | 'RECEIVER' | 'UPLOAD_DATE' | 'RELEVANCE';

let {
	items,
	canWrite,
	error,
	total = 0,
	q = '',
	sort = 'DATE',
	from = '',
	to = ''
}: {
	items: DocumentListItem[];
	canWrite: boolean;
	error?: string | null;
	total?: number;
	q?: string;
	sort?: SortMode;
	from?: string;
	to?: string;
} = $props();

// A from/to range excludes undated documents — when it yields nothing, the
// empty state must say so explicitly (a localized constant, never a reflected
// backend string). Issue #668.
const hasDateRange = $derived(!!from || !!to);

const groups = $derived.by(() => {
	if (sort === 'SENDER') return groupBySender(items);
	if (sort === 'RECEIVER') return groupByReceiver(items);
	return groupByYear(items);
});

function groupByYear(docItems: DocumentListItem[]) {
	const map = new SvelteMap<string, DocumentListItem[]>();
	for (const item of docItems) {
		const label = item.documentDate?.substring(0, 4) ?? m.docs_group_undated();
		const bucket = map.get(label);
		if (bucket) bucket.push(item);
		else map.set(label, [item]);
	}
	return Array.from(map.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
}

function groupBySender(docItems: DocumentListItem[]) {
	const map = new SvelteMap<string, DocumentListItem[]>();
	for (const item of docItems) {
		const label = item.sender?.displayName ?? m.docs_group_unknown_sender();
		const bucket = map.get(label);
		if (bucket) bucket.push(item);
		else map.set(label, [item]);
	}
	return Array.from(map.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
}

function groupByReceiver(docItems: DocumentListItem[]) {
	const map = new SvelteMap<string, DocumentListItem[]>();
	for (const item of docItems) {
		const receivers = item.receivers ?? [];
		const labels =
			receivers.length > 0
				? receivers.map((r) => r.displayName)
				: [m.docs_group_unknown_receiver()];
		for (const label of labels) {
			const bucket = map.get(label);
			if (bucket) bucket.push(item);
			else map.set(label, [item]);
		}
	}
	return Array.from(map.entries()).map(([label, groupItems]) => ({ label, items: groupItems }));
}
</script>

<!-- ERROR -->
{#if error}
	<div class="border border-line bg-surface shadow-sm">
		<div class="bg-red-50 p-8 text-center text-red-600">
			{error}
		</div>
	</div>
{:else if items.length > 0}
	<!-- RESULT COUNT -->
	{#if total > 0}
		<p class="mb-2 text-sm text-ink-2">{total} Dokumente</p>
	{/if}
	<!-- GROUP CARDS -->
	{#each groups as group (group.label)}
		<div
			data-testid="group-card"
			class="mb-4 overflow-hidden border border-line bg-surface shadow-sm"
		>
			<div class="border-b border-line bg-muted px-5 py-2">
				<span
					data-testid="group-header"
					class="font-sans text-xs font-bold text-ink-3"
					class:uppercase={sort !== 'SENDER' && sort !== 'RECEIVER'}
					class:tracking-widest={sort !== 'SENDER' && sort !== 'RECEIVER'}
					class:tracking-wide={sort === 'SENDER' || sort === 'RECEIVER'}>{group.label}</span
				>
			</div>
			<ul class="divide-y divide-line">
				{#each group.items as item (group.label + '-' + item.id)}
					<DocumentRow item={item} canWrite={canWrite} />
				{/each}
			</ul>
		</div>
	{/each}
{:else}
	<!-- EMPTY STATE -->
	<div class="border border-line bg-surface shadow-sm">
		<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">
				{#if hasDateRange}
					{m.docs_range_excludes_undated()}
				{:else if q}
					{m.docs_empty_for_term({ term: q })}
				{:else}
					{m.docs_empty_text()}
				{/if}
			</p>
			<button
				onclick={() => goto('/documents')}
				class="mt-6 text-sm font-bold tracking-wide text-primary uppercase transition hover:text-ink-2"
			>
				{m.docs_empty_btn_clear()}
			</button>
		</div>
	</div>
{/if}
