<script lang="ts">
	import { page } from '$app/stores';
	import { connectionState, nodeStore, edgeStore } from '$lib/realtime';
	import type { Edge } from '$lib/realtime';
	import { updateEdge, createCommunication } 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');
	const collectionId = $derived($page.params.id ?? '');

	const collectionNode = $derived(connected ? nodeStore.get(collectionId) : undefined);

	// =========================================================================
	// Kolonner — faste for redaksjonell arbeidsflate
	// =========================================================================

	const columns = ['pending', 'in_review', 'approved', 'scheduled'] as const;
	type Column = typeof columns[number];

	const columnLabels: Record<Column, string> = {
		pending: 'Innkomne',
		in_review: 'Under vurdering',
		approved: 'Godkjent',
		scheduled: 'Planlagt'
	};

	const columnColors: Record<Column, string> = {
		pending: 'bg-amber-50',
		in_review: 'bg-blue-50',
		approved: 'bg-green-50',
		scheduled: 'bg-purple-50'
	};

	const columnHeaderColors: Record<Column, string> = {
		pending: 'text-amber-700',
		in_review: 'text-blue-700',
		approved: 'text-green-700',
		scheduled: 'text-purple-700'
	};

	// =========================================================================
	// Kort fra WebSocket store — noder med submitted_to-edge til samlingen
	// =========================================================================

	interface CardData {
		nodeId: string;
		title: string;
		content: string | null;
		authorId: string | null;
		authorName: string | null;
		status: Column;
		submittedAt: string | null;
		publishAt: string | null;
		feedback: string | null;
		edgeId: string;
		edgeMeta: Record<string, unknown>;
		createdAt: number;
		discussionIds: string[];
	}

	function parseEdgeMeta(edge: Edge): Record<string, unknown> {
		try {
			return JSON.parse(edge.metadata ?? '{}') as Record<string, unknown>;
		} catch {
			return {};
		}
	}

	const cards = $derived.by((): CardData[] => {
		if (!connected || !collectionId) return [];

		const result: CardData[] = [];

		for (const edge of edgeStore.byTarget(collectionId)) {
			if (edge.edgeType !== 'submitted_to') continue;

			const node = nodeStore.get(edge.sourceId);
			if (!node) continue;

			const meta = parseEdgeMeta(edge);
			const rawStatus = (meta.status as string) ?? 'pending';

			// Map "approved" with publish_at to "scheduled"
			let status: Column;
			if (rawStatus === 'approved' && meta.publish_at) {
				status = 'scheduled';
			} else if (columns.includes(rawStatus as Column)) {
				status = rawStatus as Column;
			} else {
				status = 'pending';
			}

			// Resolve author name
			let authorName: string | null = null;
			const authorId = node.createdBy ?? null;
			if (node.createdBy) {
				const authorNode = nodeStore.get(node.createdBy);
				if (authorNode) authorName = authorNode.title;
			}

			// Find discussion nodes (communication nodes with belongs_to to this article)
			const discussionIds: string[] = [];
			for (const btEdge of edgeStore.byTarget(node.id)) {
				if (btEdge.edgeType !== 'belongs_to') continue;
				const srcNode = nodeStore.get(btEdge.sourceId);
				if (srcNode && srcNode.nodeKind === 'communication') {
					discussionIds.push(srcNode.id);
				}
			}

			result.push({
				nodeId: node.id,
				title: node.title || 'Uten tittel',
				content: node.content,
				authorId,
				authorName,
				status,
				submittedAt: (meta.submitted_at as string) ?? null,
				publishAt: (meta.publish_at as string) ?? null,
				feedback: (meta.feedback as string) ?? null,
				edgeId: edge.id,
				edgeMeta: meta,
				createdAt: node.createdAt ?? 0,
				discussionIds
			});
		}

		return result;
	});

	const cardsByColumn = $derived.by(() => {
		const grouped: Record<Column, CardData[]> = {
			pending: [],
			in_review: [],
			approved: [],
			scheduled: []
		};

		for (const card of cards) {
			grouped[card.status].push(card);
		}

		// Sort each column: newest first for pending, oldest first for others
		grouped.pending.sort((a, b) => b.createdAt - a.createdAt);
		for (const col of ['in_review', 'approved', 'scheduled'] as Column[]) {
			grouped[col].sort((a, b) => a.createdAt - b.createdAt);
		}

		return grouped;
	});

	// =========================================================================
	// Drag and drop
	// =========================================================================

	let draggedCard = $state<CardData | null>(null);
	let dragOverColumn = $state<Column | null>(null);

	function handleDragStart(e: DragEvent, card: CardData) {
		draggedCard = card;
		if (e.dataTransfer) {
			e.dataTransfer.effectAllowed = 'move';
			e.dataTransfer.setData('text/plain', card.nodeId);
		}
	}

	function handleDragOver(e: DragEvent, column: Column) {
		e.preventDefault();
		if (e.dataTransfer) e.dataTransfer.dropEffect = 'move';
		dragOverColumn = column;
	}

	function handleDragLeave() {
		dragOverColumn = null;
	}

	async function handleDrop(e: DragEvent, targetColumn: Column) {
		e.preventDefault();
		dragOverColumn = null;

		if (!draggedCard || !accessToken) return;
		if (draggedCard.status === targetColumn) {
			draggedCard = null;
			return;
		}

		const card = draggedCard;
		draggedCard = null;

		// "Planlagt" kolonne → vis publish_at-dialog
		if (targetColumn === 'scheduled') {
			schedulingCard = card;
			// Pre-fill with tomorrow at 08:00
			const tomorrow = new Date();
			tomorrow.setDate(tomorrow.getDate() + 1);
			tomorrow.setHours(8, 0, 0, 0);
			scheduledDate = tomorrow.toISOString().slice(0, 16);
			return;
		}

		try {
			// Map column back to actual status for the edge
			// Note: 'scheduled' case handled above with early return + dialog
			const newStatus = targetColumn;

			const newMeta: Record<string, unknown> = { ...card.edgeMeta, status: newStatus };

			// If moving away from scheduled, remove publish_at
			if (card.status === 'scheduled') {
				delete newMeta.publish_at;
			}

			await updateEdge(accessToken, {
				edge_id: card.edgeId,
				metadata: newMeta
			});
		} catch (err) {
			console.error('Feil ved statusendring:', err);
		}
	}

	function handleDragEnd() {
		draggedCard = null;
		dragOverColumn = null;
	}

	// =========================================================================
	// Planlagt publisering — publish_at dialog
	// =========================================================================

	let schedulingCard = $state<CardData | null>(null);
	let scheduledDate = $state('');
	let isScheduling = $state(false);

	async function confirmSchedule() {
		if (!schedulingCard || !accessToken || !scheduledDate) return;

		isScheduling = true;
		try {
			const publishAt = new Date(scheduledDate).toISOString();
			const newMeta: Record<string, unknown> = {
				...schedulingCard.edgeMeta,
				status: 'approved',
				publish_at: publishAt
			};

			await updateEdge(accessToken, {
				edge_id: schedulingCard.edgeId,
				metadata: newMeta
			});

			schedulingCard = null;
			scheduledDate = '';
		} catch (err) {
			console.error('Feil ved planlegging:', err);
		} finally {
			isScheduling = false;
		}
	}

	function cancelSchedule() {
		schedulingCard = null;
		scheduledDate = '';
	}

	// =========================================================================
	// Redaksjonell samtale — opprett kommunikasjonsnode
	// =========================================================================

	let creatingDiscussion = $state<string | null>(null);

	async function startDiscussion(card: CardData) {
		if (!accessToken || !nodeId || creatingDiscussion) return;

		creatingDiscussion = card.nodeId;
		try {
			const participants: string[] = [];
			if (card.authorId && card.authorId !== nodeId) {
				participants.push(card.authorId);
			}

			const result = await createCommunication(accessToken, {
				title: `Diskusjon: ${card.title}`,
				participants,
				context_id: card.nodeId
			});

			// Navigate to the new discussion
			window.location.href = `/chat/${result.node_id}`;
		} catch (err) {
			console.error('Feil ved opprettelse av samtale:', err);
		} finally {
			creatingDiscussion = null;
		}
	}

	// =========================================================================
	// Helpers
	// =========================================================================

	function formatDate(iso: string | null): string {
		if (!iso) return '';
		try {
			const d = new Date(iso);
			return d.toLocaleDateString('nb-NO', { day: 'numeric', month: 'short', year: 'numeric' });
		} catch {
			return '';
		}
	}

	function formatDateTime(iso: string | null): string {
		if (!iso) return '';
		try {
			const d = new Date(iso);
			return d.toLocaleDateString('nb-NO', {
				day: 'numeric', month: 'short', year: 'numeric',
				hour: '2-digit', minute: '2-digit'
			});
		} catch {
			return '';
		}
	}
</script>

<div class="min-h-screen bg-gray-50">
	<!-- Header -->
	<header class="border-b border-gray-200 bg-white">
		<div class="flex items-center justify-between px-4 py-3">
			<div class="flex items-center gap-3">
				<a href="/collection/{collectionId}" class="text-sm text-gray-400 hover:text-gray-600">&larr; Samling</a>
				<h1 class="text-lg font-semibold text-gray-900">
					{collectionNode?.title || 'Redaksjonell arbeidsflate'}
				</h1>
				<span class="rounded-full bg-indigo-50 px-2 py-0.5 text-xs font-medium text-indigo-600">Redaksjon</span>
			</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">{cards.length} innsendinger</span>
			</div>
		</div>
	</header>

	<!-- Board -->
	<main class="overflow-x-auto p-4">
		{#if !connected}
			<p class="text-sm text-gray-400">Venter på tilkobling…</p>
		{:else if !collectionNode}
			<div class="rounded-lg border border-yellow-200 bg-yellow-50 p-4 text-sm text-yellow-800">
				Samling ikke funnet. Sjekk at du har tilgang.
			</div>
		{:else}
			<div class="flex gap-4" style="min-width: max-content;">
				{#each columns as column (column)}
					{@const colCards = cardsByColumn[column]}
					<div
						class="w-80 shrink-0 rounded-lg {columnColors[column]} {dragOverColumn === column ? 'ring-2 ring-blue-400' : ''}"
						ondragover={(e: DragEvent) => handleDragOver(e, column)}
						ondragleave={handleDragLeave}
						ondrop={(e: DragEvent) => handleDrop(e, column)}
						role="list"
						aria-label={columnLabels[column]}
					>
						<!-- Column header -->
						<div class="flex items-center justify-between px-3 py-2">
							<h2 class="text-sm font-semibold {columnHeaderColors[column]}">
								{columnLabels[column]}
							</h2>
							<span class="rounded-full bg-white px-2 py-0.5 text-xs text-gray-500 shadow-sm">
								{colCards.length}
							</span>
						</div>

						<!-- Cards -->
						<div class="space-y-2 px-2 pb-2" style="min-height: 2rem;">
							{#each colCards as card (card.edgeId)}
								<div
									class="cursor-grab rounded-lg border border-gray-200 bg-white p-3 shadow-sm transition-shadow hover:shadow-md active:cursor-grabbing {draggedCard?.edgeId === card.edgeId ? 'opacity-50' : ''}"
									draggable="true"
									ondragstart={(e: DragEvent) => handleDragStart(e, card)}
									ondragend={handleDragEnd}
									role="listitem"
								>
									<h3 class="text-sm font-medium text-gray-900">
										{card.title}
									</h3>

									{#if card.content}
										<p class="mt-1 text-xs text-gray-500 line-clamp-2">
											{card.content}
										</p>
									{/if}

									<div class="mt-2 flex items-center justify-between">
										{#if card.authorName}
											<span class="text-xs text-gray-400">
												{card.authorName}
											</span>
										{/if}
										{#if card.submittedAt}
											<span class="text-xs text-gray-400">
												{formatDate(card.submittedAt)}
											</span>
										{/if}
									</div>

									{#if card.feedback}
										<div class="mt-2 rounded border-l-2 border-amber-400 bg-amber-50 px-2 py-1">
											<p class="text-xs text-amber-800">{card.feedback}</p>
										</div>
									{/if}

									<!-- Redaksjonell samtale -->
									{#if card.discussionIds.length > 0}
										<div class="mt-2 flex flex-wrap gap-1">
											{#each card.discussionIds as discId}
												<a
													href="/chat/{discId}"
													class="inline-flex items-center gap-1 rounded bg-indigo-50 px-2 py-0.5 text-xs text-indigo-700 hover:bg-indigo-100"
												>
													Samtale
												</a>
											{/each}
										</div>
									{:else}
										<button
											onclick={() => startDiscussion(card)}
											disabled={creatingDiscussion === card.nodeId}
											class="mt-2 inline-flex items-center gap-1 rounded border border-gray-200 px-2 py-0.5 text-xs text-gray-500 hover:bg-gray-50 hover:text-gray-700 disabled:opacity-50"
										>
											{creatingDiscussion === card.nodeId ? 'Oppretter…' : 'Start samtale'}
										</button>
									{/if}

									{#if card.publishAt}
										<div class="mt-2 flex items-center gap-1 text-xs text-purple-600">
											<span>Publiseres: {formatDateTime(card.publishAt)}</span>
										</div>
									{/if}
								</div>
							{/each}

							{#if colCards.length === 0}
								<div class="rounded-lg border border-dashed border-gray-300 p-4 text-center text-xs text-gray-400">
									{#if column === 'pending'}
										Ingen ventende innsendinger
									{:else if column === 'scheduled'}
										Dra godkjente artikler hit for å planlegge publisering
									{:else}
										Ingen artikler her
									{/if}
								</div>
							{/if}
						</div>
					</div>
				{/each}
			</div>
		{/if}
	</main>
</div>

<!-- Planleggingsdialog for publish_at -->
{#if schedulingCard}
	<div class="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
		<div class="w-full max-w-sm rounded-xl bg-white p-6 shadow-xl">
			<h3 class="text-base font-semibold text-gray-900">Planlegg publisering</h3>
			<p class="mt-1 text-sm text-gray-500">
				{schedulingCard.title}
			</p>

			<label class="mt-4 block">
				<span class="text-sm font-medium text-gray-700">Publiseringstidspunkt</span>
				<input
					type="datetime-local"
					bind:value={scheduledDate}
					class="mt-1 block w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-purple-500 focus:outline-none focus:ring-1 focus:ring-purple-500"
				/>
			</label>

			<div class="mt-6 flex justify-end gap-2">
				<button
					onclick={cancelSchedule}
					class="rounded-lg px-3 py-1.5 text-sm text-gray-600 hover:bg-gray-100"
				>
					Avbryt
				</button>
				<button
					onclick={confirmSchedule}
					disabled={isScheduling || !scheduledDate}
					class="rounded-lg bg-purple-600 px-4 py-1.5 text-sm font-medium text-white hover:bg-purple-700 disabled:opacity-50"
				>
					{isScheduling ? 'Planlegger…' : 'Planlegg'}
				</button>
			</div>
		</div>
	</div>
{/if}

<style>
	.line-clamp-2 {
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}
</style>
