<script lang="ts">
	import { onMount, onDestroy } from 'svelte';
	import { browser } from '$app/environment';
	import { ensureCodeMirrorModules } from './codemirror_modules';

	export let content: string = '';
	export let placeholder: string = 'Start typing...';

	let editor_container: HTMLDivElement;
	let editor_view: any;
	let cm: any; // Declare cm at the top level

	async function createEditor() {
		if (!browser) return;
		cm = await ensureCodeMirrorModules(); // Assign to the top-level cm
		if (!cm) return;

		// If an existing instance exists (HMR / remount), destroy it first
		if (editor_view && typeof editor_view.destroy === 'function') {
			try {
				editor_view.destroy();
			} catch (e) {
				/* ignore */
			}
			editor_view = null;
		}

		// Build extensions defensively
		const extensions = [
			cm.lineNumbers(),
			cm.highlightSpecialChars(),
			cm.history(),
			cm.foldGutter(),
			cm.drawSelection(),
			cm.dropCursor(),
			cm.EditorState_allowMultipleSelections.of(true),
			cm.indentOnInput(),
			cm.bracketMatching(),
			cm.closeBrackets(),
			cm.autocompletion(),
			cm.rectangularSelection(),
			cm.crosshairCursor(),
			cm.highlightActiveLine(),
			cm.highlightActiveLineGutter(),
			cm.EditorView_lineWrapping,
			cm.keymap.of([
				...cm.defaultKeymap,
				...cm.searchKeymap,
				...cm.historyKeymap,
				...cm.foldKeymap,
				...cm.completionKeymap,
				...cm.lintKeymap
			]),
			cm.markdown ? cm.markdown({ base: cm.markdownLanguage }) : null,
			cm.EditorView && cm.EditorView.updateListener
				? cm.EditorView.updateListener.of((update: any) => {
						if (update.docChanged) content = update.state.doc.toString();
					})
				: null
		].filter(Boolean);

		// Create editor
		editor_view = new cm.EditorView({
			state: cm.EditorState.create({
				doc: content ?? '',
				extensions
			}),
			parent: editor_container
		});
	}

	onMount(async () => {
		// ensure it's created only in browser and after modules resolved
		await createEditor();
	});

	onDestroy(() => {
		if (editor_view && typeof editor_view.destroy === 'function') {
			try {
				editor_view.destroy();
			} catch (e) {
				/* ignore */
			}
			editor_view = null;
		}
	});

	// Helper functions using the live editor_view (unchanged)
	const wrapSelection = (before: string, after: string = before) => {
		if (!editor_view) return;
		const state = editor_view.state;
		const changes = state.changeByRange((range: any) => {
			const isAlreadyWrapped =
				state.sliceDoc(range.from - before.length, range.from) === before &&
				state.sliceDoc(range.to, range.to + after.length) === after;

			if (isAlreadyWrapped) {
				return {
					changes: [
						{ from: range.from - before.length, to: range.from, insert: '' },
						{ from: range.to, to: range.to + after.length, insert: '' }
					],
					range: cm.EditorSelection.range(range.from - before.length, range.to - before.length)
				};
			}

			return {
				changes: [
					{ from: range.from, insert: before },
					{ from: range.to, insert: after }
				],
				range: cm.EditorSelection.range(range.from + before.length, range.to + before.length)
			};
		});
		editor_view.dispatch(changes);
		editor_view.focus();
	};

	const insertList = () => {
		if (!editor_view) return;
		const state = editor_view.state;
		const changes = state.changeByRange((range: any) => {
			const line = state.doc.lineAt(range.from);
			return {
				changes: [{ from: line.from, insert: '- ' }],
				range: cm.EditorSelection.range(range.from + 2, range.to + 2)
			};
		});
		editor_view.dispatch(changes);
		editor_view.focus();
	};
</script>

<div class="codemirror-wrapper border rounded">
	<div class="toolbar p-1 bg-gray-100 border-b">
		<button
			type="button"
			on:click={() => wrapSelection('**')}
			class="px-2 py-1 rounded hover:bg-gray-200"><b>B</b></button
		>
		<button
			type="button"
			on:click={() => wrapSelection('*')}
			class="px-2 py-1 rounded hover:bg-gray-200"><i>I</i></button
		>
		<button type="button" on:click={insertList} class="px-2 py-1 rounded hover:bg-gray-200"
			>List</button
		>
	</div>
	<div bind:this={editor_container} class="h-full min-h-[150px] overflow-auto"></div>
</div>
