import { useEffect, useRef, useState } from 'react'
import './App.css'
import EditorJS, { OutputData } from '@editorjs/editorjs'

class EditorJSWrapper {
  private editor: EditorJS | null = null;
  private holder: HTMLDivElement | null = null;
  private onChange!: (data: OutputData) => void;
  private static instance: EditorJSWrapper | null = null;
  private currentData: OutputData = {
    time: Date.now(),
    blocks: [],
    version: '2.28.2'
  };

  constructor(onChange: (data: OutputData) => void) {
    if (EditorJSWrapper.instance) {
      return EditorJSWrapper.instance;
    }
    this.onChange = onChange;
    EditorJSWrapper.instance = this;
  }

  initialize(holder: HTMLDivElement) {
    if (this.editor || !holder) return;

    // Ensure any existing instance is destroyed first
    if (EditorJSWrapper.instance?.editor) {
      void EditorJSWrapper.instance.destroy();
    }
    
    this.holder = holder;
    try {
      this.editor = new EditorJS({
        holder: holder,
        placeholder: 'Start writing...',
        data: this.currentData,
        onChange: async () => {
          await this.syncState();
        }
      });
    } catch (error) {
      console.error('Error initializing editor:', error);
    }
  }

  private async syncState() {
    if (!this.editor) return;
    try {
      this.currentData = await this.editor.save();
      this.onChange(this.currentData);
    } catch (err) {
      console.error('Error syncing state:', err);
    }
  }

  async addBlock(text: string) {
    if (!this.editor) return;
    
    try {
      await this.editor.blocks.insert('paragraph', { text });
      await this.syncState();
    } catch (err) {
      console.error('Error adding block:', err);
    }
  }

  async clear() {
    if (!this.editor) return;
    try {
      await this.editor.clear();
      this.currentData = {
        time: Date.now(),
        blocks: [],
        version: '2.28.2'
      };
      this.onChange(this.currentData);
    } catch (err) {
      console.error('Error clearing editor:', err);
    }
  }

  async getData(): Promise<OutputData> {
    return this.currentData;
  }

  async destroy() {
    try {
      if (this.editor && typeof this.editor.destroy === 'function') {
        await this.editor.destroy();
        this.editor = null;
        this.holder = null;
        this.currentData = {
          time: Date.now(),
          blocks: [],
          version: '2.28.2'
        };
        EditorJSWrapper.instance = null;
      }
    } catch (error: unknown) {
      console.error('Error destroying editor:', error);
    }
  }
}

function App() {
  const [editorData, setEditorData] = useState<OutputData | null>(null);
  const [inputText, setInputText] = useState<string>("");
  const [editor] = useState(() => new EditorJSWrapper((data) => setEditorData(data)));
  const inputRef = useRef<HTMLInputElement>(null);
  const editorRef = useRef<HTMLDivElement>(null);
  
  useEffect(() => {
    if (editorRef.current) {
      editor.initialize(editorRef.current);
    }
    return () => {
      const cleanup = async () => {
        await editor.destroy();
      };
      void cleanup();
    };
  }, [editor]);

  const handleAdd = async () => {
    if (!inputText.trim()) return;

    await editor.addBlock(inputText);
    setInputText("");
    
    setTimeout(() => {
      inputRef.current?.focus();
    }, 0);
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    void handleAdd();
  };

  return (
    <div style={{ backgroundColor: '#1E1E1E' }} className="flex flex-col w-full h-screen items-center">
      <div className="flex flex-row w-full h-full gap-8 items-center px-8">
        <div className="flex-1 flex justify-center">
          <div style={{ backgroundColor: '#FFFFFF' }} className="min-h-[500px] min-w-[500px] rounded shadow-xl text-gray-900 p-6">
            <div style={{ margin: '20px' }} ref={editorRef} />
          </div>
        </div>
        <div className="flex-1 flex flex-col justify-center items-center gap-4">
          <OutputComponent data={editorData} />
          <form onSubmit={handleSubmit} className="flex gap-2 m-2">
            <input 
              ref={inputRef}
              type="text" 
              className="px-6 py-3 bg-white text-gray-900 rounded border border-gray-300" 
              value={inputText} 
              onChange={(e) => setInputText(e.target.value)}
              placeholder="Enter text..."
            />
            <button 
              type="submit"
              className="px-6 py-3 bg-gray-500 text-white rounded hover:bg-gray-600"
              disabled={!inputText.trim()}
            >
              Add
            </button>
            <button 
              type="button"
              onClick={() => void editor.clear()} 
              className="px-6 py-3 bg-blue-500 text-white rounded hover:bg-blue-600"
            >
              Clear All
            </button>
          </form>
        </div>
      </div>
    </div>
  )
}

export default App

function OutputComponent({ data }: { data: OutputData | null }) {
  return (
    <div style={{ backgroundColor: '#FFFFFF' }} className="min-h-[500px] min-w-[500px] rounded shadow-xl p-6 text-gray-900">
      <pre className="whitespace-pre-wrap">
        {data ? JSON.stringify(data, null, 2) : 'Output content will go here'}
      </pre>
    </div>
  )
}