<script lang="ts">
	import type { Node } from '$lib/realtime';
	import { edgeStore, nodeStore, nodeVisibility } from '$lib/realtime';
	import { setDragPayload, checkStudioCompat, 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 Studio (Lydstudio).
	 * Only accepts audio files — opens them in the studio.
	 * Ref: docs/retninger/arbeidsflaten.md § Kompatibilitetsmatrise
	 */
	export const receiver: BlockReceiver = {
		canReceive(payload: DragPayload) {
			return checkStudioCompat(payload);
		},
		receive(payload: DragPayload) {
			const intent: PlacementIntent = {
				mode: 'lettvekts-triage',
				contextId: collection?.id ?? '',
				contextType: 'studio',
			};
			onReceiveDrop?.(payload, intent);
			return intent;
		}
	};

	// =========================================================================
	// Audio nodes belonging to this collection
	// =========================================================================

	const audioNodes = $derived.by(() => {
		const nodes: Node[] = [];
		if (!collection) return nodes;
		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;
			if (node.nodeKind === 'media') {
				try {
					const meta = JSON.parse(node.metadata ?? '{}');
					if (typeof meta.mime === 'string' && meta.mime.startsWith('audio/')) {
						nodes.push(node);
					}
				} catch { /* skip */ }
			}
		}
		nodes.sort((a, b) => {
			const ta = a.createdAt ?? 0;
			const tb = b.createdAt ?? 0;
			return tb > ta ? 1 : tb < ta ? -1 : 0;
		});
		return nodes;
	});

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

	/** Check if a node has processed versions (derived_from edges) */
	function hasVersions(nodeId: string): boolean {
		for (const edge of edgeStore.byTarget(nodeId)) {
			if (edge.edgeType === 'derived_from') return true;
		}
		return false;
	}

	/** Get version count for a node */
	function versionCount(nodeId: string): number {
		let count = 0;
		for (const edge of edgeStore.byTarget(nodeId)) {
			if (edge.edgeType === 'derived_from') count++;
		}
		return count;
	}

	/** Format duration from metadata (seconds → mm:ss) */
	function formatDuration(node: Node): string {
		try {
			const meta = JSON.parse(node.metadata ?? '{}');
			if (typeof meta.duration === 'number') {
				const m = Math.floor(meta.duration / 60);
				const s = Math.floor(meta.duration % 60);
				return `${m}:${String(s).padStart(2, '0')}`;
			}
		} catch { /* skip */ }
		return '';
	}

	/** Format file size from metadata */
	function formatSize(node: Node): string {
		try {
			const meta = JSON.parse(node.metadata ?? '{}');
			if (typeof meta.size === 'number') {
				const kb = meta.size / 1024;
				if (kb < 1024) return `${Math.round(kb)} KB`;
				return `${(kb / 1024).toFixed(1)} MB`;
			}
		} catch { /* skip */ }
		return '';
	}

	/** Get MIME subtype (e.g. 'wav' from 'audio/wav') */
	function formatType(node: Node): string {
		try {
			const meta = JSON.parse(node.metadata ?? '{}');
			if (typeof meta.mime === 'string') {
				return meta.mime.replace('audio/', '').toUpperCase();
			}
		} catch { /* skip */ }
		return '';
	}

	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' });
	}

	// =========================================================================
	// Drag-and-drop: audio items as drag source
	// =========================================================================

	function handleDragStart(e: DragEvent, node: Node) {
		if (!e.dataTransfer) return;
		setDragPayload(e.dataTransfer, {
			nodeId: node.id,
			nodeKind: node.nodeKind,
			sourcePanel: 'studio'
		});
	}
</script>

<!--
	StudioTrait — fullverdig BlockShell-panel for lydstudio.
	Viser lydfiler med metadata, drag-and-drop ut til andre paneler,
	drop-aksept for lydfiler fra andre paneler, og lenke til studioet.
	Forelder (collection page) wrapper dette i BlockShell.
-->

<div class="studio-trait">
	{#if audioNodes.length === 0}
		<div class="studio-empty">
			<span class="studio-empty-icon">🎙️</span>
			<p>Ingen lydfiler i denne samlingen.</p>
			<p class="studio-empty-hint">Dra lydfiler hit fra andre paneler, eller last opp via studio.</p>
		</div>
	{:else}
		<div class="studio-header">
			<span class="studio-header-label">Lydfiler</span>
			<span class="studio-header-count">{audioNodes.length}</span>
		</div>

		<div class="studio-items">
			{#each audioNodes as node (node.id)}
				{@const duration = formatDuration(node)}
				{@const size = formatSize(node)}
				{@const type = formatType(node)}
				{@const versions = versionCount(node.id)}
				{@const date = formatTime(node)}
				<!-- svelte-ignore a11y_no_static_element_interactions -->
				<div
					class="studio-item"
					draggable="true"
					ondragstart={(e) => handleDragStart(e, node)}
				>
					<div class="studio-item-main">
						<div class="studio-item-icon">🎵</div>
						<div class="studio-item-text">
							<span class="studio-item-title">{node.title ?? 'Uten tittel'}</span>
							<div class="studio-item-meta">
								{#if type}
									<span class="studio-item-tag">{type}</span>
								{/if}
								{#if duration}
									<span class="studio-item-duration">{duration}</span>
								{/if}
								{#if size}
									<span class="studio-item-size">{size}</span>
								{/if}
								{#if date}
									<span class="studio-item-date">{date}</span>
								{/if}
							</div>
						</div>
						<div class="studio-item-actions">
							{#if versions > 0}
								<span class="studio-item-versions" title="{versions} prosesserte versjon(er)">
									{versions} ver.
								</span>
							{/if}
							<a
								href="/studio/{node.id}"
								class="studio-edit-btn"
								title="Åpne i lydstudio"
								onclick={(e) => e.stopPropagation()}
							>
								Rediger
							</a>
						</div>
					</div>
				</div>
			{/each}
		</div>
	{/if}
</div>

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

	/* ================================================================= */
	/* Empty state                                                        */
	/* ================================================================= */
	.studio-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: 4px;
	}

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

	.studio-empty-hint {
		font-size: 11px;
		color: var(--color-text-muted);
		margin-top: 4px;
	}

	/* ================================================================= */
	/* Header                                                             */
	/* ================================================================= */
	.studio-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 8px 12px;
		flex-shrink: 0;
		border-bottom: 1px solid var(--color-border);
	}

	.studio-header-label {
		font-size: 11px;
		color: var(--color-text-dim);
		text-transform: uppercase;
		letter-spacing: 0.03em;
	}

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

	/* ================================================================= */
	/* Items list                                                         */
	/* ================================================================= */
	.studio-items {
		flex: 1;
		overflow-y: auto;
		padding: 6px;
		display: flex;
		flex-direction: column;
		gap: 4px;
		min-height: 0;
	}

	.studio-item {
		background: var(--color-surface);
		border: 1px solid var(--color-border);
		border-radius: 6px;
		padding: 8px 10px;
		cursor: grab;
		transition: box-shadow 0.1s, border-color 0.15s;
	}

	.studio-item:hover {
		box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
		border-color: var(--color-text-muted);
	}

	.studio-item:active {
		cursor: grabbing;
	}

	.studio-item-main {
		display: flex;
		align-items: center;
		gap: 8px;
	}

	.studio-item-icon {
		font-size: 16px;
		flex-shrink: 0;
		line-height: 1;
	}

	.studio-item-text {
		flex: 1;
		min-width: 0;
		display: flex;
		flex-direction: column;
		gap: 2px;
	}

	.studio-item-title {
		font-size: 13px;
		font-weight: 500;
		color: var(--color-text);
		line-height: 1.3;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.studio-item-meta {
		display: flex;
		align-items: center;
		gap: 6px;
		flex-wrap: wrap;
	}

	.studio-item-tag {
		font-size: 9px;
		font-weight: 600;
		color: var(--color-accent);
		background: var(--color-surface-hover);
		border-radius: 3px;
		padding: 0 4px;
		line-height: 16px;
	}

	.studio-item-duration {
		font-size: 11px;
		color: var(--color-text-muted);
		font-variant-numeric: tabular-nums;
	}

	.studio-item-size {
		font-size: 10px;
		color: var(--color-text-dim);
	}

	.studio-item-date {
		font-size: 10px;
		color: var(--color-text-dim);
	}

	.studio-item-actions {
		display: flex;
		align-items: center;
		gap: 6px;
		flex-shrink: 0;
	}

	.studio-item-versions {
		font-size: 10px;
		color: var(--color-success);
		white-space: nowrap;
	}

	.studio-edit-btn {
		padding: 4px 10px;
		border-radius: 4px;
		font-size: 11px;
		font-weight: 500;
		background: var(--color-surface-hover);
		color: var(--color-accent);
		text-decoration: none;
		transition: background 0.1s;
		white-space: nowrap;
	}

	.studio-edit-btn:hover {
		background: var(--color-surface-hover);
	}

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

	/* Small panels: compact layout */
	@container (max-width: 360px) {
		.studio-header {
			padding: 6px 8px;
		}

		.studio-items {
			padding: 4px;
		}

		.studio-item {
			padding: 6px 8px;
		}

		.studio-item-icon {
			display: none;
		}

		.studio-item-title {
			font-size: 12px;
		}

		.studio-item-meta {
			gap: 4px;
		}

		.studio-item-versions {
			display: none;
		}

		.studio-edit-btn {
			padding: 3px 8px;
			font-size: 10px;
		}

		.studio-empty {
			padding: 16px;
			font-size: 12px;
		}

		.studio-empty-icon {
			font-size: 22px;
		}
	}

	/* Medium panels: slightly tighter */
	@container (max-width: 500px) {
		.studio-item-size {
			display: none;
		}

		.studio-item-date {
			display: none;
		}
	}

	/* Mobile viewport fallback */
	@media (max-width: 480px) {
		.studio-header {
			padding: 6px 8px;
		}

		.studio-items {
			padding: 4px;
		}

		.studio-item {
			padding: 6px 8px;
		}

		.studio-item-icon {
			display: none;
		}

		.studio-item-title {
			font-size: 12px;
		}

		.studio-item-size {
			display: none;
		}

		.studio-empty {
			padding: 16px;
		}
	}
</style>
