<script lang="ts">
	/**
	 * AI-verktøy panel for arbeidsflaten.
	 *
	 * Viser standardprompter (ai_preset-noder), fritekst-felt for egendefinert
	 * prompt, modell-indikator (readonly), og mottar tekstnoder via drag-and-drop.
	 *
	 * Retning bestemmes av interaksjon:
	 * - Dra en node HIT → node_to_tool (ny node med AI-output)
	 * - Dra verktøyet PÅ en node → tool_to_node (in-place revisjon)
	 * For nå støtter panelet kun node_to_tool (drop-mottak).
	 */
	import type { Node } from '$lib/spacetime';
	import { nodeStore } from '$lib/spacetime';
	import { aiProcess } from '$lib/api';

	interface Props {
		accessToken?: string;
		userId?: string;
	}

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

	// --- State ---
	let selectedPresetId = $state<string | null>(null);
	let customPrompt = $state('');
	let dragOver = $state(false);
	let processing = $state(false);
	let lastResult = $state<{ success: boolean; message: string } | null>(null);
	let droppedNodeId = $state<string | null>(null);

	// --- Derived: AI-preset noder fra STDB ---
	const presets = $derived.by(() => {
		const all = nodeStore.byKind('ai_preset');
		// Sorter: standard først, deretter custom, alfabetisk innenfor
		return all.sort((a, b) => {
			const metaA = parseMetadata(a);
			const metaB = parseMetadata(b);
			const catA = metaA.category === 'standard' ? 0 : 1;
			const catB = metaB.category === 'standard' ? 0 : 1;
			if (catA !== catB) return catA - catB;
			return (a.title ?? '').localeCompare(b.title ?? '', 'nb');
		});
	});

	const selectedPreset = $derived(
		selectedPresetId ? nodeStore.get(selectedPresetId) : null
	);

	const selectedMeta = $derived(selectedPreset ? parseMetadata(selectedPreset) : null);

	const modelLabel = $derived.by(() => {
		if (!selectedMeta) return '';
		switch (selectedMeta.model_profile) {
			case 'flash': return 'Rask (flash)';
			case 'standard': return 'Standard';
			default: return selectedMeta.model_profile ?? '';
		}
	});

	const defaultDirection = $derived(
		(selectedMeta?.default_direction as string) ?? 'node_to_tool'
	);

	const droppedNode = $derived(droppedNodeId ? nodeStore.get(droppedNodeId) : null);

	// --- Helpers ---
	function parseMetadata(node: Node): Record<string, unknown> {
		try {
			return JSON.parse(node.metadata ?? '{}');
		} catch {
			return {};
		}
	}

	function presetIcon(meta: Record<string, unknown>): string {
		const icon = meta.icon as string;
		// Map heroicon names to unicode/emoji approximations
		const iconMap: Record<string, string> = {
			sparkles: '✨',
			check_badge: '✅',
			document_text: '📄',
			language: '🌐',
			pencil_square: '✏️',
			list_bullet: '📋',
			arrow_path: '🔄',
			chat_bubble_left_right: '💬'
		};
		return iconMap[icon] ?? '🤖';
	}

	// --- Drag-and-drop ---
	function handleDragOver(e: DragEvent) {
		e.preventDefault();
		if (e.dataTransfer) {
			e.dataTransfer.dropEffect = 'copy';
		}
		dragOver = true;
	}

	function handleDragLeave(e: DragEvent) {
		// Only leave if actually leaving the drop zone
		const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
		const x = e.clientX;
		const y = e.clientY;
		if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) {
			dragOver = false;
		}
	}

	function handleDrop(e: DragEvent) {
		e.preventDefault();
		dragOver = false;

		const nodeId = e.dataTransfer?.getData('text/plain');
		if (!nodeId) return;

		const node = nodeStore.get(nodeId);
		if (!node) return;

		// Sjekk kompatibilitet: kun tekstnoder
		if (node.nodeKind !== 'content' && node.nodeKind !== 'communication') {
			lastResult = {
				success: false,
				message: `AI-verktøyet behandler kun tekst. "${node.title ?? 'Noden'}" er av type ${node.nodeKind}.`
			};
			return;
		}

		if (!node.content?.trim()) {
			lastResult = {
				success: false,
				message: 'Noden har ikke noe tekstinnhold å prosessere.'
			};
			return;
		}

		droppedNodeId = nodeId;
		lastResult = null;
	}

	// --- Prosessering ---
	async function processNode() {
		if (!accessToken || !selectedPresetId || !droppedNodeId) return;

		const direction = defaultDirection === 'both' ? 'node_to_tool' : defaultDirection;
		if (direction !== 'node_to_tool' && direction !== 'tool_to_node') return;

		processing = true;
		lastResult = null;

		try {
			const res = await aiProcess(accessToken, {
				source_node_id: droppedNodeId,
				ai_preset_id: selectedPresetId,
				direction
			});
			lastResult = {
				success: true,
				message: `Jobb opprettet (${res.job_id.slice(0, 8)}…). Resultatet dukker opp i sanntid.`
			};
			droppedNodeId = null;
		} catch (err) {
			lastResult = {
				success: false,
				message: `Feil: ${err instanceof Error ? err.message : String(err)}`
			};
		} finally {
			processing = false;
		}
	}

	function clearDropped() {
		droppedNodeId = null;
		lastResult = null;
	}
</script>

<section class="rounded-lg border border-gray-200 bg-white shadow-sm" data-component="ai-tool-panel">
	<div class="flex items-center gap-2 border-b border-gray-100 px-4 py-3">
		<span class="text-lg" aria-hidden="true">🤖</span>
		<h3 class="text-sm font-semibold text-gray-700">AI-verktøy</h3>
		{#if modelLabel}
			<span class="ml-auto rounded-full bg-purple-50 px-2 py-0.5 text-xs text-purple-600">
				{modelLabel}
			</span>
		{/if}
	</div>

	<div class="p-4 space-y-4">
		<!-- Prompt-velger -->
		<div>
			<label for="ai-preset-select" class="block text-xs font-medium text-gray-500 mb-1">
				Velg verktøy
			</label>
			{#if presets.length === 0}
				<p class="text-xs text-gray-400">Ingen AI-presets tilgjengelig.</p>
			{:else}
				<div class="grid grid-cols-2 gap-1.5 sm:grid-cols-4">
					{#each presets as preset (preset.id)}
						{@const meta = parseMetadata(preset)}
						<button
							onclick={() => { selectedPresetId = preset.id; }}
							class="flex items-center gap-1.5 rounded-lg border px-2.5 py-2 text-left text-xs transition-colors
								{selectedPresetId === preset.id
									? 'border-purple-400 bg-purple-50 text-purple-800 shadow-sm'
									: 'border-gray-200 text-gray-600 hover:border-gray-300 hover:bg-gray-50'}"
							style={selectedPresetId === preset.id ? `border-color: ${meta.color}` : ''}
						>
							<span class="text-sm shrink-0">{presetIcon(meta)}</span>
							<span class="truncate">{preset.title}</span>
						</button>
					{/each}
				</div>
			{/if}
		</div>

		<!-- Valgt preset-detaljer -->
		{#if selectedPreset && selectedMeta}
			<div class="rounded-lg bg-gray-50 p-3 text-xs text-gray-600">
				<p class="font-medium text-gray-700 mb-1">{selectedPreset.title}</p>
				<p class="line-clamp-2">{selectedMeta.prompt}</p>
				<div class="mt-2 flex items-center gap-3 text-gray-400">
					<span>Modell: {modelLabel}</span>
					<span>Retning: {
						defaultDirection === 'node_to_tool' ? 'Ny node'
						: defaultDirection === 'tool_to_node' ? 'In-place'
						: 'Begge'
					}</span>
				</div>
			</div>
		{/if}

		<!-- Fritekst-felt for egendefinert prompt -->
		<div>
			<label for="custom-prompt" class="block text-xs font-medium text-gray-500 mb-1">
				Egendefinert instruksjon (valgfritt)
			</label>
			<textarea
				id="custom-prompt"
				bind:value={customPrompt}
				placeholder="Legg til spesifikke instruksjoner..."
				rows="2"
				class="w-full rounded-lg border border-gray-200 px-3 py-2 text-sm text-gray-700 placeholder:text-gray-300 focus:border-purple-400 focus:outline-none focus:ring-1 focus:ring-purple-200 resize-none"
			></textarea>
			<p class="mt-0.5 text-xs text-gray-400">
				Kommer i tillegg til valgt preset (funksjon under utvikling).
			</p>
		</div>

		<!-- Drop-sone -->
		<div
			role="region"
			aria-label="Slipp tekstnode her"
			ondragover={handleDragOver}
			ondragleave={handleDragLeave}
			ondrop={handleDrop}
			class="rounded-lg border-2 border-dashed p-6 text-center transition-colors
				{dragOver
					? 'border-purple-400 bg-purple-50'
					: droppedNode
						? 'border-green-300 bg-green-50'
						: 'border-gray-200 bg-gray-50'}"
		>
			{#if droppedNode}
				<!-- Viser droppet node -->
				<div class="space-y-2">
					<p class="text-sm font-medium text-gray-700">
						{droppedNode.title || 'Uten tittel'}
					</p>
					<p class="text-xs text-gray-500 line-clamp-2">
						{droppedNode.content?.slice(0, 120)}{(droppedNode.content?.length ?? 0) > 120 ? '…' : ''}
					</p>
					<div class="flex items-center justify-center gap-2 pt-1">
						<button
							onclick={processNode}
							disabled={!selectedPresetId || processing}
							class="rounded-lg px-4 py-1.5 text-xs font-medium text-white transition-colors
								{!selectedPresetId || processing
									? 'bg-gray-300 cursor-not-allowed'
									: 'bg-purple-600 hover:bg-purple-700'}"
						>
							{#if processing}
								Prosesserer…
							{:else}
								Kjør {selectedPreset?.title ?? 'AI'}
							{/if}
						</button>
						<button
							onclick={clearDropped}
							class="rounded-lg border border-gray-200 px-3 py-1.5 text-xs text-gray-500 hover:bg-gray-100"
						>
							Fjern
						</button>
					</div>
				</div>
			{:else if dragOver}
				<p class="text-sm text-purple-600 font-medium">Slipp her for AI-prosessering</p>
			{:else}
				<p class="text-sm text-gray-400">Dra en tekstnode hit</p>
				<p class="text-xs text-gray-300 mt-1">Støtter innholds- og kommunikasjonsnoder</p>
			{/if}
		</div>

		<!-- Resultat/feil-melding -->
		{#if lastResult}
			<div class="rounded-lg p-3 text-xs {lastResult.success ? 'bg-green-50 text-green-700' : 'bg-red-50 text-red-700'}">
				{lastResult.message}
			</div>
		{/if}
	</div>
</section>
