import React, { useEffect, useRef, memo } from 'react';
import * as monaco from 'monaco-editor';

const MonacoEditor = memo(({
  id,
  value = '',
  language = 'javascript',
  readOnly = false,
  height = '64',
  onChange = () => {}
}) => {
  const editorRef = useRef(null);
  const containerRef = useRef(null);
  const subscriptionRef = useRef(null);

  // Configure editor options based on language
  const getEditorOptions = (lang) => {
    const baseOptions = {
      automaticLayout: true,
      theme: 'vs-light',
      minimap: { enabled: false },
      readOnly,
      scrollBeyondLastLine: false,
      fontSize: 14,
      lineHeight: 21,
      padding: { top: 8, bottom: 8 },
      tabSize: 2,
      scrollbar: {
        vertical: 'auto',
        horizontal: 'auto'
      }
    };

    // Language-specific options
    switch (lang) {
      case 'json':
        return {
          ...baseOptions,
          formatOnPaste: true,
          formatOnType: true,
          autoClosingBrackets: 'always',
          autoClosingQuotes: 'always',
          bracketPairColorization: { enabled: true }
        };
      case 'xml':
        return {
          ...baseOptions,
          formatOnType: true,
          autoClosingTags: true,
          autoClosingBrackets: 'always',
          autoClosingQuotes: 'always'
        };
      default:
        return baseOptions;
    }
  };

  // Initialize or update editor
  const setupEditor = () => {
    if (!containerRef.current) return;

    // Dispose existing editor if it exists
    if (editorRef.current) {
      editorRef.current.dispose();
    }

    // Create new editor with language-specific options
    const options = getEditorOptions(language);
    editorRef.current = monaco.editor.create(containerRef.current, {
      value,
      language,
      ...options
    });

    // Set up change event handler
    if (subscriptionRef.current) {
      subscriptionRef.current.dispose();
    }

    subscriptionRef.current = editorRef.current.onDidChangeModelContent(() => {
      const newValue = editorRef.current.getValue();
      onChange(newValue);
    });

    // Format document if it's JSON
    if (language === 'json' && value) {
      try {
        const modelUri = monaco.Uri.parse(`inmemory://model-${id}.json`);
        const model = monaco.editor.createModel(value, 'json', modelUri);
        setTimeout(() => {
          monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
            validate: true,
            allowComments: false,
            schemas: []
          });
          editorRef.current.setModel(model);
        }, 100);
      } catch (e) {
        console.warn('Failed to format JSON:', e);
      }
    }
  };

  // Initial setup
  useEffect(() => {
    setupEditor();

    // Set up resize observer
    const resizeObserver = new ResizeObserver(() => {
      if (editorRef.current) {
        editorRef.current.layout();
      }
    });

    if (containerRef.current) {
      resizeObserver.observe(containerRef.current);
    }

    // Cleanup
    return () => {
      resizeObserver.disconnect();
      if (subscriptionRef.current) {
        subscriptionRef.current.dispose();
      }
      if (editorRef.current) {
        editorRef.current.dispose();
      }
    };
  }, [language]); // Reinitialize when language changes

  // Update value if it changes externally
  useEffect(() => {
    if (editorRef.current && value !== editorRef.current.getValue()) {
      editorRef.current.setValue(value);

      // Add formatting for JSON
      if (language === 'json' && value) {
        try {
          const action = editorRef.current.getAction('editor.action.formatDocument');
          if (action) {
            action.run();
          }
        } catch (e) {
          console.warn('Failed to format JSON:', e);
        }
      }
    }
  }, [value, language]);

  return (
      <div
          id={id}
          ref={containerRef}
          className={`h-${height} border mt-2`}
          style={{ minHeight: '100px' }}
      />
  );
});

MonacoEditor.displayName = 'MonacoEditor';

export default MonacoEditor;
