import { useEffect, useRef } from 'react';
import { Crepe } from '@milkdown/crepe';
import '@milkdown/crepe/theme/common/style.css';
import '@milkdown/crepe/theme/frame-dark.css';
import './markdown-editor.css';
import { cn } from '@/lib/utils';

interface MarkdownEditorProps {
  /** Initial markdown. The editor owns its content after mount; edits flow out
   *  through `onChange`, so this is only read when the editor is (re)created. */
  value: string;
  onChange?: (markdown: string) => void;
  placeholder?: string;
  /** Render the same engine read-only, for displaying a message. */
  readOnly?: boolean;
  autoFocus?: boolean;
  className?: string;
}

/**
 * Single markdown engine used for both composing and displaying messages
 * (Milkdown Crepe). Editing is inline/WYSIWYG (Obsidian/Notion feel) with full
 * GFM — headings, lists, task lists, tables, code blocks, quotes, links — and
 * read-only mode renders the exact same way, so write and read never drift.
 */
export function MarkdownEditor({
  value,
  onChange,
  placeholder,
  readOnly = false,
  autoFocus = true,
  className,
}: MarkdownEditorProps) {
  const rootRef = useRef<HTMLDivElement>(null);
  // Keep the latest onChange without forcing the editor to be recreated.
  const onChangeRef = useRef(onChange);
  onChangeRef.current = onChange;

  useEffect(() => {
    const root = rootRef.current;
    if (!root) return;

    let cancelled = false;
    let created: Crepe | null = null;

    const crepe = new Crepe({
      root,
      defaultValue: value,
      features: {
        [Crepe.Feature.CodeMirror]: true,
        [Crepe.Feature.ListItem]: true,
        [Crepe.Feature.Table]: true,
        [Crepe.Feature.LinkTooltip]: !readOnly,
        [Crepe.Feature.Cursor]: !readOnly,
        [Crepe.Feature.BlockEdit]: !readOnly,
        [Crepe.Feature.Toolbar]: !readOnly,
        [Crepe.Feature.Placeholder]: !readOnly,
        [Crepe.Feature.ImageBlock]: false,
        [Crepe.Feature.Latex]: false,
        [Crepe.Feature.TopBar]: false,
        [Crepe.Feature.AI]: false,
      },
      featureConfigs: {
        [Crepe.Feature.Placeholder]: { text: placeholder ?? '' },
      },
    });

    crepe.setReadonly(readOnly);

    if (!readOnly) {
      crepe.on((listener) => {
        listener.markdownUpdated((_ctx, markdown) => {
          onChangeRef.current?.(markdown);
        });
      });
    }

    crepe.create().then(() => {
      if (cancelled) {
        crepe.destroy();
        return;
      }
      created = crepe;
      if (autoFocus && !readOnly) {
        root.querySelector<HTMLElement>('.ProseMirror')?.focus();
      }
    });

    return () => {
      cancelled = true;
      created?.destroy();
    };
    // `value` is the initial content only; recreate when the mode flips.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [readOnly]);

  return (
    <div
      ref={rootRef}
      className={cn('llink-crepe', !readOnly && 'llink-crepe--fill', className)}
    />
  );
}
