/**
 * @file
 * FlowDrop Workflow Editor Integration for Drupal
 *
 * @description
 * Provides Drupal behavior for initializing and managing the FlowDrop workflow editor.
 * This script automatically mounts editor instances for elements with the
 * [data-flowdrop-editor] attribute.
 *
 * Requires the shared FlowDrop library (flowdrop_ui_components/flowdrop).
 *
 * @param {Function} once The "once" deduplication library.
 * @param {object} Drupal The Drupal API namespace.
 * @param {object} drupalSettings The Drupal settings object.
 */

((once, Drupal, drupalSettings) => {
  /**
   * Initialize the workflow editor in the given container
   *
   * @param {HTMLElement} editorContainer - The container element for the editor
   */
  function initializeEditor(editorContainer) {
    if (editorContainer.dataset.flowdropInitialized === 'true') {
      return;
    }

    // Apply FlowDrop theme (light/dark/auto) to document so design-tokens
    // [data-theme="dark"] rules apply. Uses initializeSettings() which
    // internally calls initializeTheme() (initializeTheme is tree-shaken
    // from the bundle exports but initializeSettings is available).
    // Do NOT pass `defaults` — that path deep-merges over the user's
    // persisted preference and writes it back, clobbering their choice.
    if (
      typeof window.FlowDrop !== 'undefined' &&
      typeof window.FlowDrop.initializeSettings === 'function'
    ) {
      window.FlowDrop.initializeSettings();
    }

    // Check if shared FlowDrop library is available
    if (typeof window.FlowDrop === 'undefined') {
      showError(
        editorContainer,
        'FlowDrop Library Not Available',
        'The FlowDrop library could not be loaded. Please ensure flowdrop_ui_components module is enabled.',
      );
      return;
    }

    if (typeof window.FlowDrop.mountFlowDropApp !== 'function') {
      showError(
        editorContainer,
        'Editor mount function not available',
        'The mountFlowDropApp function is not available in the FlowDrop library.',
      );
      return;
    }

    // Parse workflow data
    const workflow =
      parseJsonData(editorContainer.dataset.workflow) ||
      drupalSettings.flowdrop?.workflow;

    // Parse endpoint configuration
    let endpointConfig =
      parseJsonData(editorContainer.dataset.endpointConfig) ||
      drupalSettings.flowdrop?.endpointConfig;

    if (!endpointConfig) {
      const baseUrl = drupalSettings.flowdrop?.apiBaseUrl || '/api/flowdrop';
      endpointConfig = createDefaultEndpointConfig(baseUrl);
    }

    // Prepare initial workflow data
    const initialWorkflow = workflow
      ? {
          id: workflow.id,
          name: workflow.label || workflow.name || 'Untitled Workflow',
          description: workflow.description || '',
          nodes: workflow.nodes || [],
          edges: workflow.edges || [],
          metadata: {
            ...(workflow.metadata || {}),
            version: '1.0.0',
            created: workflow.created,
            changed: workflow.changed,
          },
        }
      : {
          id: `workflow_${Date.now()}`,
          name: 'New Workflow',
          description: 'A new FlowDrop workflow',
          nodes: [],
          edges: [],
          metadata: {
            version: '1.0.0',
            created: new Date().toISOString(),
            changed: new Date().toISOString(),
          },
        };

    // Parse UI configuration
    const showNavbar = editorContainer.dataset.showNavbar !== 'false';
    const navbarTitle =
      editorContainer.dataset.navbarTitle || initialWorkflow.name;
    const backUrl =
      editorContainer.dataset.backUrl || '/admin/flowdrop/workflows';
    const playgroundUrl = editorContainer.dataset.playgroundUrl || null;
    const showSaveButton = editorContainer.dataset.showSaveButton !== 'false';
    const showBackButton = editorContainer.dataset.showBackButton !== 'false';
    const enableKeyboardShortcuts =
      editorContainer.dataset.enableKeyboardShortcuts !== 'false';

    // Build navbar actions
    const navbarActions = [];

    if (showSaveButton) {
      navbarActions.push({
        label: 'Save',
        href: '#',
        variant: 'primary',
        icon: 'mdi:floppy-disk',
        onclick() {
          handleSave(editorContainer);
        },
      });
    }

    if (playgroundUrl) {
      navbarActions.push({
        label: 'Playground',
        href: playgroundUrl,
        variant: 'secondary',
        icon: 'mdi:play-circle-outline',
      });
    }

    if (showBackButton) {
      navbarActions.push({
        label: 'Back',
        href: backUrl,
        variant: 'secondary',
        icon: 'mdi:arrow-back',
      });
    }

    // Clear loading state
    const loadingElement = editorContainer.querySelector('.fd-editor__loading');
    if (loadingElement) {
      loadingElement.style.display = 'none';
    }

    // Mount the editor
    mountEditor(editorContainer, {
      workflow: initialWorkflow,
      endpointConfig,
      showNavbar,
      navbarTitle,
      navbarActions,
      enableKeyboardShortcuts,
    });
  }

  /**
   * Parse JSON data from a string, returning null on failure
   *
   * @param {string} jsonString - JSON string to parse
   * @return {object|null} Parsed object or null
   */
  function parseJsonData(jsonString) {
    if (!jsonString) return null;
    try {
      return JSON.parse(jsonString);
    } catch (error) {
      return null;
    }
  }

  /**
   * Mount the FlowDrop editor component
   *
   * @param {HTMLElement} container - The container element
   * @param {object} options - Mount options
   */
  async function mountEditor(container, options) {
    // Set initialized flag immediately to prevent duplicate initialization
    container.dataset.flowdropInitialized = 'true';
    try {
      // Register all form field types (code/template/markdown editors).
      // These are lazy-loaded — the heavy chunks (CodeMirror, EasyMDE) are
      // fetched on demand when this runs.
      if (typeof window.FlowDrop.initializeAllFieldTypes === 'function') {
        await window.FlowDrop.initializeAllFieldTypes();
      }

      const app = await window.FlowDrop.mountFlowDropApp(container, {
        workflow: options.workflow,
        endpointConfig: options.endpointConfig,
        height: '100%',
        width: '100%',
        showNavbar: options.showNavbar,
        navbarTitle: options.navbarTitle,
        navbarActions: options.navbarActions,
      });

      container.flowdropApp = app;

      if (options.enableKeyboardShortcuts) {
        setupKeyboardShortcuts(container);
      }

      container.dispatchEvent(
        new CustomEvent('flowdrop:editor:init', {
          detail: {
            editorId: container.id,
            app,
            workflow: options.workflow,
          },
          bubbles: true,
        }),
      );
    } catch (error) {
      // Clear initialization flag so retry is possible
      container.removeAttribute('data-flowdrop-initialized');
      showError(
        container,
        'Failed to load workflow editor',
        `An error occurred while initializing the editor: ${error.message}`,
      );
    }
  }

  /**
   * Set up keyboard shortcuts for the editor
   *
   * @param {HTMLElement} container - The editor container
   */
  function setupKeyboardShortcuts(container) {
    const keydownHandler = (event) => {
      if ((event.ctrlKey || event.metaKey) && event.key === 's') {
        event.preventDefault();
        handleSave(container);
      }
    };

    document.addEventListener('keydown', keydownHandler);
    container.keydownHandler = keydownHandler;
  }

  /**
   * Handle save action
   *
   * @param {HTMLElement} container - The editor container
   */
  function handleSave(container) {
    if (typeof window.flowdropSave === 'function') {
      window
        .flowdropSave()
        .then((result) => {
          container.dispatchEvent(
            new CustomEvent('flowdrop:editor:save', {
              detail: { editorId: container.id, success: true, result },
              bubbles: true,
            }),
          );
        })
        .catch((error) => {
          container.dispatchEvent(
            new CustomEvent('flowdrop:editor:save', {
              detail: {
                editorId: container.id,
                success: false,
                error: error.message,
              },
              bubbles: true,
            }),
          );
        });
    } else if (
      container.flowdropApp &&
      typeof container.flowdropApp.save === 'function'
    ) {
      container.flowdropApp.save().catch(() => {
        // Save handler not yet wired up — surface via the editor's error
        // event would require a container reference, so swallow silently.
      });
    }
  }

  /**
   * Cleanup editor instance
   *
   * @param {HTMLElement} container - The editor container
   */
  function cleanupEditor(container) {
    if (container.keydownHandler) {
      document.removeEventListener('keydown', container.keydownHandler);
      container.keydownHandler = null;
    }

    if (
      container.flowdropApp &&
      typeof container.flowdropApp.destroy === 'function'
    ) {
      container.flowdropApp.destroy();
      container.flowdropApp = null;
    }

    container.removeAttribute('data-flowdrop-initialized');
  }

  /**
   * Create default endpoint configuration
   *
   * @param {string} baseUrl - The base URL for API endpoints
   * @return {object} Default endpoint configuration
   */
  function createDefaultEndpointConfig(baseUrl) {
    return {
      baseUrl,
      endpoints: {
        categories: '/categories',
        nodes: {
          list: '/nodes',
          get: '/nodes/{id}',
          byCategory: '/nodes?category={category}',
          metadata: '/nodes/{id}/metadata',
        },
        workflows: {
          list: '/workflows',
          get: '/workflows/{id}',
          create: '/workflows',
          update: '/workflows/{id}',
          delete: '/workflows/{id}',
          validate: '/workflows/validate',
          export: '/workflows/{id}/export',
          import: '/workflows/import',
        },
        executions: {
          execute: '/workflows/{id}/execute',
          status: '/executions/{id}',
          cancel: '/executions/{id}/cancel',
          logs: '/executions/{id}/logs',
          history: '/executions',
        },
        chat: {
          sendMessage: '/workflows/{id}/chat/messages',
          getHistory: '/workflows/{id}/chat/messages',
          clearHistory: '/workflows/{id}/chat/messages',
        },
      },
      timeout: 30000,
      retry: {
        enabled: true,
        maxAttempts: 3,
        delay: 1000,
        backoff: 'exponential',
      },
      auth: { type: 'none' },
    };
  }

  /**
   * Display an error message in the editor container
   *
   * @param {HTMLElement} container - The container element
   * @param {string} title - Error title
   * @param {string} message - Error message details
   */
  function showError(container, title, message) {
    const loadingElement = container.querySelector('.fd-editor__loading');
    if (loadingElement) {
      loadingElement.remove();
    }

    // Clear container safely
    while (container.firstChild) {
      container.removeChild(container.firstChild);
    }

    // Build error UI with safe DOM construction
    const errorDiv = document.createElement('div');
    errorDiv.className = 'fd-editor__error';
    errorDiv.setAttribute('role', 'alert');
    errorDiv.setAttribute('aria-live', 'assertive');

    const iconDiv = document.createElement('div');
    iconDiv.className = 'fd-editor__error-icon';
    const svgNS = 'http://www.w3.org/2000/svg';
    const svg = document.createElementNS(svgNS, 'svg');
    svg.setAttribute('xmlns', svgNS);
    svg.setAttribute('width', '48');
    svg.setAttribute('height', '48');
    svg.setAttribute('viewBox', '0 0 24 24');
    svg.setAttribute('fill', 'none');
    svg.setAttribute('stroke', 'currentColor');
    svg.setAttribute('stroke-width', '2');
    const circle = document.createElementNS(svgNS, 'circle');
    circle.setAttribute('cx', '12');
    circle.setAttribute('cy', '12');
    circle.setAttribute('r', '10');
    svg.appendChild(circle);
    const line1 = document.createElementNS(svgNS, 'line');
    line1.setAttribute('x1', '12');
    line1.setAttribute('y1', '8');
    line1.setAttribute('x2', '12');
    line1.setAttribute('y2', '12');
    svg.appendChild(line1);
    const line2 = document.createElementNS(svgNS, 'line');
    line2.setAttribute('x1', '12');
    line2.setAttribute('y1', '16');
    line2.setAttribute('x2', '12.01');
    line2.setAttribute('y2', '16');
    svg.appendChild(line2);
    iconDiv.appendChild(svg);
    errorDiv.appendChild(iconDiv);

    const h3 = document.createElement('h3');
    h3.className = 'fd-editor__error-title';
    h3.textContent = Drupal.checkPlain(title);
    errorDiv.appendChild(h3);

    const p = document.createElement('p');
    p.className = 'fd-editor__error-message';
    p.textContent = Drupal.checkPlain(message);
    errorDiv.appendChild(p);

    const hint = document.createElement('p');
    hint.className = 'fd-editor__error-hint';
    hint.textContent =
      'Please refresh the page or contact support if the problem persists.';
    errorDiv.appendChild(hint);

    container.appendChild(errorDiv);
    container.classList.add('fd-editor--error');
  }

  /**
   * Drupal behavior for mounting FlowDrop workflow editor
   *
   * @type {object}
   */
  Drupal.behaviors.flowdropEditor = {
    /**
     * Attach behavior to editor containers
     *
     * @param {HTMLElement} context - The context element to search within
     */
    attach(context) {
      once('flowdrop-editor', '[data-flowdrop-editor]', context).forEach(
        (editorContainer) => {
          initializeEditor(editorContainer);
        },
      );
    },

    /**
     * Detach behavior and cleanup mounted components
     *
     * @param {HTMLElement} context - The context element to search within
     * @param {object} settings - Drupal settings object
     * @param {string} trigger - The trigger for detachment
     */
    detach(context, settings, trigger) {
      if (trigger !== 'unload') {
        return;
      }

      const containers = context.querySelectorAll('[data-flowdrop-editor]');
      containers.forEach((editorContainer) => {
        cleanupEditor(editorContainer);
      });
    },
  };

  /**
   * Public API for FlowDrop Editor
   */
  Drupal.flowdropEditor = {
    getApp(editorIdOrElement) {
      const container =
        typeof editorIdOrElement === 'string'
          ? document.getElementById(editorIdOrElement)
          : editorIdOrElement;
      return container?.flowdropApp || null;
    },

    save(editorIdOrElement) {
      const container =
        typeof editorIdOrElement === 'string'
          ? document.getElementById(editorIdOrElement)
          : editorIdOrElement;
      if (container) {
        handleSave(container);
      }
    },

    destroy(editorIdOrElement) {
      const container =
        typeof editorIdOrElement === 'string'
          ? document.getElementById(editorIdOrElement)
          : editorIdOrElement;
      if (container) {
        cleanupEditor(container);
      }
    },
  };
})(once, Drupal, drupalSettings);
