<script lang="ts">
	import { page } from '$app/stores';
	import { connectionState, nodeStore, edgeStore, nodeAccessStore, nodeVisibility } from '$lib/realtime';
	import type { Node } from '$lib/realtime';
	import { fetchMyWorkspace, updateNode } from '$lib/api';
	import ContextHeader from '$lib/components/ContextHeader.svelte';
	import {
		type ThemeConfig,
		DEFAULT_THEME,
		applyTheme,
		loadThemeFromMetadata,
		themeToMetadata,
	} from '$lib/workspace/theme.js';

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

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

	// Trait components (reuse from collection page)
	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 MindMapTrait from '$lib/components/traits/MindMapTrait.svelte';
	import GenericTrait from '$lib/components/traits/GenericTrait.svelte';
	import AiToolPanel from '$lib/components/AiToolPanel.svelte';
	import NodeUsage from '$lib/components/NodeUsage.svelte';

	import { createBlockReceiver, executeTransfer, resolveTransferMode, type DragPayload } from '$lib/transfer';
	import type { BlockReceiver } from '$lib/components/blockshell/types';

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

	// =========================================================================
	// Workspace node (fetched from backend)
	// =========================================================================

	let workspaceNodeId = $state<string | undefined>(undefined);
	let workspaceLoading = $state(true);
	let workspaceError = $state<string | undefined>(undefined);

	// Fetch or create workspace on load
	$effect(() => {
		if (!accessToken) return;
		workspaceLoading = true;
		fetchMyWorkspace(accessToken)
			.then((res) => {
				workspaceNodeId = res.node_id;
				// Initialize layout from backend metadata if we don't have one yet
				if (!layoutInitialized && res.metadata?.workspace_layout) {
					const saved = res.metadata.workspace_layout as WorkspaceLayout;
					if (saved.panels && Array.isArray(saved.panels) && saved.panels.length > 0) {
						layout = saved;
					}
					layoutInitialized = true;
				} else if (!layoutInitialized) {
					layoutInitialized = true;
				}
				// Load preferences
				if (res.metadata) {
					loadThemeFromMeta(res.metadata as Record<string, unknown>);
					const meta = res.metadata as Record<string, unknown>;
					const cam = meta.camera as Camera | undefined;
					if (cam && typeof cam.x === 'number') {
						savedCamera = cam;
					}
					if (typeof meta.gridEnabled === 'boolean') {
						gridEnabled = meta.gridEnabled;
					}
					if (Array.isArray(meta.savedThemes)) {
						savedThemes = meta.savedThemes as ThemeConfig[];
					}
					if (meta.panelSizes && typeof meta.panelSizes === 'object') {
						panelSizes = meta.panelSizes as Record<string, { width: number; height: number }>;
					}
				}
			})
			.catch((err) => {
				workspaceError = err.message;
			})
			.finally(() => {
				workspaceLoading = false;
			});
	});

	// Also try to read layout from WS node store (for real-time sync)
	const workspaceNode = $derived(
		workspaceNodeId && connected ? nodeStore.get(workspaceNodeId) : undefined
	);

	// =========================================================================
	// Layout state
	// =========================================================================

	let layout = $state<WorkspaceLayout>({ panels: [] });
	let layoutInitialized = $state(false);
	let savedCamera = $state<Camera>({ x: 0, y: 0, zoom: 1.0 });
	let gridEnabled = $state(false);
	let savedThemes = $state<ThemeConfig[]>([]);
	let panelSizes = $state<Record<string, { width: number; height: number }>>({});

	// When workspace node appears in store (after creation), load its layout
	$effect(() => {
		if (!workspaceNode || layoutInitialized) return;
		try {
			const meta = JSON.parse(workspaceNode.metadata ?? '{}');
			if (meta.workspace_layout?.panels?.length > 0) {
				layout = meta.workspace_layout as WorkspaceLayout;
			}
		} catch { /* ignore */ }
		layoutInitialized = true;
	});

	/** Convert layout panels to CanvasObjects */
	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 (debounced save to workspace node metadata)
	// =========================================================================

	let saveTimeout: ReturnType<typeof setTimeout> | undefined;

	/** Persist all workspace metadata (layout + preferences) */
	function persistMetadata() {
		if (!accessToken || !workspaceNodeId) return;
		clearTimeout(saveTimeout);
		saveTimeout = setTimeout(async () => {
			try {
				const currentMeta = workspaceNode
					? JSON.parse(workspaceNode.metadata ?? '{}')
					: {};
				await updateNode(accessToken!, {
					node_id: workspaceNodeId!,
					metadata: {
						...currentMeta,
						workspace_layout: layout,
						camera: savedCamera,
						gridEnabled,
						savedThemes,
						panelSizes,
						preferences: {
							...(currentMeta.preferences ?? {}),
							theme: themeToMetadata(currentTheme),
						},
					},
				});
			} catch (err) {
				console.warn('Failed to persist workspace metadata:', err);
			}
		}, 1000);
	}

	// Keep old name as alias for callers
	function persistLayout() { persistMetadata(); }

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

	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 };
			// Remember size per trait type
			panelSizes = { ...panelSizes, [trait]: { width, height } };
			persistLayout();
		}
	}

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

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

	function handleAddPanel(trait: string) {
		if (layout.panels.some(p => p.trait === trait)) return;
		const info = getPanelInfo(trait);
		const remembered = panelSizes[trait];
		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: remembered?.width ?? info.defaultWidth,
					height: remembered?.height ?? info.defaultHeight,
				},
			],
		};
		persistLayout();
	}

	const activeLayoutTraits = $derived(layout.panels.map(p => p.trait));

	// =========================================================================
	// Theme
	// =========================================================================

	let currentTheme = $state<ThemeConfig>(DEFAULT_THEME);

	function handleThemeChange(newTheme: ThemeConfig) {
		currentTheme = newTheme;
		persistMetadata();
	}

	function handleSavedThemesChange(themes: ThemeConfig[]) {
		savedThemes = themes;
		persistMetadata();
	}

	function loadThemeFromMeta(meta: Record<string, unknown>) {
		const loaded = loadThemeFromMetadata(meta);
		if (loaded) {
			currentTheme = loaded;
			applyTheme(loaded);
		}
	}

	// =========================================================================
	// Mobile detection
	// =========================================================================

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

	$effect(() => {
		if (activeTab >= layout.panels.length && layout.panels.length > 0) {
			activeTab = 0;
		}
	});

	// =========================================================================
	// Click outside
	// =========================================================================

	/** Trait components that have dedicated implementations */
	const knownTraits = new Set([
		'editor', 'chat', 'kanban', 'podcast', 'publishing',
		'rss', 'calendar', 'recording', 'transcription', 'studio', 'mixer', 'mindmap',
		'ai', 'usage'
	]);

	// =========================================================================
	// BlockReceiver per tool type — wired into BlockShell for drop compatibility
	// Ref: docs/features/universell_overfoering.md § 4
	// =========================================================================

	/** Traits that support BlockReceiver drops */
	const RECEIVER_TRAITS = new Set(['editor', 'chat', 'kanban', 'calendar', 'studio']);

	/** Cache receivers by trait name — one per type */
	const receiverCache = new Map<string, BlockReceiver>();

	function getReceiverForTrait(trait: string): BlockReceiver | undefined {
		if (!RECEIVER_TRAITS.has(trait)) return undefined;
		if (!receiverCache.has(trait)) {
			const toolType = trait as import('$lib/transfer').ToolType;
			receiverCache.set(trait, createBlockReceiver(toolType));
		}
		return receiverCache.get(trait);
	}

	function handlePanelDrop(trait: string, payload: DragPayload, shiftKey: boolean = false) {
		const receiver = getReceiverForTrait(trait);
		if (!receiver?.receive) {
			console.warn(`[universell-overføring] Ingen mottaker for ${trait}`);
			return;
		}

		const intent = receiver.receive(payload);
		const mode = resolveTransferMode(
			payload.sourcePanel,
			trait as import('$lib/transfer').ToolType,
			shiftKey,
		);
		// Override intent mode with centrally resolved mode
		intent.mode = mode;

		if (!accessToken) {
			console.error('[universell-overføring] Mangler accessToken — kan ikke utføre overføring');
			return;
		}

		console.log(`[universell-overføring] ${payload.sourcePanel} → ${trait} (${mode}${shiftKey ? ', shift' : ''}):`, intent);

		executeTransfer(accessToken, payload, intent, shiftKey)
			.then((result) => {
				console.log(`[universell-overføring] Fullført:`, result);
			})
			.catch((err) => {
				console.error(`[universell-overføring] Feil:`, err);
			});
	}
</script>

<div class="workspace-page">
	<ContextHeader
		userId={nodeId}
		accessToken={accessToken}
		{connected}
		onAddPanel={handleAddPanel}
		activeTraits={activeLayoutTraits}
		theme={currentTheme}
		onThemeChange={handleThemeChange}
		{savedThemes}
		onSavedThemesChange={handleSavedThemesChange}
	/>

	<!-- Main content -->
	{#if workspaceLoading}
		<div class="workspace-message">
			<p>Laster arbeidsflate...</p>
		</div>
	{:else if workspaceError}
		<div class="workspace-message workspace-message-warn">
			<p class="workspace-message-title">Kunne ikke laste arbeidsflate</p>
			<p>{workspaceError}</p>
		</div>
	{:else if !connected}
		<div class="workspace-message">
			<p>Venter på tilkobling...</p>
		</div>
	{:else if layout.panels.length === 0}
		<div class="workspace-empty">
			<div class="workspace-empty-inner">
				<p class="workspace-empty-title">Din personlige arbeidsflate</p>
				<p class="workspace-empty-desc">
					Legg til verktøy-paneler for å bygge opp arbeidsflaten din.
					Arrangementet huskes mellom besøk.
				</p>
				<div class="workspace-empty-tools">
					{#each Object.entries(TRAIT_PANEL_INFO) as [key, info] (key)}
						<button
							class="workspace-empty-tool"
							onclick={() => handleAddPanel(key)}
						>
							<span class="workspace-empty-tool-icon">{info.icon}</span>
							<span class="workspace-empty-tool-label">{info.title}</span>
						</button>
					{/each}
				</div>
			</div>
		</div>
	{:else if isMobile}
		<!-- MOBILE: Stacked tabs -->
		<div class="mobile-tabs">
			{#each layout.panels as panel, i (panel.trait)}
				<button
					class="mobile-tab {activeTab === i ? 'mobile-tab-active' : ''}"
					onclick={() => { activeTab = i; }}
				>
					{getPanelInfo(panel.trait).icon}
					<span class="mobile-tab-label">{getPanelInfo(panel.trait).title}</span>
				</button>
			{/each}
		</div>

		<div class="mobile-panel">
			{#each layout.panels as panel, i (panel.trait)}
				{#if activeTab === i}
					<div class="mobile-panel-content">
						{#if knownTraits.has(panel.trait)}
							{#if panel.trait === 'editor'}
								<EditorTrait collection={undefined} config={{}} userId={nodeId} {accessToken} collectionMetadata={{}} />
							{:else if panel.trait === 'chat'}
								<ChatTrait collection={undefined} config={{}} userId={nodeId} {accessToken} />
							{:else if panel.trait === 'kanban'}
								<KanbanTrait collection={undefined} config={{}} userId={nodeId} />
							{:else if panel.trait === 'calendar'}
								<CalendarTrait collection={undefined} config={{}} userId={nodeId} />
							{:else if panel.trait === 'podcast'}
								<PodcastTrait collection={undefined} config={{}} userId={nodeId} {accessToken} />
							{:else if panel.trait === 'publishing'}
								<PublishingTrait collection={undefined} config={{}} />
							{:else if panel.trait === 'rss'}
								<RssTrait collection={undefined} config={{}} />
							{:else if panel.trait === 'recording'}
								<RecordingTrait collection={undefined} config={{}} {accessToken} />
							{:else if panel.trait === 'transcription'}
								<TranscriptionTrait collection={undefined} config={{}} />
							{:else if panel.trait === 'studio'}
								<StudioTrait collection={undefined} config={{}} userId={nodeId} />
							{:else if panel.trait === 'mixer'}
								<MixerTrait collection={undefined} config={{}} {accessToken} />
							{:else if panel.trait === 'mindmap'}
								<MindMapTrait collection={undefined} config={{}} userId={nodeId} {accessToken} />
							{:else if panel.trait === 'ai'}
								<AiToolPanel {accessToken} userId={nodeId} />
							{:else if panel.trait === 'usage'}
								{#if nodeId && accessToken}
									<NodeUsage nodeId={nodeId} {accessToken} />
								{/if}
							{/if}
						{:else}
							<GenericTrait name={panel.trait} config={{}} />
						{/if}
					</div>
				{/if}
			{/each}
		</div>
	{:else}
		<!-- DESKTOP: Spatial Canvas -->
		<div class="workspace-canvas">
			<Canvas
				objects={canvasObjects}
				onObjectMove={handleObjectMove}
				grid={{ enabled: gridEnabled, size: 20 }}
				initialCamera={savedCamera}
				onCameraChange={(cam) => { savedCamera = cam; persistMetadata(); }}
				onGridChange={(enabled) => { gridEnabled = enabled; persistMetadata(); }}
			>
				{#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}
						receiver={getReceiverForTrait(trait)}
						onResize={(w, h, dx, dy) => handlePanelResize(trait, w, h, dx, dy)}
						onClose={() => handlePanelClose(trait)}
						onMinimizeChange={(m) => handlePanelMinimize(trait, m)}
						onDrop={(payload, shiftKey) => handlePanelDrop(trait, payload, shiftKey)}
					>
						{#if knownTraits.has(trait)}
							{#if trait === 'editor'}
								<EditorTrait collection={undefined} config={{}} userId={nodeId} {accessToken} collectionMetadata={{}} />
							{:else if trait === 'chat'}
								<ChatTrait collection={undefined} config={{}} userId={nodeId} {accessToken} />
							{:else if trait === 'kanban'}
								<KanbanTrait collection={undefined} config={{}} userId={nodeId} />
							{:else if trait === 'calendar'}
								<CalendarTrait collection={undefined} config={{}} userId={nodeId} />
							{:else if trait === 'podcast'}
								<PodcastTrait collection={undefined} config={{}} userId={nodeId} {accessToken} />
							{:else if trait === 'publishing'}
								<PublishingTrait collection={undefined} config={{}} />
							{:else if trait === 'rss'}
								<RssTrait collection={undefined} config={{}} />
							{:else if trait === 'recording'}
								<RecordingTrait collection={undefined} config={{}} {accessToken} />
							{:else if trait === 'transcription'}
								<TranscriptionTrait collection={undefined} config={{}} />
							{:else if trait === 'studio'}
								<StudioTrait collection={undefined} config={{}} userId={nodeId} />
							{:else if trait === 'mixer'}
								<MixerTrait collection={undefined} config={{}} {accessToken} />
							{:else if trait === 'mindmap'}
								<MindMapTrait collection={undefined} config={{}} userId={nodeId} {accessToken} />
							{:else if trait === 'ai'}
								<AiToolPanel {accessToken} userId={nodeId} />
							{:else if trait === 'usage'}
								{#if nodeId && accessToken}
									<NodeUsage nodeId={nodeId} {accessToken} />
								{/if}
							{/if}
						{:else}
							<GenericTrait name={trait} config={{}} />
						{/if}
					</BlockShell>
				{/snippet}
			</Canvas>
		</div>
	{/if}

</div>

<style>
	.workspace-page {
		display: flex;
		flex-direction: column;
		height: 100vh;
		background: var(--color-bg, #0a0a0b);
	}

	/* ================================================================= */
	/* Messages                                                          */
	/* ================================================================= */
	.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;
	}

	/* ================================================================= */
	/* Empty state (no panels)                                           */
	/* ================================================================= */
	.workspace-empty {
		display: flex;
		align-items: center;
		justify-content: center;
		flex: 1;
		padding: 24px;
	}

	.workspace-empty-inner {
		text-align: center;
		max-width: 480px;
	}

	.workspace-empty-title {
		font-size: 18px;
		font-weight: 600;
		color: #e8e8ec;
		margin-bottom: 8px;
	}

	.workspace-empty-desc {
		font-size: 14px;
		color: #8a8a96;
		margin-bottom: 24px;
	}

	.workspace-empty-tools {
		display: flex;
		flex-wrap: wrap;
		justify-content: center;
		gap: 8px;
	}

	.workspace-empty-tool {
		display: flex;
		align-items: center;
		gap: 6px;
		padding: 8px 14px;
		border: 1px solid var(--color-border, #2a2a2e);
		border-radius: 8px;
		background: var(--color-surface, #1c1c20);
		cursor: pointer;
		font-size: 13px;
		color: #8a8a96;
		transition: border-color 0.12s, box-shadow 0.12s;
	}

	.workspace-empty-tool:hover {
		border-color: var(--color-accent, #4f46e5);
		box-shadow: 0 2px 8px rgba(79, 70, 229, 0.1);
	}

	.workspace-empty-tool-icon {
		font-size: 16px;
	}

	.workspace-empty-tool-label {
		font-weight: 500;
	}

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

	/* ================================================================= */
	/* Mobile tabs                                                       */
	/* ================================================================= */
	.mobile-tabs {
		display: flex;
		overflow-x: auto;
		gap: 0;
		background: var(--color-surface, #1c1c20);
		border-bottom: 1px solid var(--color-border, #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: var(--color-accent, #4f46e5);
		border-bottom-color: var(--color-accent, #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-empty-tools {
			gap: 6px;
		}

		.workspace-empty-tool {
			padding: 6px 10px;
			font-size: 12px;
		}
	}
</style>
