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

loader.config({
  paths: {
    vs: '/monaco-editor/min/vs'
  },
  'vs/nls': {
    availableLanguages: {},
  },
  // Specify which languages to load
  languages: ['javascript', 'json', 'xml','plaintext']
});

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

  // Ensure value is always a string
  const normalizedValue = value ?? '';

  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'
      }
    };

    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;
    }
  };

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

    const options = getEditorOptions(language);
    const editor = monaco.editor.create(containerRef.current, {
      ...options,
      value: normalizedValue,
      language: language
    });

    editorRef.current = editor;

    const subscription = editor.onDidChangeModelContent(() => {
      const newValue = editor.getValue();
      onChange(newValue);
    });

    subscriptionRef.current = subscription;

    if (language === 'json' && normalizedValue) {
      try {
        monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
          validate: true,
          allowComments: false,
          schemas: []
        });

        const action = editor.getAction('editor.action.formatDocument');
        if (action) {
          setTimeout(() => {
            action.run();
          }, 100);
        }
      } catch (e) {
        console.warn('Failed to format JSON:', e);
      }
    }

    const resizeObserver = new ResizeObserver(() => {
      editor.layout();
    });

    resizeObserver.observe(containerRef.current);

    return () => {
      resizeObserver.disconnect();
      subscription.dispose();

      // Ensure proper cleanup
      if (editor) {
        try {
          const model = editor.getModel();
          if (model) {
            model.dispose();
          }
          editor.dispose();
        } catch (e) {
          console.warn('Editor disposal error:', e);
        }
      }
    };
  }, [language]); // Only recreate when language changes

  // Handle value updates
  useEffect(() => {
    if (editorRef.current) {
      const currentValue = editorRef.current.getValue();
      if (currentValue !== normalizedValue) {
        editorRef.current.setValue(normalizedValue);
      }
    }
  }, [normalizedValue]);

  // Convert height to pixel value if it's a number
  const containerHeight = typeof height === 'number'
      ? `${height}px`
      : height.endsWith('px') ? height : `${height}px`;

  return (
      <div
          id={id}
          ref={containerRef}
          style={{
            minHeight: '100px',
            height: containerHeight,
            border: '1px solid #e2e8f0',
            marginTop: '0.5rem'
          }}
      />
  );
});

MonacoEditor.displayName = 'MonacoEditor';

export default MonacoEditor;
