/**
 * @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;
		}

		// 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);

			if (drupalSettings.flowdrop?.csrfToken) {
				endpointConfig.headers = endpointConfig.headers || {};
				endpointConfig.headers["X-CSRF-Token"] = drupalSettings.flowdrop.csrfToken;
			}
		}

		// 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 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 (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) {
		try {
			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.dataset.flowdropInitialized = "true";
			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) {
			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);
			delete container.keydownHandler;
		}

		if (container.flowdropApp && typeof container.flowdropApp.destroy === "function") {
			container.flowdropApp.destroy();
			delete container.flowdropApp;
		}

		delete container.dataset.flowdropInitialized;
	}

	/**
	 * 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: {
				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" },
			headers: { "Content-Type": "application/json", Accept: "application/json" }
		};
	}

	/**
	 * 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();
		}

		container.innerHTML =
			'<div class="fd-editor__error">' +
			'<div class="fd-editor__error-icon">' +
			'<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">' +
			'<circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/>' +
			"</svg></div>" +
			'<h3 class="fd-editor__error-title">' + Drupal.checkPlain(title) + "</h3>" +
			'<p class="fd-editor__error-message">' + Drupal.checkPlain(message) + "</p>" +
			'<p class="fd-editor__error-hint">Please refresh the page or contact support if the problem persists.</p>' +
			"</div>";

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