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

	// Canvas + BlockShell
	import Canvas from '$lib/components/canvas/Canvas.svelte';
	import type { CanvasObject } from '$lib/components/canvas/types.js';
	import BlockShell from '$lib/components/blockshell/BlockShell.svelte';

	// Workspace layout
	import {
		type PanelLayout,
		type WorkspaceLayout,
		getPanelInfo,
		generateDefaultLayout,
		resolveLayout,
		PANEL_HEADER_HEIGHT,
	} from '$lib/workspace/types.js';

	// Context header
	import ContextHeader from '$lib/components/ContextHeader.svelte';

	// Trait components
	import EditorTrait from '$lib/components/traits/EditorTrait.svelte';
	import ChatTrait from '$lib/components/traits/ChatTrait.svelte';
	import KanbanTrait from '$lib/components/traits/KanbanTrait.svelte';
	import PodcastTrait from '$lib/components/traits/PodcastTrait.svelte';
	import PublishingTrait from '$lib/components/traits/PublishingTrait.svelte';
	import RssTrait from '$lib/components/traits/RssTrait.svelte';
	import CalendarTrait from '$lib/components/traits/CalendarTrait.svelte';
	import RecordingTrait from '$lib/components/traits/RecordingTrait.svelte';
	import TranscriptionTrait from '$lib/components/traits/TranscriptionTrait.svelte';
	import StudioTrait from '$lib/components/traits/StudioTrait.svelte';
	import MixerTrait from '$lib/components/traits/MixerTrait.svelte';
	import OrchestrationTrait from '$lib/components/traits/OrchestrationTrait.svelte';
	import MindMapTrait from '$lib/components/traits/MindMapTrait.svelte';
	import StoryboardTrait from '$lib/components/traits/StoryboardTrait.svelte';
	import GenericTrait from '$lib/components/traits/GenericTrait.svelte';
	import TraitAdmin from '$lib/components/traits/TraitAdmin.svelte';

	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);
	let showTraitAdmin = $state(false);
	const connected = $derived(connectionState.current === 'connected');
	const collectionId = $derived($page.params.id ?? '');

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

	/** Parse full metadata */
	const parsedMetadata = $derived.by((): Record<string, unknown> => {
		if (!collectionNode) return {};
		try {
			return JSON.parse(collectionNode.metadata ?? '{}') as Record<string, unknown>;
		} catch { return {}; }
	});

	/** Parse traits from collection metadata */
	const traits = $derived.by((): Record<string, Record<string, unknown>> => {
		const meta = parsedMetadata;
		if (meta.traits && typeof meta.traits === 'object' && !Array.isArray(meta.traits)) {
			return meta.traits as Record<string, Record<string, unknown>>;
		}
		return {};
	});

	const traitNames = $derived(Object.keys(traits));

	/** Traits with dedicated components */
	const knownTraits = new Set([
		'editor', 'chat', 'kanban', 'podcast', 'publishing',
		'rss', 'calendar', 'recording', 'transcription', 'studio', 'mixer', 'orchestration', 'mindmap', 'storyboard'
	]);

	/** Count of child nodes */
	const childCount = $derived.by(() => {
		if (!connected || !collectionId) return 0;
		let count = 0;
		for (const edge of edgeStore.byTarget(collectionId)) {
			if (edge.edgeType === 'belongs_to') count++;
		}
		return count;
	});

	// =========================================================================
	// Workspace layout state
	// =========================================================================

	/** Find the user's edge to this collection (owner or member_of) */
	const userEdge = $derived.by(() => {
		if (!connected || !nodeId || !collectionId) return undefined;
		for (const edge of edgeStore.bySource(nodeId)) {
			if (
				(edge.edgeType === 'owner' || edge.edgeType === 'member_of') &&
				edge.targetId === collectionId
			) {
				return edge;
			}
		}
		return undefined;
	});

	/** Parse saved layout from user's edge metadata */
	const savedLayout = $derived.by((): WorkspaceLayout | null => {
		if (!userEdge) return null;
		try {
			const meta = JSON.parse(userEdge.metadata ?? '{}');
			if (meta.workspace_layout && Array.isArray(meta.workspace_layout.panels)) {
				return meta.workspace_layout as WorkspaceLayout;
			}
		} catch { /* ignore */ }
		return null;
	});

	/** Resolved layout using three-layer model */
	let layout = $state<WorkspaceLayout>({ panels: [] });
	let layoutInitialized = $state(false);

	// Initialize layout when traits and saved layout become available
	$effect(() => {
		if (traitNames.length === 0) return;
		// Only initialize once per collection — user moves update layout directly
		if (!layoutInitialized) {
			layout = resolveLayout(traitNames, savedLayout);
			layoutInitialized = true;
		}
	});

	let saveTimeout: ReturnType<typeof setTimeout> | undefined;

	// Reset when collection changes
	$effect(() => {
		const _id = collectionId;
		layoutInitialized = false;
		clearTimeout(saveTimeout);
	});

	/** Convert layout panels to CanvasObjects for the Canvas component */
	const canvasObjects = $derived<CanvasObject[]>(
		layout.panels.map(p => ({
			id: p.trait,
			x: p.x,
			y: p.y,
			width: p.width,
			height: p.minimized ? PANEL_HEADER_HEIGHT : p.height,
		}))
	);

	// =========================================================================
	// Layout persistence
	// =========================================================================

	/** Persist layout to user's edge metadata (debounced) */
	function persistLayout() {
		if (!accessToken || !userEdge) return;
		clearTimeout(saveTimeout);
		saveTimeout = setTimeout(async () => {
			try {
				const existingMeta = JSON.parse(userEdge!.metadata ?? '{}');
				await updateEdge(accessToken!, {
					edge_id: userEdge!.id,
					metadata: {
						...existingMeta,
						workspace_layout: layout,
					},
				});
			} catch (err) {
				console.warn('Failed to persist workspace layout:', err);
			}
		}, 1000);
	}

	/** Handle panel move on canvas */
	function handleObjectMove(id: string, x: number, y: number) {
		const idx = layout.panels.findIndex(p => p.trait === id);
		if (idx >= 0) {
			layout.panels[idx] = { ...layout.panels[idx], x, y };
			layout = { ...layout };
			persistLayout();
		}
	}

	/** Handle panel resize via BlockShell */
	function handlePanelResize(trait: string, width: number, height: number, dx?: number, dy?: number) {
		const idx = layout.panels.findIndex(p => p.trait === trait);
		if (idx >= 0) {
			const panel = layout.panels[idx];
			layout.panels[idx] = {
				...panel,
				width,
				height,
				x: panel.x + (dx ?? 0),
				y: panel.y + (dy ?? 0),
			};
			layout = { ...layout };
			persistLayout();
		}
	}

	/** Handle panel close */
	function handlePanelClose(trait: string) {
		layout = {
			panels: layout.panels.filter(p => p.trait !== trait),
		};
		persistLayout();
	}

	/** Handle panel minimize/restore toggle */
	function handlePanelMinimize(trait: string, isMinimized: boolean) {
		const idx = layout.panels.findIndex(p => p.trait === trait);
		if (idx >= 0) {
			layout.panels[idx] = { ...layout.panels[idx], minimized: isMinimized };
			layout = { ...layout };
			persistLayout();
		}
	}

	/** Handle adding a new panel from the tool menu */
	function handleAddPanel(trait: string) {
		// Don't add duplicate panels
		if (layout.panels.some(p => p.trait === trait)) return;

		const info = getPanelInfo(trait);
		// Place below existing panels
		const maxY = layout.panels.length > 0
			? Math.max(...layout.panels.map(p => p.y + p.height))
			: 0;

		layout = {
			panels: [
				...layout.panels,
				{
					trait,
					x: 30,
					y: maxY + 30,
					width: info.defaultWidth,
					height: info.defaultHeight,
				},
			],
		};
		persistLayout();
	}

	/** Active trait keys in the current layout (for tool menu) */
	const activeLayoutTraits = $derived(layout.panels.map(p => p.trait));

	// =========================================================================
	// Mobile detection + tab state
	// =========================================================================

	let windowWidth = $state(typeof window !== 'undefined' ? window.innerWidth : 1024);
	const isMobile = $derived(windowWidth < 768);
	let activeTab = $state(0);

	$effect(() => {
		function onResize() { windowWidth = window.innerWidth; }
		window.addEventListener('resize', onResize);
		return () => window.removeEventListener('resize', onResize);
	});

	// Clamp active tab when panels change
	$effect(() => {
		if (activeTab >= traitNames.length && traitNames.length > 0) {
			activeTab = 0;
		}
	});
</script>

<div class="workspace-page">
	<!-- Context Header: context selector + tool menu -->
	<ContextHeader
		{collectionId}
		{collectionNode}
		userId={nodeId}
		{connected}
		{traitNames}
		onToggleTraitAdmin={() => { showTraitAdmin = !showTraitAdmin; }}
		{showTraitAdmin}
		onAddPanel={handleAddPanel}
		activeTraits={activeLayoutTraits}
	/>

	<!-- Trait admin panel (overlay) -->
	{#if showTraitAdmin && accessToken}
		<div class="workspace-admin-overlay">
			<TraitAdmin
				{accessToken}
				collectionId={collectionId}
				{traits}
				metadata={parsedMetadata}
				onclose={() => { showTraitAdmin = false; }}
			/>
		</div>
	{/if}

	<!-- Main content area -->
	{#if !connected}
		<div class="workspace-message">
			<p>Venter på tilkobling…</p>
		</div>
	{:else if !collectionNode}
		<div class="workspace-message workspace-message-warn">
			<p class="workspace-message-title">Samling ikke funnet</p>
			<p>Samlingsnoden med ID {collectionId} finnes ikke eller er ikke tilgjengelig.</p>
			<a href="/" class="workspace-link">Tilbake til arbeidsflaten</a>
		</div>
	{:else if traitNames.length === 0}
		<div class="workspace-message">
			<p>Denne samlingen har ingen aktive traits.</p>
			<p class="workspace-message-sub">Traits bestemmer hvilke verktøy og visninger som er tilgjengelige.</p>
			{#if accessToken && !showTraitAdmin}
				<button
					onclick={() => { showTraitAdmin = true; }}
					class="workspace-btn-primary"
				>
					Legg til traits
				</button>
			{/if}
		</div>
	{:else if isMobile}
		<!-- ============================================================= -->
		<!-- MOBILE: Stacked with tab navigation                           -->
		<!-- ============================================================= -->
		<div class="mobile-tabs">
			{#each traitNames as trait, i (trait)}
				<button
					class="mobile-tab {activeTab === i ? 'mobile-tab-active' : ''}"
					onclick={() => { activeTab = i; }}
				>
					{getPanelInfo(trait).icon}
					<span class="mobile-tab-label">{getPanelInfo(trait).title}</span>
				</button>
			{/each}
		</div>

		<div class="mobile-panel">
			{#each traitNames as trait, i (trait)}
				{#if activeTab === i}
					<div class="mobile-panel-content">
						{#if knownTraits.has(trait)}
							{#if trait === 'editor'}
								<EditorTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} collectionMetadata={parsedMetadata} />
							{:else if trait === 'chat'}
								<ChatTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'kanban'}
								<KanbanTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'podcast'}
								<PodcastTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'publishing'}
								<PublishingTrait collection={collectionNode} config={traits[trait]} />
							{:else if trait === 'rss'}
								<RssTrait collection={collectionNode} config={traits[trait]} />
							{:else if trait === 'calendar'}
								<CalendarTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'recording'}
								<RecordingTrait collection={collectionNode} config={traits[trait]} {accessToken} />
							{:else if trait === 'transcription'}
								<TranscriptionTrait collection={collectionNode} config={traits[trait]} />
							{:else if trait === 'studio'}
								<StudioTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'mixer'}
								<MixerTrait collection={collectionNode} config={traits[trait]} {accessToken} />
							{:else if trait === 'orchestration'}
								<OrchestrationTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'mindmap'}
								<MindMapTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'storyboard'}
								<StoryboardTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{/if}
						{:else}
							<GenericTrait name={trait} config={traits[trait]} />
						{/if}
					</div>
				{/if}
			{/each}
		</div>
	{:else}
		<!-- ============================================================= -->
		<!-- DESKTOP: Spatial Canvas with BlockShell panels                 -->
		<!-- ============================================================= -->
		<div class="workspace-canvas">
			<Canvas
				objects={canvasObjects}
				onObjectMove={handleObjectMove}
				grid={{ enabled: false, size: 20 }}
			>
				{#snippet renderObject(obj)}
					{@const trait = obj.id}
					{@const info = getPanelInfo(trait)}
					{@const panel = layout.panels.find(p => p.trait === trait)}
					<BlockShell
						title={info.title}
						icon={info.icon}
						width={panel?.width ?? obj.width}
						height={panel?.height ?? obj.height}
						minimized={panel?.minimized ?? false}
						onResize={(w, h, dx, dy) => handlePanelResize(trait, w, h, dx, dy)}
						onClose={() => handlePanelClose(trait)}
						onMinimizeChange={(m) => handlePanelMinimize(trait, m)}
					>
						{#if knownTraits.has(trait)}
							{#if trait === 'editor'}
								<EditorTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} collectionMetadata={parsedMetadata} />
							{:else if trait === 'chat'}
								<ChatTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'kanban'}
								<KanbanTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'podcast'}
								<PodcastTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'publishing'}
								<PublishingTrait collection={collectionNode} config={traits[trait]} />
							{:else if trait === 'rss'}
								<RssTrait collection={collectionNode} config={traits[trait]} />
							{:else if trait === 'calendar'}
								<CalendarTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'recording'}
								<RecordingTrait collection={collectionNode} config={traits[trait]} {accessToken} />
							{:else if trait === 'transcription'}
								<TranscriptionTrait collection={collectionNode} config={traits[trait]} />
							{:else if trait === 'studio'}
								<StudioTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'mixer'}
								<MixerTrait collection={collectionNode} config={traits[trait]} {accessToken} />
							{:else if trait === 'orchestration'}
								<OrchestrationTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'mindmap'}
								<MindMapTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{:else if trait === 'storyboard'}
								<StoryboardTrait collection={collectionNode} config={traits[trait]} userId={nodeId} {accessToken} />
							{/if}
						{:else}
							<GenericTrait name={trait} config={traits[trait]} />
						{/if}
					</BlockShell>
				{/snippet}
			</Canvas>
		</div>
	{/if}

</div>

<style>
	/* ================================================================= */
	/* Page layout                                                       */
	/* ================================================================= */
	.workspace-page {
		display: flex;
		flex-direction: column;
		height: 100vh;
		background: #0a0a0b;
	}

	.workspace-btn-primary {
		margin-top: 12px;
		padding: 8px 16px;
		border: none;
		border-radius: 8px;
		font-size: 14px;
		font-weight: 500;
		cursor: pointer;
		background: #4f46e5;
		color: white;
	}

	.workspace-btn-primary:hover {
		background: #4338ca;
	}

	/* ================================================================= */
	/* Trait admin overlay                                                */
	/* ================================================================= */
	.workspace-admin-overlay {
		position: relative;
		z-index: 25;
		padding: 12px 16px;
		background: #141416;
		border-bottom: 1px solid #2a2a2e;
	}

	/* ================================================================= */
	/* Messages (loading, not found, empty)                              */
	/* ================================================================= */
	.workspace-message {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		flex: 1;
		padding: 24px;
		text-align: center;
		font-size: 14px;
		color: #8a8a96;
	}

	.workspace-message-warn {
		color: #92400e;
		background: #fffbeb;
	}

	.workspace-message-title {
		font-weight: 600;
		margin-bottom: 4px;
	}

	.workspace-message-sub {
		font-size: 12px;
		color: #5a5a66;
		margin-top: 4px;
	}

	.workspace-link {
		margin-top: 8px;
		color: #2563eb;
		text-decoration: none;
	}

	.workspace-link:hover {
		text-decoration: underline;
	}

	/* ================================================================= */
	/* Desktop: Canvas fills remaining space                             */
	/* ================================================================= */
	.workspace-canvas {
		flex: 1;
		min-height: 0;
	}

	/* ================================================================= */
	/* Mobile: Tab navigation                                            */
	/* ================================================================= */
	.mobile-tabs {
		display: flex;
		overflow-x: auto;
		gap: 0;
		background: #1c1c20;
		border-bottom: 1px solid #2a2a2e;
		flex-shrink: 0;
		-webkit-overflow-scrolling: touch;
	}

	.mobile-tab {
		display: flex;
		align-items: center;
		gap: 4px;
		padding: 10px 14px;
		border: none;
		background: transparent;
		font-size: 13px;
		color: #8a8a96;
		cursor: pointer;
		white-space: nowrap;
		border-bottom: 2px solid transparent;
		transition: color 0.12s, border-color 0.12s;
	}

	.mobile-tab:hover {
		color: #8a8a96;
	}

	.mobile-tab-active {
		color: #4f46e5;
		border-bottom-color: #4f46e5;
		font-weight: 500;
	}

	.mobile-tab-label {
		font-size: 12px;
	}

	.mobile-panel {
		flex: 1;
		overflow: auto;
		min-height: 0;
	}

	.mobile-panel-content {
		min-height: 100%;
	}

	/* ================================================================= */
	/* Responsive                                                        */
	/* ================================================================= */
	@media (max-width: 768px) {
		.workspace-page { height: auto; }
	}
</style>
