/**
 * EditorInitializer - Handles TinyMCE editor initialization
 *
 * Provides a clean, modular approach to initializing TinyMCE editors
 * with proper configuration, event handling, and plugin setup.
 */

import { CUSTOM_FORMATS, MINIFIED_PROPS } from '../config/constants';
import { PasteHandler } from './PasteHandler';
import { VisibilityManager } from './VisibilityManager';

export class EditorInitializer {
  constructor(stateManager) {
    this.stateManager = stateManager;
    this.pasteHandler = new PasteHandler();
    this.visibilityManager = new VisibilityManager(stateManager);
  }

  /**
   * Get base configuration for an editor
   * @param {string} id - Editor ID
   * @param {Object} config - Initial configuration
   * @returns {Object} Base configuration
   */
  getBaseConfig(id, config) {
    return {
      ...config,
      advlist_bullet_styles: 'default',
      advlist_number_styles: 'default',
      formats: { ...config.formats, ...CUSTOM_FORMATS },
      newline_behavior: 'default'
    };
  }

  /**
   * Initialize a TinyMCE editor
   * @param {string} selector - Editor selector (e.g., "#content")
   * @param {Object} config - Editor configuration
   * @param {boolean} isInline - Whether this is an inline editor
   */
  initEditor(selector, config, isInline = false) {
    try {
      if (!config || !selector) {
        console.error('Invalid config or selector for TinyMCE initialization:', { selector, config });
        return;
      }

      const finalConfig = this.buildConfig(selector, config, isInline);

      console.log(`Initializing TinyMCE editor: ${selector}`, finalConfig);
      window.tinymce.init(finalConfig);

      if (isInline) {
        const id = selector.replace('#', '');
        this.stateManager.markAsInline(id);
      }
    } catch (error) {
      console.error(`Failed to initialize editor for ${selector}:`, error);
    }
  }

  /**
   * Build the final configuration for an editor
   * @param {string} selector - Editor selector
   * @param {Object} config - Base configuration
   * @param {boolean} isInline - Whether inline editor
   * @returns {Object} Final configuration
   */
  buildConfig(selector, config, isInline) {
    const finalConfig = isInline
      ? { ...config, ...MINIFIED_PROPS, selector }
      : { ...config, selector };

    // Ensure critical properties are set
    finalConfig.readonly = false;
    finalConfig.disabled = false;

    // Store original setup function
    const originalSetup = finalConfig.setup;

    // Set up the editor
    finalConfig.setup = editor => {
      this.setupEditor(editor, config, originalSetup);
    };

    return finalConfig;
  }

  /**
   * Set up editor event handlers
   * @param {Object} editor - TinyMCE editor instance
   * @param {Object} config - Editor configuration
   * @param {Function} originalSetup - Original setup function
   */
  setupEditor(editor, config, originalSetup) {
    // Call original setup if it exists
    if (originalSetup && typeof originalSetup === 'function') {
      originalSetup(editor);
    }

    // Handle before set content
    editor.on('beforesetcontent', o => {
      if (o.initial) {
        o.content = o.content.replace(/<p><\/p>/g, '');
      }
    });

    // Sync parent window width to iframe
    editor.on('init', () => {
      this.setupResponsiveSync(editor);
    });

    // Attach paste handlers
    this.pasteHandler.attach(editor);

    // Handle initialization
    editor.on('init', () => {
      this.handleEditorInit(editor, config);
    });

    // Handle potential readonly issues
    editor.on('focus', () => {
      if (editor.readonly) {
        console.warn(`Editor ${editor.id} is readonly, attempting to make editable`);
        editor.setMode('design');
      }
    });
  }

  /**
   * Set up responsive width syncing
   * @param {Object} editor - TinyMCE editor instance
   */
  setupResponsiveSync(editor) {
    const syncParentWidth = () => {
      const parentWidth = window.innerWidth;
      const iframeDoc = editor.getDoc();
      const iframeHtml = iframeDoc?.documentElement;

      if (iframeHtml) {
        iframeHtml.style.setProperty('--parent-width', `${parentWidth}px`);

        // Add responsive classes
        iframeHtml.classList.remove('parent-mobile', 'parent-tablet', 'parent-desktop', 'parent-wide');

        if (parentWidth < 768) {
          iframeHtml.classList.add('parent-mobile');
        } else if (parentWidth < 1024) {
          iframeHtml.classList.add('parent-tablet');
        } else if (parentWidth < 1440) {
          iframeHtml.classList.add('parent-desktop');
        } else {
          iframeHtml.classList.add('parent-wide');
        }
      }
    };

    // Initial sync
    syncParentWidth();

    // Sync on resize
    window.addEventListener('resize', syncParentWidth);

    // Cleanup on editor removal
    editor.on('remove', () => {
      window.removeEventListener('resize', syncParentWidth);
    });
  }

  /**
   * Handle editor initialization event
   * @param {Object} editor - TinyMCE editor instance
   * @param {Object} config - Editor configuration
   */
  handleEditorInit(editor, config) {
    const editorElement = editor.getElement();
    const isHidden =
      editorElement &&
      (editorElement.style.display === 'none' || editorElement.offsetParent === null);

    console.log(`TinyMCE editor initialized: ${editor.id}`, {
      editable: !editor.readonly,
      hasBody: !!editor.getBody(),
      disabled: editor.disabled,
      hidden: editor.isHidden?.() || false,
      elementHidden: isHidden
    });

    // Ensure editor is editable
    if (editor.readonly) {
      editor.setMode('design');
    }

    // Initialize plugins
    this.initializePlugins(editor, config);

    // Handle visibility
    this.visibilityManager.handleEditorVisibility(editor, editorElement);
  }

  /**
   * Initialize editor plugins
   * @param {Object} editor - TinyMCE editor instance
   * @param {Object} config - Editor configuration
   */
  initializePlugins(editor, config) {
    try {
      // Prefer per-editor style_formats from the config; fall back to a global
      // a provider (e.g. TheDock) can set. We build the editor config from the
      // DOM when WordPress doesn't emit one, which drops any style_formats added
      // server-side via tiny_mce_before_init — the global is how those styles
      // still reach the dropdown. Without a provider the global is absent and the
      // Styles button stays disabled.
      const styleFormats =
        config.style_formats ||
        (typeof window !== 'undefined' ? window.erteStyleFormats : null);
      if (styleFormats && editor.plugins.tdstyles) {
        editor.plugins.tdstyles.initStyles(styleFormats);
      }
      if (editor.plugins.tdblocks) {
        editor.plugins.tdblocks.initBlocks(config.tdblocks_formats || config.block_formats);
      }
    } catch (pluginError) {
      console.warn(`Plugin initialization warning for ${editor.id}:`, pluginError);
    }
  }
}

export default EditorInitializer;
