<script lang="ts">
	import { onMount, onDestroy } from 'svelte';
	import { Editor } from '@tiptap/core';
	import StarterKit from '@tiptap/starter-kit';
	import Image from '@tiptap/extension-image';
	import Link from '@tiptap/extension-link';
	import Placeholder from '@tiptap/extension-placeholder';
	import { Markdown } from 'tiptap-markdown';
	import { TiptapMention } from '$lib/editor/tiptapMention';
	import { storeImage, getImageUrl, resolveImageUrls, objectUrlToKaImg } from '$lib/db/imageStore';

	interface Props {
		content?: string;
		placeholder?: string;
		minHeight?: string;
		onchange?: (markdown: string) => void;
		onsave?: () => void;
		onsavearchive?: () => void;
	}
	let { content = '', placeholder = '', minHeight = '80px', onchange, onsave, onsavearchive }: Props = $props();

	let element: HTMLDivElement;
	let editor: Editor | null = null;
	let skipNextUpdate = false;
	let lastExternalContent = $state(content);

	export function getMarkdown(): string {
		if (!editor) return '';
		const raw = editor.storage.markdown.getMarkdown();
		return objectUrlToKaImg(raw);
	}

	export function clear() {
		if (!editor) return;
		editor.commands.clearContent(true);
	}

	function emitChange() {
		if (!editor || skipNextUpdate) {
			skipNextUpdate = false;
			return;
		}
		const md = getMarkdown();
		onchange?.(md);
	}

	function handlePaste(_view: any, event: ClipboardEvent): boolean {
		const items = event.clipboardData?.items;
		if (!items) return false;

		for (const item of items) {
			if (item.type.startsWith('image/')) {
				event.preventDefault();
				const blob = item.getAsFile();
				if (blob) {
					storeImage(blob)
						.then((id) => getImageUrl(id))
						.then((url) => {
							if (url && editor) {
								editor.chain().focus().setImage({ src: url }).run();
							}
						});
				}
				return true;
			}
		}
		return false;
	}

	onMount(async () => {
		let initialContent = content;
		if (content.includes('ka-img:')) {
			initialContent = await resolveImageUrls(content);
		}

		editor = new Editor({
			element,
			extensions: [
				StarterKit,
				Image.configure({ inline: true, allowBase64: false }),
				Link.configure({ autolink: true, openOnClick: false }),
				Placeholder.configure({ placeholder }),
				Markdown.configure({ html: false, transformCopiedText: true, transformPastedText: true }),
				TiptapMention
			],
			content: initialContent,
			editorProps: {
				handlePaste,
				handleKeyDown: (_view, event) => {
					if (event.key === 'Enter' && (event.ctrlKey || event.metaKey) && event.shiftKey) {
						onsavearchive?.();
						return true;
					}
					if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) {
						onsave?.();
						return true;
					}
					return false;
				},
				attributes: {
					style: `min-height: ${minHeight}`
				}
			},
			onUpdate: () => emitChange(),
			onTransaction: ({ editor: e }) => {
				// Force Svelte reactivity by reassigning
				editor = e;
			}
		});

		// Bind to DOM — Tiptap needs this for Svelte
		element.querySelector('.ProseMirror')?.setAttribute('data-ready', 'true');
	});

	// React to external content changes
	$effect(() => {
		if (!editor || content === lastExternalContent) return;
		lastExternalContent = content;

		const currentMd = getMarkdown();
		if (content === currentMd) return;

		skipNextUpdate = true;
		if (content.includes('ka-img:')) {
			resolveImageUrls(content).then(resolved => {
				editor?.commands.setContent(resolved);
			});
		} else {
			editor.commands.setContent(content);
		}
	});

	onDestroy(() => {
		editor?.destroy();
	});
</script>

<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
<div class="ka-editor-wrapper" onclick={(e) => e.stopPropagation()}>
	<div bind:this={element}></div>
</div>
