/**
 * NoteNode Component
 *
 * A rich text note editor node using BlockNote.
 * Storage-agnostic - accepts a storage adapter for any backend.
 */

'use client';

import React, { useEffect, useRef } from 'react';
import { useCreateBlockNote, useEditorChange } from '@blocknote/react';
import { BlockNoteView } from '@blocknote/shadcn';
import { en } from '@blocknote/core/locales';

import type { NoteNodeProps } from './types';
import { createDebug } from '../../utils/debug';

const debug = createDebug('note-node');

// CSS imports - consumers must ensure these are available
import '@blocknote/core/fonts/inter.css';
import '@blocknote/shadcn/style.css';

/**
 * NoteNode - A rich text editor node for canvas.
 *
 * Uses BlockNote for the editor and accepts a storage adapter
 * for persistence. This allows it to work with any backend:
 * Jazz, Supabase, local state, etc.
 *
 * @example
 * ```tsx
 * // With Jazz storage
 * <NoteNode
 *   nodeData={nodeData}
 *   storage={useJazzNoteStorage(nodeData.id)}
 * />
 *
 * // With local state
 * const [content, setContent] = useState('');
 * <NoteNode
 *   nodeData={nodeData}
 *   storage={{ content, onChange: setContent }}
 * />
 * ```
 */
export function NoteNode({
	nodeData,
	storage,
	theme = 'light',
	placeholder = 'Start typing...',
	isResizing,
}: NoteNodeProps) {
	// Refs to prevent sync loops between editor and storage
	const isSyncingFromStorage = useRef(false);
	const isSyncingToStorage = useRef(false);
	const lastStorageContent = useRef<string>('');

	// Create BlockNote editor
	const editor = useCreateBlockNote(
		{
			initialContent: [
				{
					id: crypto.randomUUID(),
					type: 'paragraph',
					content: '',
				},
			],
			dictionary: {
				...en,
				placeholders: {
					...en.placeholders,
					emptyDocument: placeholder,
					default: placeholder,
					heading: 'Enter a heading',
				},
			},
		},
		[],
	);

	// Sync editor changes → storage
	useEditorChange(() => {
		if (isSyncingFromStorage.current) {
			return;
		}

		try {
			isSyncingToStorage.current = true;
			const html = editor.blocksToFullHTML(editor.document);

			if (html !== lastStorageContent.current) {
				lastStorageContent.current = html;
				storage.onChange(html);
			}
		} catch (err) {
			debug.error('Failed to sync to storage: %O', err);
		} finally {
			isSyncingToStorage.current = false;
		}
	}, editor);

	// Sync storage changes → editor (for real-time sync)
	useEffect(() => {
		if (!editor) return;

		const handleStorageChange = (newContent: string) => {
			if (isSyncingToStorage.current) {
				return;
			}

			// Throttle to next microtask to avoid invalid intermediate states
			queueMicrotask(() => {
				if (newContent === lastStorageContent.current) return;

				lastStorageContent.current = newContent;

				if (newContent && newContent.trim()) {
					try {
						isSyncingFromStorage.current = true;
						const blocks = editor.tryParseHTMLToBlocks(newContent);
						editor.replaceBlocks(editor.document, blocks);
					} catch (err) {
						debug.error('Failed to parse HTML from storage: %O', err);
					} finally {
						isSyncingFromStorage.current = false;
					}
				}
			});
		};

		// Subscribe to external changes if available
		const unsubscribe = storage.subscribe?.(handleStorageChange);

		// Initial sync from storage
		if (storage.content && storage.content !== lastStorageContent.current) {
			handleStorageChange(storage.content);
		}

		return () => {
			unsubscribe?.();
		};
	}, [editor, storage]);

	// Show loading state if storage is loading
	if (storage.isLoading) {
		return (
			<div className="note-node note-node--loading" style={styles.loading}>
				Loading...
			</div>
		);
	}

	return (
		<div
			className="note-node"
			style={styles.container}
			data-no-drag="true"
			onClick={(e) => {
				e.stopPropagation();
			}}
		>
			<BlockNoteView editor={editor} theme={theme} />
		</div>
	);
}

const styles = {
	container: {
		height: '100%',
		width: '100%',
		overflow: 'auto',
		touchAction: 'auto',
	},
	loading: {
		display: 'flex',
		alignItems: 'center',
		justifyContent: 'center',
		height: '100%',
		color: '#666',
	},
} as const;

export default NoteNode;
