import { useEffect, useRef } from 'react';
import { Crepe, CrepeFeature } from '@milkdown/crepe';
import { upload, uploadConfig } from '@milkdown/plugin-upload';

import '@milkdown/crepe/theme/common/style.css';
import '@milkdown/crepe/theme/nord.css';

function fileToDataUrl(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result as string);
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

interface MilkdownEditorProps {
  initialContent: string;
  onChange: (markdown: string) => void;
}

export function MilkdownEditor({ initialContent, onChange }: MilkdownEditorProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const crepeRef = useRef<Crepe | null>(null);
  const onChangeRef = useRef(onChange);
  onChangeRef.current = onChange;

  useEffect(() => {
    if (!containerRef.current) return;

    const crepe = new Crepe({
      root: containerRef.current,
      defaultValue: initialContent,
      featureConfigs: {
        [CrepeFeature.Placeholder]: {
          text: 'Start writing...',
        },
        [CrepeFeature.ImageBlock]: {
          onUpload: fileToDataUrl,
          inlineOnUpload: fileToDataUrl,
          blockOnUpload: fileToDataUrl,
        },
      },
    });

    // Add upload plugin to handle Ctrl+V and drag-drop of image files
    crepe.editor
      .config((ctx) => {
        ctx.update(uploadConfig.key, (prev) => ({
          ...prev,
          uploader: async (files: FileList, schema: import('@milkdown/prose/model').Schema) => {
            const results: import('@milkdown/prose/model').Node[] = [];
            for (let i = 0; i < files.length; i++) {
              const file = files.item(i);
              if (!file?.type.includes('image')) continue;
              const src = await fileToDataUrl(file);
              const node = schema.nodes.image?.createAndFill({ src, alt: file.name });
              if (node) results.push(node);
            }
            return results;
          },
          enableHtmlFileUploader: true,
        }));
      })
      .use(upload);

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

    crepe.create();
    crepeRef.current = crepe;

    return () => {
      crepe.destroy();
      crepeRef.current = null;
    };
  }, []);

  return <div ref={containerRef} className="milkdown-container" />;
}
