<script lang="ts">
	import { page } from '$app/stores';
	import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/realtime';
	import type { Node } from '$lib/realtime';
	import { createNode, createEdge } from '$lib/api';

	const session = $derived($page.data.session as Record<string, unknown> | undefined);
	const nodeId = $derived(session?.nodeId as string | undefined);
	const accessToken = $derived(session?.accessToken as string | undefined);
	const connected = $derived(connectionState.current === 'connected');

	// =========================================================================
	// Diary entries: private nodes with no shared edges, sorted by time
	// =========================================================================

	/**
	 * A diary entry is a node that:
	 * 1. Was created by the current user
	 * 2. Has no non-system edges connecting it to other users/nodes
	 *    (only owner edge from user → node is allowed)
	 * 3. Is not a special kind (communication, agent)
	 */
	const diaryEntries = $derived.by((): Node[] => {
		if (!connected || !nodeId) return [];

		const entries: Node[] = [];

		for (const node of nodeStore.all) {
			// Must be created by current user
			if (node.createdBy !== nodeId) continue;

			// Skip special node kinds that aren't diary material
			if (node.nodeKind === 'communication' || node.nodeKind === 'agent' ||
				node.nodeKind === 'person' || node.nodeKind === 'team') continue;

			// Check if this node is "private" — no shared edges
			// Allowed edges: owner from user, system edges, self-referential edges
			if (hasSharedEdges(node.id)) continue;

			entries.push(node);
		}

		// Sort by created_at descending (newest first)
		entries.sort((a, b) => {
			const ta = a.createdAt ?? 0;
			const tb = b.createdAt ?? 0;
			return tb - ta;
		});

		return entries;
	});

	/**
	 * Check if a node has edges that "share" it with other users/nodes.
	 * Returns true if the node has non-private edges.
	 *
	 * Private means: only edges where the other end is the current user,
	 * the node itself, or system edges.
	 */
	function hasSharedEdges(targetNodeId: string): boolean {
		if (!nodeId) return false;

		// Check edges FROM this node
		for (const edge of edgeStore.bySource(targetNodeId)) {
			if (edge.system) continue;
			// Self-referential edge (e.g. scheduled edge pointing to itself)
			if (edge.targetId === targetNodeId) continue;
			// Edge to the owner (user)
			if (edge.targetId === nodeId) continue;
			// Any other edge means it's shared
			return true;
		}

		// Check edges TO this node
		for (const edge of edgeStore.byTarget(targetNodeId)) {
			if (edge.system) continue;
			// Self-referential
			if (edge.sourceId === targetNodeId) continue;
			// Edge from the owner (user), e.g. owner edge
			if (edge.sourceId === nodeId) continue;
			// Any other edge means it's shared
			return true;
		}

		return false;
	}

	// =========================================================================
	// Date grouping
	// =========================================================================

	interface DiaryGroup {
		dateLabel: string;
		dateKey: string;
		entries: Node[];
	}

	const monthNames = [
		'januar', 'februar', 'mars', 'april', 'mai', 'juni',
		'juli', 'august', 'september', 'oktober', 'november', 'desember'
	];
	const dayNames = ['søndag', 'mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag'];

	function nodeDate(node: Node): Date {
		const micros = node.createdAt ?? 0;
		return new Date(micros / 1000);
	}

	function formatDateKey(d: Date): string {
		return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
	}

	function formatDateLabel(d: Date): string {
		const today = new Date();
		const todayKey = formatDateKey(today);
		const dateKey = formatDateKey(d);

		if (dateKey === todayKey) return 'I dag';

		const yesterday = new Date(today);
		yesterday.setDate(yesterday.getDate() - 1);
		if (dateKey === formatDateKey(yesterday)) return 'I går';

		return `${dayNames[d.getDay()]} ${d.getDate()}. ${monthNames[d.getMonth()]} ${d.getFullYear()}`;
	}

	/** Group diary entries by date */
	const groupedEntries = $derived.by((): DiaryGroup[] => {
		const groups = new Map<string, { label: string; entries: Node[] }>();

		for (const node of diaryEntries) {
			const d = nodeDate(node);
			const key = formatDateKey(d);
			const existing = groups.get(key);
			if (existing) {
				existing.entries.push(node);
			} else {
				groups.set(key, { label: formatDateLabel(d), entries: [node] });
			}
		}

		return [...groups.entries()].map(([dateKey, { label, entries }]) => ({
			dateLabel: label,
			dateKey,
			entries
		}));
	});

	// =========================================================================
	// Create new diary entry
	// =========================================================================

	let newTitle = $state('');
	let newContent = $state('');
	let isCreating = $state(false);
	let showForm = $state(false);

	async function handleCreate() {
		if (!accessToken || !nodeId || !newTitle.trim() || isCreating) return;

		isCreating = true;
		try {
			const { node_id } = await createNode(accessToken, {
				node_kind: 'content',
				title: newTitle.trim(),
				content: newContent.trim() || undefined,
				visibility: 'hidden'
			});

			// Create owner edge
			await createEdge(accessToken, {
				source_id: nodeId,
				target_id: node_id,
				edge_type: 'owner'
			});

			newTitle = '';
			newContent = '';
			showForm = false;
		} catch (err) {
			console.error('Feil ved oppretting av dagbokinnlegg:', err);
		} finally {
			isCreating = false;
		}
	}

	function handleKeydown(e: KeyboardEvent) {
		if (e.key === 'Escape') {
			showForm = false;
			newTitle = '';
			newContent = '';
		}
	}

	// =========================================================================
	// Time formatting
	// =========================================================================

	function formatTime(node: Node): string {
		const d = nodeDate(node);
		return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
	}

	/** Truncate content to a short excerpt */
	function excerpt(content: string, maxLen = 200): string {
		if (!content) return '';
		if (content.length <= maxLen) return content;
		return content.slice(0, maxLen).trimEnd() + '…';
	}

	/** Kind label in Norwegian */
	function kindLabel(kind: string): string {
		const labels: Record<string, string> = {
			content: 'Innhold',
			collection: 'Samling',
			topic: 'Tema',
			media: 'Media'
		};
		return labels[kind] ?? kind;
	}
</script>

<div class="min-h-screen bg-gray-50">
	<!-- Header -->
	<header class="border-b border-gray-200 bg-white">
		<div class="mx-auto flex max-w-3xl items-center justify-between px-4 py-3">
			<div class="flex items-center gap-3">
				<a href="/" class="text-sm text-gray-400 hover:text-gray-600">&larr; Arbeidsflaten</a>
				<h1 class="text-lg font-semibold text-gray-900">Dagbok</h1>
			</div>
			<div class="flex items-center gap-3">
				{#if connected}
					<span class="text-xs text-green-600">Tilkoblet</span>
				{:else}
					<span class="text-xs text-gray-400">{connectionState.current}</span>
				{/if}
				<span class="text-xs text-gray-400">{diaryEntries.length} innlegg</span>
			</div>
		</div>
	</header>

	<main class="mx-auto max-w-3xl px-4 py-6">
		{#if !connected}
			<p class="text-sm text-gray-400">Venter på tilkobling…</p>
		{:else}
			<!-- New entry button / form -->
			{#if accessToken && nodeId}
				{#if !showForm}
					<button
						onclick={() => showForm = true}
						class="mb-6 w-full rounded-lg border-2 border-dashed border-gray-300 bg-white p-4 text-sm text-gray-500 hover:border-gray-400 hover:text-gray-700 transition-colors"
					>
						Nytt dagbokinnlegg…
					</button>
				{:else}
					<div class="mb-6 rounded-lg border border-gray-200 bg-white p-4 shadow-sm" onkeydown={handleKeydown}>
						<input
							type="text"
							bind:value={newTitle}
							placeholder="Tittel…"
							class="w-full rounded border border-gray-200 px-3 py-2 text-sm focus:border-blue-400 focus:outline-none"
							disabled={isCreating}
						/>
						<textarea
							bind:value={newContent}
							placeholder="Skriv her…"
							rows={4}
							class="mt-2 w-full rounded border border-gray-200 px-3 py-2 text-sm focus:border-blue-400 focus:outline-none resize-y"
							disabled={isCreating}
						></textarea>
						<div class="mt-3 flex gap-2">
							<button
								onclick={handleCreate}
								disabled={isCreating || !newTitle.trim()}
								class="rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:opacity-50"
							>
								{isCreating ? 'Lagrer…' : 'Lagre'}
							</button>
							<button
								onclick={() => { showForm = false; newTitle = ''; newContent = ''; }}
								class="rounded-lg px-4 py-2 text-sm text-gray-500 hover:bg-gray-100"
							>
								Avbryt
							</button>
						</div>
					</div>
				{/if}
			{/if}

			<!-- Diary entries grouped by date -->
			{#if diaryEntries.length === 0}
				<div class="text-center py-12">
					<p class="text-gray-400 text-sm">Ingen dagbokinnlegg ennå.</p>
					<p class="text-gray-300 text-xs mt-1">Private noder uten delte edges vises her.</p>
				</div>
			{:else}
				<div class="space-y-6">
					{#each groupedEntries as group (group.dateKey)}
						<div>
							<h2 class="mb-2 text-sm font-semibold text-gray-500 uppercase tracking-wide">
								{group.dateLabel}
							</h2>
							<ul class="space-y-2">
								{#each group.entries as node (node.id)}
									<li class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm">
										<div class="flex items-start justify-between gap-2">
											<div class="min-w-0 flex-1">
												<div class="flex items-center gap-2">
													<span class="shrink-0 text-xs text-gray-400">{formatTime(node)}</span>
													<h3 class="font-medium text-gray-900 truncate">
														{node.title || 'Uten tittel'}
													</h3>
												</div>
												{#if node.content}
													<p class="mt-1 text-sm text-gray-500 whitespace-pre-line">
														{excerpt(node.content)}
													</p>
												{/if}
											</div>
											{#if node.nodeKind !== 'content'}
												<span class="shrink-0 rounded-full bg-gray-100 px-2 py-0.5 text-xs text-gray-500">
													{kindLabel(node.nodeKind)}
												</span>
											{/if}
										</div>
									</li>
								{/each}
							</ul>
						</div>
					{/each}
				</div>
			{/if}
		{/if}
	</main>
</div>
