<script lang="ts">
	import type { Node, Edge } from '$lib/realtime';
	import { edgeStore, nodeStore, nodeVisibility } from '$lib/realtime';
	import { createNode, createEdge, updateEdge } from '$lib/api';
	import { setDragPayload, checkKanbanCompat, type DragPayload } from '$lib/transfer';
	import type { BlockReceiver, PlacementIntent } from '$lib/components/blockshell/types';

	interface Props {
		collection?: Node;
		config: Record<string, unknown>;
		userId?: string;
		accessToken?: string;
		/** Called when a drop is received on this panel */
		onReceiveDrop?: (payload: DragPayload, intent: PlacementIntent) => void;
	}

	let { collection, config, userId, accessToken, onReceiveDrop }: Props = $props();

	/**
	 * BlockReceiver implementation for Kanban.
	 * Accepts communication and content nodes as new tasks.
	 * Creates source_material edge to the original.
	 * Ref: docs/retninger/arbeidsflaten.md § Kompatibilitetsmatrise
	 */
	export const receiver: BlockReceiver = {
		canReceive(payload: DragPayload) {
			return checkKanbanCompat(payload);
		},
		receive(payload: DragPayload) {
			const intent: PlacementIntent = {
				mode: 'innholdstransfer',
				contextId: collection?.id ?? '',
				contextType: 'kanban',
				position: { column_id: 'todo', position: 0 },
			};
			onReceiveDrop?.(payload, intent);
			return intent;
		}
	};

	// =========================================================================
	// Column definitions from collection metadata
	// =========================================================================

	const columns = $derived.by(() => {
		if (!collection) return ['todo', 'in_progress', 'done'];
		try {
			const meta = JSON.parse(collection.metadata ?? '{}');
			const traitConf = meta.traits?.kanban;
			if (traitConf && Array.isArray(traitConf.columns) && traitConf.columns.length > 0) {
				return traitConf.columns as string[];
			}
		} catch { /* ignore */ }
		return ['todo', 'in_progress', 'done'];
	});

	const columnLabels: Record<string, string> = {
		todo: 'Å gjøre',
		in_progress: 'I gang',
		done: 'Ferdig',
	};

	function columnLabel(col: string): string {
		return columnLabels[col] ?? col;
	}

	// =========================================================================
	// Cards: nodes with belongs_to edge to this collection
	// =========================================================================

	interface CardData {
		node: Node;
		status: string;
		position: number;
		belongsToEdge: Edge;
		statusEdge: Edge | undefined;
	}

	const cards = $derived.by((): CardData[] => {
		if (!collection?.id) return [];

		const result: CardData[] = [];

		for (const edge of edgeStore.byTarget(collection.id)) {
			if (edge.edgeType !== 'belongs_to') continue;

			const node = nodeStore.get(edge.sourceId);
			if (!node || nodeVisibility(node, userId) === 'hidden') continue;
			// Skip non-content nodes (communication channels, etc.)
			if (node.nodeKind !== 'content') continue;

			let statusEdge: Edge | undefined;
			let status = columns[0] ?? 'todo';

			for (const e of edgeStore.bySource(node.id)) {
				if (e.edgeType === 'status' && e.targetId === collection.id) {
					statusEdge = e;
					try {
						const meta = JSON.parse(e.metadata ?? '{}');
						if (meta.value) status = meta.value;
					} catch { /* ignore */ }
					break;
				}
			}

			let position = 0;
			try {
				const meta = JSON.parse(edge.metadata ?? '{}');
				if (typeof meta.position === 'number') position = meta.position;
			} catch { /* ignore */ }

			result.push({ node, status, position, belongsToEdge: edge, statusEdge });
		}

		return result;
	});

	const cardsByColumn = $derived.by(() => {
		const grouped: Record<string, CardData[]> = {};
		for (const col of columns) {
			grouped[col] = [];
		}
		for (const card of cards) {
			const col = columns.includes(card.status) ? card.status : columns[0] ?? 'todo';
			if (!grouped[col]) grouped[col] = [];
			grouped[col].push(card);
		}
		for (const col of Object.keys(grouped)) {
			grouped[col].sort((a, b) => a.position - b.position);
		}
		return grouped;
	});

	// =========================================================================
	// Internal drag-and-drop (column move)
	// =========================================================================

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

	function handleDragStart(e: DragEvent, card: CardData) {
		draggedCard = card;
		if (!e.dataTransfer) return;
		// Set both internal state and cross-panel payload
		e.dataTransfer.effectAllowed = 'move';
		setDragPayload(e.dataTransfer, {
			nodeId: card.node.id,
			nodeKind: card.node.nodeKind,
			sourcePanel: 'kanban',
		});
	}

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

	function handleDragLeave() {
		dragOverColumn = null;
	}

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

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

		const card = draggedCard;
		draggedCard = null;

		try {
			if (card.statusEdge) {
				await updateEdge(accessToken, {
					edge_id: card.statusEdge.id,
					metadata: { value: targetColumn },
				});
			} else {
				await createEdge(accessToken, {
					source_id: card.node.id,
					target_id: collection.id,
					edge_type: 'status',
					metadata: { value: targetColumn },
				});
			}
		} catch (err) {
			console.error('Feil ved statusendring:', err);
		}
	}

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

	// =========================================================================
	// Card creation
	// =========================================================================

	let newCardTitle = $state('');
	let addingToColumn = $state<string | null>(null);
	let isCreating = $state(false);

	async function handleCreateCard(column: string) {
		if (!accessToken || !collection || !newCardTitle.trim() || isCreating) return;

		isCreating = true;
		try {
			const colCards = cardsByColumn[column] ?? [];
			const maxPos = colCards.length > 0
				? Math.max(...colCards.map(c => c.position))
				: 0;
			const position = maxPos + 1;

			const { node_id } = await createNode(accessToken, {
				node_kind: 'content',
				title: newCardTitle.trim(),
				visibility: 'hidden',
			});

			await createEdge(accessToken, {
				source_id: node_id,
				target_id: collection.id,
				edge_type: 'belongs_to',
				metadata: { position },
			});

			await createEdge(accessToken, {
				source_id: node_id,
				target_id: collection.id,
				edge_type: 'status',
				metadata: { value: column },
			});

			newCardTitle = '';
			addingToColumn = null;
		} catch (err) {
			console.error('Feil ved oppretting av kort:', err);
		} finally {
			isCreating = false;
		}
	}

	function handleCardKeydown(e: KeyboardEvent, column: string) {
		if (e.key === 'Enter') {
			e.preventDefault();
			handleCreateCard(column);
		} else if (e.key === 'Escape') {
			addingToColumn = null;
			newCardTitle = '';
		}
	}

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

	function formatTime(node: Node): string {
		if (!node.createdAt) return '';
		const ms = Math.floor(node.createdAt / 1000);
		const date = new Date(ms);
		return date.toLocaleDateString('nb-NO', { day: 'numeric', month: 'short' });
	}
</script>

<!--
	KanbanTrait — fullverdig BlockShell-panel for kanban-brett.
	Viser kolonner med kort, drag-and-drop mellom kolonner,
	og støtter mottak av noder fra andre paneler.
	Forelder (collection page) wrapper dette i BlockShell.
-->

<div class="kanban-trait">
	{#if cards.length === 0 && !accessToken}
		<!-- Empty state (read-only) -->
		<div class="kanban-empty">
			<span class="kanban-empty-icon">📋</span>
			<p>Ingen oppgaver på brettet ennå.</p>
		</div>
	{:else}
		<!-- Board columns -->
		<div class="kanban-board">
			{#each columns as column (column)}
				{@const colCards = cardsByColumn[column] ?? []}
				<div
					class="kanban-column {dragOverColumn === column ? 'kanban-column-dragover' : ''}"
					ondragover={(e) => handleDragOver(e, column)}
					ondragleave={handleDragLeave}
					ondrop={(e) => handleDrop(e, column)}
					role="list"
					aria-label={columnLabel(column)}
				>
					<!-- Column header -->
					<div class="kanban-column-header">
						<span class="kanban-column-title">{columnLabel(column)}</span>
						<span class="kanban-column-count">{colCards.length}</span>
					</div>

					<!-- Cards -->
					<div class="kanban-column-cards">
						{#each colCards as card (card.node.id)}
							<div
								class="kanban-card {draggedCard?.node.id === card.node.id ? 'kanban-card-dragging' : ''}"
								draggable="true"
								ondragstart={(e) => handleDragStart(e, card)}
								ondragend={handleDragEnd}
								role="listitem"
							>
								<span class="kanban-card-title">
									{card.node.title || 'Uten tittel'}
								</span>
								{#if card.node.content}
									<span class="kanban-card-content">
										{card.node.content}
									</span>
								{/if}
								{#if formatTime(card.node)}
									<span class="kanban-card-time">{formatTime(card.node)}</span>
								{/if}
							</div>
						{/each}

						<!-- Add card -->
						{#if addingToColumn === column}
							<div class="kanban-add-form">
								<input
									type="text"
									bind:value={newCardTitle}
									onkeydown={(e) => handleCardKeydown(e, column)}
									placeholder="Tittel…"
									class="kanban-add-input"
									disabled={isCreating}
								/>
								<div class="kanban-add-actions">
									<button
										onclick={() => handleCreateCard(column)}
										disabled={isCreating || !newCardTitle.trim()}
										class="kanban-add-btn"
									>
										{isCreating ? '…' : 'Legg til'}
									</button>
									<button
										onclick={() => { addingToColumn = null; newCardTitle = ''; }}
										class="kanban-cancel-btn"
									>
										Avbryt
									</button>
								</div>
							</div>
						{:else if accessToken}
							<button
								onclick={() => { addingToColumn = column; newCardTitle = ''; }}
								class="kanban-add-trigger"
							>
								+ Nytt kort
							</button>
						{/if}
					</div>
				</div>
			{/each}
		</div>
	{/if}
</div>

<style>
	/* ================================================================= */
	/* Root — fills BlockShell content area                               */
	/* ================================================================= */
	.kanban-trait {
		display: flex;
		flex-direction: column;
		height: 100%;
		min-height: 0;
		overflow: hidden;
	}

	/* ================================================================= */
	/* Empty state                                                        */
	/* ================================================================= */
	.kanban-empty {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		flex: 1;
		padding: 24px;
		color: var(--color-text-dim);
		font-size: 13px;
		text-align: center;
		gap: 8px;
	}

	.kanban-empty-icon {
		font-size: 28px;
	}

	/* ================================================================= */
	/* Board layout — horizontal columns                                  */
	/* ================================================================= */
	.kanban-board {
		display: flex;
		flex: 1;
		gap: 8px;
		padding: 8px;
		overflow-x: auto;
		overflow-y: hidden;
		min-height: 0;
	}

	/* ================================================================= */
	/* Column                                                             */
	/* ================================================================= */
	.kanban-column {
		display: flex;
		flex-direction: column;
		flex: 1 1 0;
		min-width: 140px;
		max-width: 320px;
		background: var(--color-surface-hover);
		border-radius: 8px;
		overflow: hidden;
		transition: box-shadow 0.15s;
	}

	.kanban-column-dragover {
		box-shadow: inset 0 0 0 2px var(--color-accent);
	}

	.kanban-column-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 8px 10px;
		flex-shrink: 0;
	}

	.kanban-column-title {
		font-size: 12px;
		font-weight: 600;
		color: var(--color-text-muted);
		text-transform: uppercase;
		letter-spacing: 0.03em;
	}

	.kanban-column-count {
		font-size: 11px;
		color: var(--color-text-dim);
		background: var(--color-surface);
		border-radius: 9999px;
		padding: 0 6px;
		line-height: 18px;
	}

	.kanban-column-cards {
		display: flex;
		flex-direction: column;
		gap: 4px;
		padding: 0 6px 6px;
		flex: 1;
		overflow-y: auto;
		min-height: 24px;
	}

	/* ================================================================= */
	/* Card                                                               */
	/* ================================================================= */
	.kanban-card {
		background: var(--color-surface);
		border: 1px solid var(--color-border);
		border-radius: 6px;
		padding: 8px 10px;
		cursor: grab;
		transition: box-shadow 0.1s, opacity 0.15s;
	}

	.kanban-card:hover {
		box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
	}

	.kanban-card:active {
		cursor: grabbing;
	}

	.kanban-card-dragging {
		opacity: 0.4;
	}

	.kanban-card-title {
		display: block;
		font-size: 13px;
		font-weight: 500;
		color: var(--color-text);
		line-height: 1.3;
		word-break: break-word;
	}

	.kanban-card-content {
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
		font-size: 12px;
		color: var(--color-text-muted);
		margin-top: 3px;
		line-height: 1.3;
	}

	.kanban-card-time {
		display: block;
		font-size: 10px;
		color: var(--color-text-dim);
		margin-top: 4px;
	}

	/* ================================================================= */
	/* Add card form                                                      */
	/* ================================================================= */
	.kanban-add-trigger {
		display: block;
		width: 100%;
		padding: 6px 8px;
		border: none;
		background: transparent;
		font-size: 12px;
		color: var(--color-text-dim);
		text-align: left;
		cursor: pointer;
		border-radius: 4px;
		transition: background 0.1s, color 0.1s;
	}

	.kanban-add-trigger:hover {
		background: rgba(255, 255, 255, 0.6);
		color: var(--color-text-muted);
	}

	.kanban-add-form {
		background: var(--color-surface);
		border: 1px solid var(--color-accent);
		border-radius: 6px;
		padding: 6px;
	}

	.kanban-add-input {
		width: 100%;
		padding: 4px 6px;
		border: 1px solid var(--color-border);
		border-radius: 4px;
		font-size: 12px;
		outline: none;
		box-sizing: border-box;
	}

	.kanban-add-input:focus {
		border-color: var(--color-accent);
	}

	.kanban-add-actions {
		display: flex;
		gap: 4px;
		margin-top: 4px;
	}

	.kanban-add-btn {
		padding: 3px 8px;
		border: none;
		border-radius: 4px;
		font-size: 11px;
		font-weight: 500;
		background: var(--color-accent);
		color: white;
		cursor: pointer;
	}

	.kanban-add-btn:hover {
		background: var(--color-accent-hover);
	}

	.kanban-add-btn:disabled {
		opacity: 0.5;
		cursor: default;
	}

	.kanban-cancel-btn {
		padding: 3px 8px;
		border: none;
		border-radius: 4px;
		font-size: 11px;
		background: transparent;
		color: var(--color-text-muted);
		cursor: pointer;
	}

	.kanban-cancel-btn:hover {
		background: var(--color-surface-hover);
	}

	/* ================================================================= */
	/* Responsive within bounded container                                */
	/* ================================================================= */

	/* Small panels: stack columns vertically */
	@container (max-width: 400px) {
		.kanban-board {
			flex-direction: column;
			overflow-x: hidden;
			overflow-y: auto;
			gap: 6px;
			padding: 6px;
		}

		.kanban-column {
			max-width: none;
			min-width: 0;
		}

		.kanban-column-cards {
			max-height: 200px;
		}
	}

	/* Medium panels: tighter spacing */
	@container (max-width: 600px) {
		.kanban-card {
			padding: 6px 8px;
		}

		.kanban-card-title {
			font-size: 12px;
		}

		.kanban-column-header {
			padding: 6px 8px;
		}
	}

	/* Mobile viewport fallback */
	@media (max-width: 480px) {
		.kanban-board {
			flex-direction: column;
			overflow-x: hidden;
			overflow-y: auto;
			gap: 6px;
			padding: 6px;
		}

		.kanban-column {
			max-width: none;
			min-width: 0;
		}

		.kanban-column-cards {
			max-height: 250px;
		}
	}
</style>
