/**
 * FieldDiscoveryManager - Unified field discovery system
 *
 * Replaces multiple overlapping discovery mechanisms with a single,
 * focused class that handles:
 * - Initial field scanning
 * - MutationObserver for dynamic fields
 * - ACF event handling
 * - Periodic fallback scanning
 */

export class FieldDiscoveryManager {
  constructor(stateManager, fieldInitializer) {
    this.stateManager = stateManager;
    this.fieldInitializer = fieldInitializer;
    this.observer = null;
    this.scanInterval = null;
    this.scanTimeout = null;
    this.isStarted = false;
  }

  /**
   * Start the field discovery system
   */
  start() {
    if (this.isStarted) return;

    console.log('Starting field discovery system');
    this.isStarted = true;

    // Initial discovery
    this.scanForFields();

    // Set up DOM observer
    this.setupMutationObserver();

    // Set up ACF event handlers
    this.setupACFEventHandlers();

    // Set up periodic fallback scan
    this.scanInterval = setInterval(() => {
      const summary = this.stateManager.getStatusSummary();
      if (summary.processing > 0 || summary.discovered > 0) {
        console.log('Running periodic field discovery scan');
        this.scanForFields();
      }
    }, 2000);

    // Track for cleanup
    this.stateManager.addObserver({ disconnect: () => clearInterval(this.scanInterval) });
  }

  /**
   * Scan document for ACF textarea and JetEngine WYSIWYG fields needing initialization
   */
  scanForFields() {
    // Note: JetEngine WYSIWYG fields (.cx-control-wysiwyg) are NOT included here.
    // They are initialized by JetEngine's wp.editor.initialize() which is intercepted
    // by wrapTinyMCEInit to normalize TinyMCE 4 settings to TinyMCE 7.
    const selectors = [
      '.acf-field.acf-field-textarea textarea[id]:not([data-erte-processed])',
      '.cx-control-textarea textarea.cx-ui-textarea[id]:not([data-erte-processed])'
    ];
    const textareas = document.querySelectorAll(selectors.join(','));

    if (textareas.length > 0) {
      console.log(`Field discovery: found ${textareas.length} candidates`);
    }

    textareas.forEach(textarea => {
      const id = textarea.id;

      if (this.shouldProcessField(id, textarea)) {
        this.processField(id, textarea);
        textarea.setAttribute('data-erte-processed', 'true');
      }
    });
  }

  /**
   * Check if a field should be processed
   * @param {string} id - Field ID
   * @param {Element} textarea - Textarea element
   * @returns {boolean}
   */
  shouldProcessField(id, textarea) {
    // Skip if already being handled
    if (this.stateManager.isProcessing(id) || this.stateManager.isInitialized(id)) {
      return false;
    }

    // Skip excluded fields
    if (this.stateManager.shouldExclude(id, textarea)) {
      return false;
    }

    return true;
  }

  /**
   * Process a discovered field
   * @param {string} id - Field ID
   * @param {Element} textarea - Textarea element
   */
  processField(id, textarea) {
    this.stateManager.markAsDiscovered(id, textarea);
    this.fieldInitializer.initializeField(id, textarea);
  }

  /**
   * Set up mutation observer for dynamically added fields
   */
  setupMutationObserver() {
    this.observer = new MutationObserver(mutations => {
      let hasNewFields = false;

      mutations.forEach(mutation => {
        // Handle added nodes
        mutation.addedNodes.forEach(node => {
          if (node.nodeType === Node.ELEMENT_NODE) {
            hasNewFields = this.scanNodeForFields(node) || hasNewFields;
          }
        });

        // Handle visibility changes (style/class changes)
        if (
          mutation.type === 'attributes' &&
          ['style', 'class', 'data-acf-hidden'].includes(mutation.attributeName)
        ) {
          const target = mutation.target;
          if (target.nodeType === Node.ELEMENT_NODE && target.querySelectorAll) {
            hasNewFields = this.scanNodeForFields(target) || hasNewFields;
          }
        }
      });

      // Debounced full scan if new fields were found
      if (hasNewFields) {
        this.debouncedScan();
      }
    });

    this.observer.observe(document.body, {
      childList: true,
      subtree: true,
      attributes: true,
      attributeFilter: ['style', 'class', 'data-acf-hidden']
    });

    this.stateManager.addObserver(this.observer);
  }

  /**
   * Set up ACF event handlers
   */
  setupACFEventHandlers() {
    // Watch for ACF repeater additions
    jQuery(document).on('acf/add_field', (event, $field) => {
      const textareas = $field.find('textarea');
      textareas.each((_, textarea) => {
        const id = jQuery(textarea).attr('id');
        if (id && this.shouldProcessField(id, textarea)) {
          this.processField(id, textarea);
        }
      });
    });

    // Watch for ACF flexible content additions
    jQuery(document).on('acf/append', (event, $el) => {
      const textareas = $el.find('textarea');
      textareas.each((_, textarea) => {
        const id = jQuery(textarea).attr('id');
        if (id && this.shouldProcessField(id, textarea)) {
          this.processField(id, textarea);
        }
      });
    });
  }

  /**
   * Scan a specific node for ACF textarea and JetEngine WYSIWYG fields
   * @param {Element} node - Node to scan
   * @returns {boolean} True if fields were found
   */
  scanNodeForFields(node) {
    if (!node.querySelectorAll) return false;

    let foundFields = false;

    // Check if the node itself is an ACF textarea or JetEngine WYSIWYG field
    if (node.matches && (
      node.matches('.acf-field.acf-field-textarea') ||
      node.matches('.cx-control-textarea')
    )) {
      const textarea = node.querySelector('textarea[id]');
      if (textarea && this.shouldProcessField(textarea.id, textarea)) {
        this.processField(textarea.id, textarea);
        textarea.setAttribute('data-erte-processed', 'true');
        foundFields = true;
      }
    }

    // Check for ACF textarea and JetEngine WYSIWYG fields within the node
    const textareas = node.querySelectorAll(
      '.acf-field.acf-field-textarea textarea[id], .cx-control-textarea textarea.cx-ui-textarea[id]'
    );

    textareas.forEach(textarea => {
      const id = textarea.id;
      if (this.shouldProcessField(id, textarea)) {
        this.processField(id, textarea);
        textarea.setAttribute('data-erte-processed', 'true');
        foundFields = true;
      }
    });

    return foundFields;
  }

  /**
   * Debounced full scan
   */
  debouncedScan() {
    if (this.scanTimeout) {
      clearTimeout(this.scanTimeout);
    }

    this.scanTimeout = setTimeout(() => {
      this.scanForFields();
      this.scanTimeout = null;
    }, 100);
  }

  /**
   * Force a complete re-scan
   */
  forceScan() {
    console.log('Force scanning all ACF textarea fields...');

    // Remove processed markers to allow re-scanning
    document
      .querySelectorAll('.acf-field.acf-field-textarea textarea[data-erte-processed], .cx-control-textarea textarea[data-erte-processed]')
      .forEach(textarea => {
        textarea.removeAttribute('data-erte-processed');
      });

    this.scanForFields();

    // Also retry failed fields
    this.fieldInitializer.retryFailedFields();

    console.log('Force scan complete:', this.stateManager.getStatusSummary());
  }

  /**
   * Initialize fields in a specific container
   * @param {string|Element} container - Container selector or element
   */
  initializeFieldsInContainer(container) {
    const $container = typeof container === 'string' ? jQuery(container) : jQuery(container);
    const textareas = $container.find('.acf-field.acf-field-textarea textarea[id], .cx-control-textarea textarea.cx-ui-textarea[id]');

    console.log(`Initializing fields in container, found ${textareas.length} ACF textareas`);

    textareas.each((_, textarea) => {
      const id = textarea.id;
      if (this.shouldProcessField(id, textarea)) {
        this.processField(id, textarea);
      }
    });
  }

  /**
   * Stop the discovery system and cleanup
   */
  stop() {
    console.log('Stopping field discovery system');
    this.isStarted = false;

    if (this.observer) {
      this.observer.disconnect();
      this.observer = null;
    }

    if (this.scanInterval) {
      clearInterval(this.scanInterval);
      this.scanInterval = null;
    }

    if (this.scanTimeout) {
      clearTimeout(this.scanTimeout);
      this.scanTimeout = null;
    }

    // Remove ACF event handlers
    jQuery(document).off('acf/add_field');
    jQuery(document).off('acf/append');
  }
}

export default FieldDiscoveryManager;
