/**
 * @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).
 */

(function (once, Drupal, drupalSettings) {
	"use strict";

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

		/**
		 * 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: function (context, settings, trigger) {
			if (trigger !== "unload") {
				return;
			}

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

	/**
	 * Initialize the workflow editor in the given container
	 *
	 * @param {HTMLElement} editorContainer - The container element for the editor
	 * @param {object} settings - Drupal settings object
	 */
	function initializeEditor(editorContainer, settings) {
		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).
		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
		let 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: function () {
					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: endpointConfig,
			showNavbar: showNavbar,
			navbarTitle: navbarTitle,
			navbarActions: navbarActions,
			enableKeyboardShortcuts: enableKeyboardShortcuts
		});
	}

	/**
	 * Parse JSON data from a string, returning null on failure
	 *
	 * @param {string} jsonString - JSON string to parse
	 * @returns {object|null} Parsed object or null
	 */
	function parseJsonData(jsonString) {
		if (!jsonString) return null;
		try {
			return JSON.parse(jsonString);
		} catch (error) {
			console.warn("[FlowDropEditor] Failed to parse JSON:", 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: 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
			);
			console.error("[FlowDropEditor] Initialization error:", error);
		}
	}

	/**
	 * Set up keyboard shortcuts for the editor
	 *
	 * @param {HTMLElement} container - The editor container
	 */
	function setupKeyboardShortcuts(container) {
		const keydownHandler = function (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(function (result) {
					container.dispatchEvent(new CustomEvent("flowdrop:editor:save", {
						detail: { editorId: container.id, success: true, result: result },
						bubbles: true
					}));
				})
				.catch(function (error) {
					console.error("[FlowDropEditor] Save failed:", 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(function (error) {
				console.error("[FlowDropEditor] Save failed:", error);
			});
		} else {
			console.warn("[FlowDropEditor] Save functionality not available");
		}
	}

	/**
	 * 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
	 * @returns {object} Default endpoint configuration
	 */
	function createDefaultEndpointConfig(baseUrl) {
		return {
			baseUrl: 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"
				}
			},
			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) {
		var 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
		var errorDiv = document.createElement("div");
		errorDiv.className = "fd-editor__error";
		errorDiv.setAttribute("role", "alert");
		errorDiv.setAttribute("aria-live", "assertive");

		var iconDiv = document.createElement("div");
		iconDiv.className = "fd-editor__error-icon";
		var svgNS = "http://www.w3.org/2000/svg";
		var 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");
		var circle = document.createElementNS(svgNS, "circle");
		circle.setAttribute("cx", "12");
		circle.setAttribute("cy", "12");
		circle.setAttribute("r", "10");
		svg.appendChild(circle);
		var line1 = document.createElementNS(svgNS, "line");
		line1.setAttribute("x1", "12");
		line1.setAttribute("y1", "8");
		line1.setAttribute("x2", "12");
		line1.setAttribute("y2", "12");
		svg.appendChild(line1);
		var 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);

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

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

		var 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");
	}

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

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

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