/* jshint browser: true */
/* global epofw_var, CodeMirror */
/**
 * Epofw admin js.
 *
 * @version 1.0.0
 * @package Extra_Product_Options_For_WooCommerce
 */


( function ( $ ) {
	'use strict';
	initFunction();
	$( document ).ajaxComplete(
		function () {
			initFunction();
		}
	);

	function initFunction () {
		var classDatePicker                       = $( '.epofw_condition_data_class_date_picker' ),
			epofwDatepicker                       = $( '.epofw_datepicker' ),
			epofwColorpicker                      = $( '.epofw_colorpicker' );

		if ( classDatePicker.length ) {
			classDatePicker.datepicker( { dateFormat : 'dd-mm-yy' } );
		}
		if ( epofwDatepicker.length ) {
			epofwDatepicker.datepicker( { dateFormat : 'dd-mm-yy' } );
		}

		if ( epofwColorpicker.length ) {
			epofwColorpicker.wpColorPicker();
		}

		if ( $( '.epofw-icon-picker' ).length && typeof $.fn.epofwIconPicker !== 'undefined' ) {
			$( '.epofw-icon-picker' ).epofwIconPicker(
				{
					onSelect : function () {
						// Trigger change event for any dependent fields.
						$( this ).trigger( 'change' );
					}
				}
			);
		}

		epofwToggleGlobalStylingFields();
		epofwInitGlobalSettingsAccordion();
	}

	function epofwToggleGlobalStylingFields () {
		var $labelToggle = $( '#epofw_global_label_styling_enabled' ),
			$labelFields = $( '#epofw-global-label-styling-fields' ),
			$containerToggle = $( '#epofw_global_field_container_enabled' ),
			$containerFields = $( '#epofw-global-field-container-fields' );

		if ( ! $labelToggle.length && ! $containerToggle.length ) {
			return;
		}

		function epofwToggleGlobalFields () {
			$labelFields.toggle( $labelToggle.is( ':checked' ) );
			$containerFields.toggle( $containerToggle.is( ':checked' ) );
		}

		epofwToggleGlobalFields();
		$labelToggle.off( 'change.epofwToggle' ).on( 'change.epofwToggle', epofwToggleGlobalFields );
		$containerToggle.off( 'change.epofwToggle' ).on( 'change.epofwToggle', epofwToggleGlobalFields );
	}

	function epofwInitGlobalSettingsAccordion () {
		var $accordionBoxes = $( '.epofw-general-settings-container .epofw-configuration-box, .epofw-global-section-layout-settings' );

		if ( ! $accordionBoxes.length ) {
			return;
		}

		$accordionBoxes.each(
			function ( index ) {
				var $box = $( this ),
					$toggle = $box.find( '.epofw-accordion-toggle' ).first(),
					$content = $box.find( '.epofw-box-content' ).first(),
					defaultOpen = $toggle.data( 'epofw-default-open' );

				if ( ! $toggle.length || ! $content.length ) {
					return;
				}

				function epofwUpdateAccordionState ( isExpanded, shouldAnimate ) {
					var expandText = $toggle.data( 'epofw-expand-text' ) || '';
					var collapseText = $toggle.data( 'epofw-collapse-text' ) || '';
					var nextText = isExpanded ? collapseText : expandText;
					var $icon = $toggle.find( '.dashicons' );

					$toggle.attr( 'aria-expanded', isExpanded ? 'true' : 'false' );
					$box.toggleClass( 'epofw-accordion-collapsed', ! isExpanded );
					if ( shouldAnimate ) {
						$content.stop( true, true )[ isExpanded ? 'slideDown' : 'slideUp' ]( 500, 'swing' );
					} else {
						$content.toggle( isExpanded );
					}
					if ( $icon.length ) {
						$icon.removeClass( 'dashicons-arrow-down-alt dashicons-arrow-up-alt' );
						$icon.addClass( isExpanded ? 'dashicons-arrow-down-alt' : 'dashicons-arrow-up-alt' );
					}

					if ( nextText ) {
						$toggle.find( '.epofw-accordion-toggle-text' ).text( nextText );
					}
				}

				$toggle.off( 'click.epofwAccordion' ).on(
					'click.epofwAccordion',
					function () {
						var isExpanded = $toggle.attr( 'aria-expanded' ) === 'true';
						epofwUpdateAccordionState( ! isExpanded, true );
					}
				);

				if ( typeof defaultOpen === 'undefined' ) {
					defaultOpen = index === 0;
				}

				epofwUpdateAccordionState( defaultOpen ? true : $toggle.attr( 'aria-expanded' ) === 'true', false );
			}
		);
	}

	/**
	 * Handle displaying the appropriate price type notice based on field type and price type selection.
	 *
	 * This function shows/hides pricing notice information based on:
	 * 1. The field type (slider, text, etc.)
	 * 2. The selected price type (pps, cpf, etc.)
	 *
	 * @param {HTMLElement} selectElement - The price type select element that was changed
	 */
	function handlePriceTypeNotice ( selectElement ) {
		var selectedValue = $( selectElement ).val();

		// Get the field type from the new structure
		var main_field_type = null;

		// Method 1: Get from the element's data attribute in the new structure
		var $element = $( selectElement ).closest( '.epofw-element' );
		if ( $element.length ) {
			main_field_type = $element.attr( 'data-element-type' );
		}
		
		// Method 2: Get from the modal's data attribute
		if ( ! main_field_type ) {
			var $modal = $( selectElement ).closest( '.epofw-element-modal' );
			if ( $modal.length ) {
				var $elementInModal = $modal.closest( '.epofw-element' );
				if ( $elementInModal.length ) {
					main_field_type = $elementInModal.attr( 'data-element-type' );
				}
			}
		}
		
		// Method 3: Get from the section's data attribute
		if ( ! main_field_type ) {
			var $section = $( selectElement ).closest( '.epofw-section' );
			if ( $section.length ) {
				var $elementInSection = $section.find( '.epofw-element' ).first();
				if ( $elementInSection.length ) {
					main_field_type = $elementInSection.attr( 'data-element-type' );
				}
			}
		}

		// Now handle the custom price formula display for text fields
		var $customFormulaInfo = $( selectElement ).closest( '.epofw-price-extra-fields-container' ).find( '.epofw-custom-price-formula-info' );
		
		if ( $customFormulaInfo.length ) {			
			if ( selectedValue === 'cpf' ) {
				$customFormulaInfo.addClass( 'active' ).removeClass( 'show' ).removeAttr( 'style' );
			} else {
				$customFormulaInfo.removeClass( 'active show' ).attr( 'style', 'display: none;' );
			}
		}
	}

	function forAllFilter () {
		jQuery( 'li .epofw_data_condition' ).each(
			function () {
				var current_condition_val = $( this ).val();
				if ( 'product_qty' !== current_condition_val && 'date_picker' !== current_condition_val ) {
					if ( 'user_role' !== current_condition_val ) {
						selectFilter( '.epofw_condition_data_class_' + current_condition_val, 'epofw_get_data_based_on_cd', current_condition_val );
					} else {
						selectFilter2( '.epofw_condition_data_class_' + current_condition_val, 'epofw_get_data_based_on_cd', current_condition_val );
					}
				}
			}
		);

		// Ensure all additional rule elements have proper name attributes
		jQuery( '.additional_rule_ul' ).each( function() {
			var $rule = $( this );
			var attrKey = $rule.attr( 'data-attr-key' );
			if ( attrKey ) {
				$rule.find( 'select.epofw_data_condition' ).attr( 'name', 'epofw_data[additional_rule_data][' + attrKey + '][condition]' );
				$rule.find( 'select.epofw_data_operator' ).attr( 'name', 'epofw_data[additional_rule_data][' + attrKey + '][operator]' );
				$rule.find( 'select.epofw_condition_data_class' ).attr( 'name', 'epofw_data[additional_rule_data][' + attrKey + '][value][]' );
				$rule.find( 'input.epofw_condition_input_data_class' ).attr( 'name', 'epofw_data[additional_rule_data][' + attrKey + '][value][]' );
			}
		});
	}

	function cpoAllowSpecialCharacter ( str ) {
		return str.replace( '&#8211;', '–' ).replace( '&gt;', '>' ).replace( '&lt;', '<' ).replace( '&#197;', 'Å' );
	}

	function selectFilter2 ( filterBasedOnClass, ajaxAction, current_val ) {
		jQuery( filterBasedOnClass ).each(
			function () {
				jQuery( filterBasedOnClass ).select2(
					{
						ajax : {
							url            : epofw_var.ajaxurl,
							dataType       : 'json',
							delay          : 250,
							type           : 'post',
							data           : function ( params ) {
								return {
									value                      : params.term,
									current_condition          : current_val,
									action                     : ajaxAction,
									get_data_based_on_cd_nonce : epofw_var.get_data_based_on_cd_nonce,
									page                       : params.page || 1,
									per_page                   : 50
								};
							},
							processResults : function ( data, params ) {
								params.page = params.page || 1;
								var options = [];
								var results = data.results || data;
								if ( results && Array.isArray( results ) ) {
									$.each(
										results,
										function ( index, text ) {
											options.push(
												{
													id : text[ 0 ],
													text : cpoAllowSpecialCharacter( text[ 1 ] )
												}
											);
										}
									);
								}
								return {
									results    : options,
									pagination : {
										more : data.pagination ? data.pagination.more : false
									}
								};
							},
							cache          : true
						},
					}
				);
			}
		);
	}

	function selectFilter ( filterBasedOnClass, ajaxAction, current_val ) {
		jQuery( filterBasedOnClass ).each(
			function () {
				jQuery( filterBasedOnClass ).select2(
					{
						ajax               : {
							url            : epofw_var.ajaxurl,
							dataType       : 'json',
							delay          : 250,
							type           : 'post',
							data           : function ( params ) {
								return {
									value                      : params.term,
									current_condition          : current_val,
									action                     : ajaxAction,
									get_data_based_on_cd_nonce : epofw_var.get_data_based_on_cd_nonce,
									page                       : params.page || 1,
									per_page                   : 50
								};
							},
							processResults : function ( data, params ) {
								params.page = params.page || 1;
								var options = [];
								var results = data.results || data;
								if ( results && Array.isArray( results ) ) {
									$.each(
										results,
										function ( index, text ) {
											options.push(
												{
													id : text[ 0 ],
													text : cpoAllowSpecialCharacter( text[ 1 ] )
												}
											);
										}
									);
								}
								return {
									results    : options,
									pagination : {
										more : data.pagination ? data.pagination.more : false
									}
								};
							},
							cache          : true
						},
						minimumInputLength : 3
					}
				);
			}
		);
	}

	var AWS_ADMIN = {
		init : function () {
			forAllFilter();
			jQuery( document ).on( 'click', '.epofw-add-option', AWS_ADMIN.cloneOptions );
			jQuery( document ).on( 'click', '#remove-opt, .epofw-remove-option', AWS_ADMIN.removeOptions );
			jQuery( document ).on( 'change', '.epofw_data_condition', AWS_ADMIN.getDataBasedOnCondition );
			jQuery( document ).on( 'click', '#add-new-conditional', AWS_ADMIN.addNewConditionalGroup );
			jQuery( document ).on( 'click', '.conditional_action_remove .remove-location-rule', AWS_ADMIN.removeConditionalRule );
			// Nested conditional logic handlers (v4.4.4+).
			jQuery( document ).on( 'click', '.epofw-add-group', AWS_ADMIN.addNestedRuleGroup );
			jQuery( document ).on( 'click', '.epofw-remove-group', AWS_ADMIN.removeNestedRuleGroup );
			jQuery( document ).on( 'click', '.epofw-add-condition', AWS_ADMIN.addNestedCondition );
			jQuery( document ).on( 'click', '.epofw-remove-condition', AWS_ADMIN.removeNestedCondition );
			jQuery( document ).on( 'change', '.epofw-logic-between-groups', AWS_ADMIN.updateGroupLogicSeparators );
			jQuery( document ).on( 'click', '.select_all_ad', AWS_ADMIN.onSelectAllMultiSelect );
			jQuery( document ).on( 'click', '.clear_all_ad', AWS_ADMIN.onClearAllMultiSelect );
			jQuery( document ).on( 'click', '.disable_all_options', AWS_ADMIN.disableAllOptions );
			jQuery( document ).on( 'click', '.epofw_options_chk', AWS_ADMIN.epofwSingleOptions );
			jQuery( document ).on( 'change', '.epofw_af_current_field_show_hide', AWS_ADMIN.epofwAfCurrentFieldShowHide );
			// Add event listener for addon_price_type changes.
			jQuery( document ).on( 'change', '.epofw_addon_price_type', AWS_ADMIN.handleAddonPriceTypeChange );
			jQuery( document ).on( 'click', '.epofw-review-notice .notice-dismiss', AWS_ADMIN.epofwDismissNotice );
			jQuery( document ).on( 'click', '.epofw-edit-element, .epofw-element-edit', AWS_ADMIN.epofwElementEdit );
			
			// Initialize show/hide functionality for required fields
			jQuery( document ).on( 'change', '.epofw-has-sub', AWS_ADMIN.handleShowHideFields );

			jQuery( document ).on( 'click', '.epofw-toggle-btn', AWS_ADMIN.epofwToggleStatusOnList );
			jQuery( document ).on( 'click', '.epofw-add-element, .epofw-add-first-element', AWS_ADMIN.handleMainAddElement );
			jQuery( document ).on( 'click', '.epofw-add-element-btn', AWS_ADMIN.epofwAddElement );
			jQuery( document ).on( 'click', '.epofw-add-section, .epofw-add-first-section, .epofw-add-section-btn', AWS_ADMIN.epofwAddSection );
			jQuery( document ).on( 'click', '.epofw-element-delete, .epofw-section-delete', AWS_ADMIN.epofwDeleteElement );
			
			// Handle edit button clicks in addon list page
			jQuery( document ).on( 'click', '.epofw-edit-btn', AWS_ADMIN.handleEditButtonClick );
			jQuery( document ).on( 'click', '.epofw-tab-btn', AWS_ADMIN.epofwTabBtn );
			
			jQuery( document ).on( 'click', '.epofw-modal-close, .epofw-modal-cancel, .epofw-modal-overlay', AWS_ADMIN.epofwCloseElementModal );
			jQuery( document ).on( 'click', '.epofw-view-toggle', AWS_ADMIN.epofwViewToggle );
			jQuery( document ).on( 'click', '.epofw-view-more-link', AWS_ADMIN.epofwViewMoreToggle );

			jQuery( document ).on( 'click', '.epofw-save-element', AWS_ADMIN.epofwSaveElement );
			jQuery( document ).on( 'click', '.epofw-save-section', AWS_ADMIN.epofwSaveSection );
			
			jQuery( document ).on( 'input', '.epofw-dynamic-code-example', AWS_ADMIN.updateDynamicCodeExample );
			jQuery( document ).on( 'change', '.epofw-label-code-example, .epofw-subtitle-code-example', AWS_ADMIN.updateUpdateCodeExample );
			jQuery( document ).on( 'keyup', '.epofw-section-title-edit', AWS_ADMIN.sectionTitleEdit );
			jQuery( document ).on( 'click', '.epofw-section-edit', AWS_ADMIN.sectionEdit );
			jQuery( document ).on( 'click', '.epofw-section-title span', AWS_ADMIN.sectionTitleEditOnSpan );
			jQuery( document ).on( 'click', '.epofw-section-title .dashicons-arrow-down-alt, .epofw-section-title .dashicons-arrow-up-alt', AWS_ADMIN.toggleSectionAccordion );
			
			jQuery( document ).on( 'click', '.epofw-delete-btn', AWS_ADMIN.handleDeleteButtonClick );
			jQuery( document ).on( 'click', '.epofw-duplicate-btn', AWS_ADMIN.handleDuplicateButtonClick );
			jQuery( document ).on( 'click', '.epofw-export-btn', AWS_ADMIN.handleExportButtonClick );
		jQuery( document ).on( 'click', '.epofw-import-btn', AWS_ADMIN.handleImportButtonClick );
		jQuery( document ).on( 'submit', 'form', AWS_ADMIN.handleAddonFormSubmit );

		// Add novalidate to addon form to disable browser's native validation
		// We handle validation ourselves via JavaScript
		jQuery('form').has('.epofw-save-addon').attr('novalidate', 'novalidate');

			// Column management functionality (Row = horizontal group, Column = individual items)
			jQuery( document ).on( 'click', '.epofw-add-row-btn', AWS_ADMIN.showRowSelectionModal );
			jQuery( document ).on( 'click', '.epofw-row-option', AWS_ADMIN.selectRowOption );
			jQuery( document ).on( 'click', '.epofw-create-rows', AWS_ADMIN.createRows );
			jQuery( document ).on( 'click', '.epofw-row-delete', AWS_ADMIN.deleteRow );
			jQuery( document ).on( 'click', '.epofw-add-column-btn', AWS_ADMIN.addColumnToRowGroup );

			// Columns container management (uses same modal as "Add Row")
			jQuery( document ).on( 'click', '.epofw-add-columns-btn', AWS_ADMIN.showColumnsSelectionModal );

			// Row group management functionality
			jQuery( document ).on( 'click', '.epofw-row-group-edit', AWS_ADMIN.rowGroupEdit );
			jQuery( document ).on( 'click', '.epofw-row-group-delete', AWS_ADMIN.rowGroupDelete );
			jQuery( document ).on( 'click', '.epofw-columns-delete', AWS_ADMIN.deleteColumnsGroup );
			jQuery( document ).on( 'click', '.epofw-save-row', AWS_ADMIN.saveRowSettings );
			
			// Column (row container) management functionality
			jQuery( document ).on( 'click', '.epofw-save-column', AWS_ADMIN.saveColumnSettings );

			// Section and Field status toggle handlers
			jQuery( document ).on( 'change', '.epofw-section-status-checkbox', AWS_ADMIN.handleSectionStatusToggle );
			jQuery( document ).on( 'change', '.epofw-field-status-checkbox', AWS_ADMIN.handleFieldStatusToggle );

			// Sync modal field_status checkbox back to the toggle
			jQuery( document ).on( 'change', '.epofw-modal-body input[name*="[field_status]"]', AWS_ADMIN.handleModalFieldStatusChange );

			// Sync section modal status checkbox back to the toggle
			jQuery( document ).on( 'change', '.epofw-section-modal input[name*="][status]"]', AWS_ADMIN.handleModalSectionStatusChange );

			// Initialize sortable for existing columns containers (from PHP rendering)
			AWS_ADMIN.initColumnsSortable();
		},

		/**
		 * Initialize sortable for all existing columns containers
		 * This enables drag-and-drop reordering of columns
		 */
		initColumnsSortable: function() {
			var $allColumns = jQuery('.epofw-columns');

			$allColumns.each(function() {
				var $columnsContainer = jQuery(this);

				// Skip if already initialized
				if ($columnsContainer.hasClass('ui-sortable')) {
					return;
				}

				// Find the columns content div
				var $columnsContent = $columnsContainer.find('.epofw-columns-content');

				if (!$columnsContent.length) {
					return;
				}

				// Initialize sortable on the columns-content, not the container
				$columnsContent.sortable({
					items: '> .epofw-column, > .epofw-row-container',
					handle: '.epofw-column-drag',
					placeholder: 'epofw-column-placeholder',
					tolerance: 'pointer',
					axis: 'x',
					start: function(event, ui) {
						ui.placeholder.height(ui.item.height());
						ui.item.addClass('dragging');
					},
					stop: function(event, ui) {
						ui.item.removeClass('dragging');
						// Update column numbers after reordering
						AWS_ADMIN.updateColumnNumbers($columnsContainer);
					}
				});
			});
		},
		// Handler for addon_price_type changes.
		handleAddonPriceTypeChange        : function () {
			handlePriceTypeNotice( this );
		},
		epofwAfCurrentFieldShowHide       : function () {
			var parentId      = $( this ).closest( '.epofw-element-modal' ).attr( 'id' );
			var fieldParentId = $( this ).attr( 'id' );
			if ( this.checked ) {
				$( '#' + parentId + ' .show_on_' + fieldParentId ).addClass( 'epofw-hide' );
				$( '#' + parentId + ' .hide_on_' + fieldParentId ).addClass( 'epofw-hide' );
			} else {
				$( '#' + parentId + ' .show_on_' + fieldParentId ).removeClass( 'epofw-hide' );
				$( '#' + parentId + ' .hide_on_' + fieldParentId ).removeClass( 'epofw-hide' );
			}
		},
		epofwSingleOptions                : function () {
			if ( jQuery( '.epofw_options_chk_all' ).is( ':checked' ) ) {
				return;
			}
			if ( jQuery( '.epofw_options_chk' ).is( ':checked' ) ) {
				$( '.disable_all_options' ).removeClass( 'hide' ).addClass( 'show' );
			} else {
				$( '.disable_all_options' ).removeClass( 'show' ).addClass( 'hide' );
			}
		},
		disableAllOptions                 : function () {
			var fieldIds = [];
			jQuery( '.accordion_cls' ).each(
				function () {
					if ( jQuery( this ).find( '.epofw_chk_data .epofw_options_chk' ).is( ':checked' ) ) {
						fieldIds.push( jQuery( this ).attr( 'data-id' ) );
					}
				}
			);
			jQuery.ajax(
				{
					type    : 'post',
					url     : epofw_var.ajaxurl,
					data    : {
						action               : 'epofw_disbale_field_options',
						get_post_id          : epofw_var.get_post_id,
						field_ids            : fieldIds,
						disable_option_nonce : epofw_var.disable_option_nonce,
					},
					success : function ( response ) {
						if ( response ) {
							if ( true === response.success ) {
								window.location.reload();
							} else {
								var pTag = document.createElement( 'p' );
								pTag.setAttribute( 'class', 'error epofw_disable_option_error' );
								var errorMessage = document.createTextNode( response.data.msg );
								pTag.appendChild( errorMessage );

								var elementTag = document.getElementsByClassName( 'addon_fields_header' )[ 0 ];
								elementTag.append( pTag );
							}
						}
					},
					error   : function () {
						// AJAX error occurred.
					}
				}
			);
		},
		removeConditionalRule             : function () {
			$( this ).parent().parent().remove();
		},
		// Nested conditional logic functions (v4.4.4+).
		addNestedRuleGroup                : function () {
			var $container = $( '#epofw_additional_rules_section .epofw-rule-groups-container' );
			var groupId    = 'group_' + Math.floor( Math.random() * 1000000000 );
			var $lastGroup = $container.find( '.epofw-rule-group:last' );
			var $template  = $lastGroup.length ? $lastGroup.clone() : $( '.epofw-rule-group:first' ).clone();

			if ( ! $template.length ) {
				// Create empty group template if no groups exist.
				var groupHtml = '<div class="epofw-rule-group" data-group-id="' + groupId + '">' +
					'<div class="epofw-group-header">' +
					'<span class="epofw-group-logic-label">Match:</span>' +
					'<select name="additional_rule_data[groups][' + groupId + '][logic]" class="epofw-group-logic" title="Logic for conditions within this group">' +
					'<option value="and">All (AND)</option>' +
					'<option value="or">Any (OR)</option>' +
					'</select>' +
					'<button type="button" class="button epofw-remove-group epofw-icon -minus" title="Remove Group"></button>' +
					'</div>' +
					'<div class="epofw-conditions-container"></div>' +
					'<div class="epofw-add-condition-action">' +
					'<button type="button" class="button epofw-add-condition" data-group-id="' + groupId + '">Add Condition</button>' +
					'</div>' +
					'</div>';
				$container.append( groupHtml );
				AWS_ADMIN.addNestedCondition.call( { target: $container.find( '.epofw-add-condition:last' )[0] } );
				return;
			}

			// Update group ID in cloned template.
			$template.attr( 'data-group-id', groupId );
			$template.find( '.epofw-group-logic' ).attr( 'name', 'additional_rule_data[groups][' + groupId + '][logic]' );
			$template.find( '.epofw-add-condition' ).attr( 'data-group-id', groupId );
			$template.find( '.epofw-conditions-container' ).empty(); // Clear conditions.

			// Update all form field names in conditions container.
			$template.find( '.additional_rule_ul' ).each( function () {
				var $conditionRow = $( this );
				var conditionId   = 'cond_' + Math.floor( Math.random() * 1000000000 );
				$conditionRow.attr( 'data-group-id', groupId ).attr( 'data-condition-id', conditionId );
				$conditionRow.find( 'select.epofw_data_condition' ).attr( 'name', 'additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + '][condition]' );
				$conditionRow.find( 'select.epofw_data_operator' ).attr( 'name', 'additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + '][operator]' );
				$conditionRow.find( 'select.epofw_condition_data_class' ).attr( 'name', 'additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + '][value][]' );
				$conditionRow.find( 'input.epofw_condition_input_data_class' ).attr( 'name', 'additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + '][value][]' );
			} );

			$container.append( $template );

			// Add logic separator before the new group (if there are existing groups).
			var $existingGroups = $container.find( '.epofw-rule-group' );
			if ( $existingGroups.length > 1 ) {
				// Get the logic_between_groups value.
				var logicBetween = $( '.epofw-logic-between-groups' ).val() || 'and';
				var logicText    = 'or' === logicBetween ? 'OR' : 'AND';
				var $separator   = $( '<div class="epofw-group-logic-separator" data-logic="' + logicBetween + '"><span class="epofw-group-logic-text">' + logicText + '</span></div>' );
				$template.before( $separator );
			}

			// If template was empty, add one condition.
			if ( $template.find( '.additional_rule_ul' ).length === 0 ) {
				AWS_ADMIN.addNestedCondition.call( { target: $template.find( '.epofw-add-condition' )[0] } );
			}
		},
		removeNestedRuleGroup             : function () {
			var $group = $( this ).closest( '.epofw-rule-group' );
			// Remove associated separator (the one before this group).
			$group.prev( '.epofw-group-logic-separator' ).remove();
			$group.remove();
			// Clean up separators if only one group remains.
			var $container = $( '#epofw_additional_rules_section .epofw-rule-groups-container' );
			var $groups    = $container.find( '.epofw-rule-group' );
			if ( $groups.length <= 1 ) {
				$container.find( '.epofw-group-logic-separator' ).remove();
			}
		},
		addNestedCondition                : function () {
			var $button      = $( this );
			var groupId      = $button.attr( 'data-group-id' ) || $button.closest( '.epofw-rule-group' ).attr( 'data-group-id' );
			var $group       = $button.closest( '.epofw-rule-group' );
			var $container   = $group.find( '.epofw-conditions-container' );
			var conditionId  = 'cond_' + Math.floor( Math.random() * 1000000000 );
			var $lastCondition = $container.find( '.additional_rule_ul:last' );
			var $template    = $lastCondition.length ? $lastCondition.clone() : $( '.epofw-conditions-container .additional_rule_ul:first' ).clone();

			if ( ! $template.length ) {
				// Build condition options HTML from localized data.
				var conditionOptionsHtml = '';
				if ( typeof epofw_var !== 'undefined' && epofw_var.condition_options ) {
					for ( var key in epofw_var.condition_options ) {
						if ( epofw_var.condition_options.hasOwnProperty( key ) ) {
							conditionOptionsHtml += '<option value="' + key + '">' + epofw_var.condition_options[ key ] + '</option>';
						}
					}
				}
				// Create empty condition template.
				var conditionHtml = '<ul class="additional_rule_ul epofw-condition-row" data-group-id="' + groupId + '" data-condition-id="' + conditionId + '">' +
					'<li><select title="conditional_name" name="additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + '][condition]" class="epofw_data_condition epofw_data_condition">' + conditionOptionsHtml + '</select></li>' +
					'<li><select title="conditional_operator" name="additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + '][operator]" class="epofw_data_operator"></select></li>' +
					'<li class="epofw_condition_field_data"></li>' +
					'<li class="conditional_action_remove"><button type="button" class="button epofw-remove-condition epofw-icon -minus" title="Remove Condition"></button></li>' +
					'</ul>';
				$container.append( conditionHtml );
				// Trigger change to populate operator dropdown and value field.
				$container.find( '.epofw_data_condition:last' ).trigger( 'change' );
				return;
			}

			// Update condition ID in cloned template.
			$template.attr( 'data-group-id', groupId ).attr( 'data-condition-id', conditionId );
			var $conditionSelect = $template.find( 'select.epofw_data_condition' );
			$conditionSelect.attr( 'name', 'additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + '][condition]' );
			// Set default value to first option if available, otherwise 'product'.
			if ( $conditionSelect.find( 'option' ).length > 0 ) {
				var firstOptionValue = $conditionSelect.find( 'option:first' ).val();
				$conditionSelect.val( firstOptionValue || 'product' );
			} else {
				$conditionSelect.val( 'product' );
			}
			$template.find( 'select.epofw_data_operator' ).attr( 'name', 'additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + '][operator]' );
			$template.find( 'select.epofw_condition_data_class' ).attr( 'name', 'additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + '][value][]' ).attr( 'id', 'epofw_condition_data_id_' + groupId + '_' + conditionId ).val( null );
			$template.find( 'input.epofw_condition_input_data_class' ).attr( 'name', 'additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + '][value][]' ).attr( 'id', 'epofw_condition_input_data_' + groupId + '_' + conditionId ).val( '' );
			$template.find( '.epofw_condition_field_data' ).html( '' ); // Clear value field.

			$container.append( $template );

			// Initialize condition dropdown and trigger change to populate operator dropdown and field data.
			if ( $conditionSelect.length ) {
				$conditionSelect.trigger( 'change' );
			}
		},
		removeNestedCondition             : function () {
			var $condition = $( this ).closest( '.additional_rule_ul' );
			$condition.remove();
		},
		updateGroupLogicSeparators        : function () {
			var selectedLogic = $( this ).val();
			var logicText     = 'or' === selectedLogic ? 'OR' : 'AND';
			$( '.epofw-group-logic-separator' ).each( function() {
				$( this ).attr( 'data-logic', selectedLogic );
				$( this ).find( '.epofw-group-logic-text' ).text( logicText );
			} );
		},
		onClearAllMultiSelect             : function () {
			var parentId      = $( this ).parent().parent().parent().attr( 'id' );
			var dataSelection = jQuery( '#' + parentId + ' .epofw_condition_field_data select' );
			dataSelection.val( null ).trigger( 'change' );
		},
		onSelectAllMultiSelect            : function () {
			var parentId      = $( this ).parent().parent().parent().attr( 'id' );
			var dataSelection = jQuery( '#' + parentId + ' .epofw_condition_field_data select' );
			var datCnd        = jQuery( this ).attr( 'data-cnd' );
			var datNonce      = jQuery( this ).attr( 'data-nonce' );
			jQuery.ajax(
				{
					type     : 'post',
					dataType : 'json',
					url      : epofw_var.ajaxurl,
					data     : {
						action   : 'epofw_select_all_product',
						data_cnd : datCnd,
						nonce    : datNonce
					},
					success  : function ( data ) {
						if ( data ) {
							// Clear existing selections first to avoid duplicates.
							dataSelection.empty();
							$.each(
								data,
								function ( index, text ) {
									if ( text && text[ 1 ] ) {
										var newOption = new Option( cpoAllowSpecialCharacter( text[ 1 ] ), text[ 0 ], true, true );
										dataSelection.append( newOption ).trigger( 'change' );
									}
								}
							);
						}
					},
					error    : function () {
						// AJAX error occurred.
					}
				}
			);
		},
		addNewConditionalGroup            : function () {
			var li_elem = $( this ).parents().find( '.additional_rule_ul:last' );
			var num     = Math.floor( Math.random() * 1000000000 );

			var clon_id = li_elem.clone().prop( 'id', 'additional_rule_ul_' + num );
			clon_id.attr( 'data-attr-key', num );
			li_elem.after( clon_id );
			var totalLength = $( '.additional_rule_ul' ).length;
			if ( totalLength > 1 && $( '.conditional_action_remove' ).length === 0 ) {
				var createLi = document.createElement( 'li' );
				createLi.setAttribute( 'class', 'conditional_action_remove' );
				var createLia = document.createElement( 'a' );
				createLia.setAttribute( 'href', '#' );
				createLia.setAttribute( 'class', 'epofw-icon -minus remove-location-rule' );
				createLi.appendChild( createLia );
				clon_id.find( 'li:last' ).after( createLi );
			}
			clon_id.find( 'li select.epofw_data_condition' ).attr( 'name', 'epofw_data[additional_rule_data][' + num + '][condition]' );
			clon_id.find( 'li select.epofw_data_operator' ).attr( 'name', 'epofw_data[additional_rule_data][' + num + '][operator]' );
			clon_id.find( 'li select.epofw_condition_data_class' ).attr( 'name', 'epofw_data[additional_rule_data][' + num + '][value][]' );
			clon_id.find( 'li select.epofw_condition_data_class' ).attr( 'id', 'epofw_condition_data_id_' + num );
			clon_id.find( 'li input.epofw_condition_input_data_class' ).attr( 'name', 'epofw_data[additional_rule_data][' + num + '][value][]' );
			clon_id.find( 'li input.epofw_condition_input_data_class' ).attr( 'id', 'epofw_condition_input_data_' + num );
		},
		getDataBasedOnCondition           : function () {
			var $conditionRow = $( this ).closest( '.additional_rule_ul' );
			var main_parent_attr_id   = $conditionRow.attr( 'id' );
			var main_parent_attr_key  = $conditionRow.attr( 'data-attr-key' );
			var groupId               = $conditionRow.attr( 'data-group-id' );
			var conditionId           = $conditionRow.attr( 'data-condition-id' );
			var current_condition_val = $( this ).val();
			var append_value_element;
			var $td_apsub_elem;
			var isNested              = groupId && conditionId; // Check if nested structure.
			var fieldNamePrefix, fieldIdPrefix;

			if ( isNested ) {
				// Nested structure: additional_rule_data[groups][group_id][conditions][condition_id][...]
				fieldNamePrefix = 'additional_rule_data[groups][' + groupId + '][conditions][' + conditionId + ']';
				fieldIdPrefix   = groupId + '_' + conditionId;
				// Ensure condition and operator name attributes are set correctly for nested structure.
				$conditionRow.find( 'select.epofw_data_condition' ).attr( 'name', fieldNamePrefix + '[condition]' );
				$conditionRow.find( 'select.epofw_data_operator' ).attr( 'name', fieldNamePrefix + '[operator]' );
				// Populate operator select if empty.
				var $operatorSelect = $conditionRow.find( 'select.epofw_data_operator' );
				if ( $operatorSelect.length && $operatorSelect.find( 'option' ).length === 0 ) {
					if ( typeof epofw_var !== 'undefined' && epofw_var.operator_options ) {
						for ( var opKey in epofw_var.operator_options ) {
							if ( epofw_var.operator_options.hasOwnProperty( opKey ) ) {
								$operatorSelect.append( '<option value="' + opKey + '">' + epofw_var.operator_options[ opKey ] + '</option>' );
							}
						}
					}
				}
				// Clear all existing field data when condition changes.
				$conditionRow.find( 'li.epofw_condition_field_data' ).html( '' );
				append_value_element = $conditionRow.find( 'li.epofw_condition_field_data' )[0];
			} else {
				// Old flat structure: epofw_data[additional_rule_data][attr_key][...]
				fieldNamePrefix = 'epofw_data[additional_rule_data][' + main_parent_attr_key + ']';
				fieldIdPrefix   = main_parent_attr_key;
				// Ensure condition and operator name attributes are set correctly for old structure.
				if ( main_parent_attr_id ) {
					$( '#' + main_parent_attr_id ).find( 'select.epofw_data_condition' ).attr( 'name', fieldNamePrefix + '[condition]' );
					$( '#' + main_parent_attr_id ).find( 'select.epofw_data_operator' ).attr( 'name', fieldNamePrefix + '[operator]' );
					// Clear all existing field data when condition changes.
					$( '#' + main_parent_attr_id ).find( 'li.epofw_condition_field_data' ).html( '' );
					append_value_element = document.getElementById( main_parent_attr_id ).getElementsByClassName( 'epofw_condition_field_data' )[ 0 ];
				} else {
					return; // No parent element found.
				}
			}

			if ( 'product_qty' === current_condition_val || 'date_picker' === current_condition_val ) {
				// Input field type (product_qty, date_picker).
				var inputId   = 'epofw_condition_input_data_' + fieldIdPrefix;
				var inputName = fieldNamePrefix + '[value][]';

				$td_apsub_elem = document.createElement( 'input' );
				$td_apsub_elem.setAttribute( 'type', 'text' );
				$td_apsub_elem.setAttribute( 'class', 'epofw_condition_data_class_' + current_condition_val + ' epofw_condition_input_data_class' );
				$td_apsub_elem.setAttribute( 'id', inputId );
				$td_apsub_elem.setAttribute( 'name', inputName );
				if ( 'product_qty' === current_condition_val ) {
					$td_apsub_elem.setAttribute( 'placeholder', 'Enter Product Qty' );
				}
				if ( 'date_picker' === current_condition_val ) {
					$td_apsub_elem.setAttribute( 'placeholder', 'Enter Date' );
				}
				append_value_element.appendChild( $td_apsub_elem );
				if ( 'date_picker' === current_condition_val ) {
					var classDatePicker = $( '.epofw_condition_data_class_' + current_condition_val );
					if ( classDatePicker.length ) {
						classDatePicker.datepicker( { dateFormat : 'dd-mm-yy' } );
					}
				}
			} else {
				// Select field type (product, category, tag, etc.).
				var selectId   = 'epofw_condition_data_id_' + fieldIdPrefix;
				var selectName = fieldNamePrefix + '[value][]';
				// Field data is already cleared above, so append_value_element is already set.

				$td_apsub_elem = document.createElement( 'select' );
				$td_apsub_elem.setAttribute( 'class', 'epofw_condition_data_class_' + current_condition_val + ' epofw_condition_data_class multiselect2' );
				$td_apsub_elem.setAttribute( 'id', selectId );
				$td_apsub_elem.setAttribute( 'name', selectName );
				$td_apsub_elem.setAttribute( 'multiple', 'multiple' );

				append_value_element.appendChild( $td_apsub_elem );

				// Add Select All/Clear All buttons.
				var createDiv = document.createElement( 'div' );
				createDiv.setAttribute( 'class', 'epofw_all_selection_btn' );

				var createButton = document.createElement( 'button' );
				createButton.setAttribute( 'type', 'button' );
				createButton.setAttribute( 'class', 'button select_all_ad' );
				createButton.setAttribute( 'data-cnd', current_condition_val );
				createButton.setAttribute( 'data-nonce', epofw_var.select_all_nonce );
				createButton.appendChild( document.createTextNode( 'Select All' ) );
				createDiv.appendChild( createButton );

				var createButton1 = document.createElement( 'button' );
				createButton1.setAttribute( 'type', 'button' );
				createButton1.setAttribute( 'class', 'button clear_all_ad' );
				createButton1.setAttribute( 'data-cnd', current_condition_val );
				createButton1.appendChild( document.createTextNode( 'Clear All' ) );
				createDiv.appendChild( createButton1 );

				append_value_element.appendChild( createDiv );
				forAllFilter();
			}
		},
		cloneOptions: function () {
			var li_elem = this.parentElement.parentElement.querySelector( 'div.opt-li:last-child' );
			var num     = parseInt( li_elem.id.match( /\d+/g ), 10 ) + 1;
			var clon_id = li_elem.cloneNode( true );
			clon_id.id  = 'opt-li-' + num;
			
			if ( clon_id.querySelector( '.epofw-cs-colorswitcher' ) ) {
				var dataIdUn = clon_id.querySelector( '.epofw-cs-colorswitcher' ).id;
				$( '#' + dataIdUn ).wpColorPicker();
			}
			
			var inputs = clon_id.querySelectorAll( 'input' );
			inputs.forEach(
				function ( elem ) {
					var inpElem = elem;
					inpElem.id  = 'select-opt-value-' + num;
					if ( inpElem.classList.contains( 'epofw-cs-colorswitcher' ) ) {
						inpElem.id = 'select-opt-epofw-cs-colorswitcher-' + num;
					}
				}
			);
			
			clon_id.querySelectorAll( 'input' ).forEach( function( input ) {
				input.value = '';
			} );
			
			li_elem.insertAdjacentElement( 'afterend', clon_id );
			
			var visibleOptLi = $( '.epofw-tab-content[data-tab="field-options"] .opt-li:visible' );
			if ( visibleOptLi.length > 1 ) {
				visibleOptLi.find( '.remove-opt-btn' ).show();
			} else {
				visibleOptLi.find( '.remove-opt-btn' ).hide();
			}
		},
		removeOptions                     : function ( e ) {
			e.preventDefault();
			var optLi = $( this ).closest( '.opt-li' );
			if ( optLi.length ) {
				optLi.remove();
			}

			optLi = $( '.epofw-tab-content[data-tab="field-options"] .opt-li:visible' );
			if ( optLi.length ) {
				var optLiCount = parseInt( optLi.length );
				if ( optLiCount > 1 ) {
					$( optLi ).find( '.remove-opt-btn' ).show();
				} else {
					$( optLi ).find( '.remove-opt-btn' ).hide();
				}
			}
		},
		epofwDismissNotice                : function () {
			jQuery.ajax(
				{
					type    : 'post',
					url     : epofw_var.ajaxurl,
					data    : {
						action                      : 'epofw_dismiss_review_notice',
						dismiss_review_notice_nonce : epofw_var.dismiss_review_notice_nonce
					},
					success : function ( response ) {
						if ( response ) {
							if ( true === response.success ) {
								$( '.epofw-review-notice' ).remove();
							}
						}
					}
				}
			);
		},

		epofwTabBtn: function ( e ) {
			e.preventDefault();
			var tabId = $(this).data('tab');
			var modal = $(this).closest('.epofw-element-modal, .epofw-section-modal');
			
			// Remove active class from all tabs and contents
			modal.find('.epofw-tab-btn').removeClass('active');
			modal.find('.epofw-tab-content').removeClass('active');
			
			// Add active class to clicked tab and corresponding content
			$(this).addClass('active');
			modal.find('.epofw-tab-content[data-tab="' + tabId + '"]').addClass('active');

			var tab = $(this).data('tab');
			AWS_ADMIN.epofwSwitchTab(tab);
		},

		epofwSwitchTab: function (tab) {
			$('.epofw-tab-btn').removeClass('active');
            $('.epofw-tab-btn[data-tab="' + tab + '"]').addClass('active');
            
            $('.epofw-tab-pane').removeClass('active');
            $('#' + tab + '-tab').addClass('active');
		},

		epofwCloseElementModal: function () {
			var elementId = $(this).closest('.epofw-element-modal, .epofw-section-modal').attr('id');
			AWS_ADMIN.closeElementModal( elementId );
		},

		epofwViewToggle: function ( e ) {
			e.preventDefault();
			var view = $(this).data('view');
			AWS_ADMIN.switchView(view);
		},

		epofwViewMoreToggle: function ( e ) {
			e.preventDefault();
			var $link = $(this);
			var $hiddenItems = $link.siblings('.epofw-hidden-items');
			var viewMoreText = (typeof epofw_var !== 'undefined' && epofw_var.strings && epofw_var.strings.view_more) ? epofw_var.strings.view_more : 'View more';
			var viewLessText = (typeof epofw_var !== 'undefined' && epofw_var.strings && epofw_var.strings.view_less) ? epofw_var.strings.view_less : 'View less';

			if ($hiddenItems.is(':visible')) {
				$hiddenItems.hide();
				$link.text(viewMoreText);
			} else {
				$hiddenItems.show();
				$link.text(viewLessText);
			}
		},

		switchView: function(view) {
			// Remove active class from all toggle buttons
			$('.epofw-view-toggle').each(function() {
				$(this).removeClass('active');
			});
            $('.epofw-view-toggle[data-view="' + view + '"]').addClass('active');

            // Save view preference to database
            AWS_ADMIN.saveViewPreference(view);
        },

		// Save view preference to database
		saveViewPreference: function(view) {
			jQuery.ajax({
				type: 'POST',
				url: epofw_var.ajaxurl,
				data: {
					action: 'epofw_save_view_preference',
					view: view,
					nonce: epofw_var.epofw_admin_nonce
				},
				success: function(response) {
					if ( response.success ) {
						$('.epofw-addons-container').removeClass('epofw-addons-grid epofw-addons-list').addClass('epofw-addons-' + view);
					}
				},
				error: function() {
					// Silent fail for view preference
				}
			});
		},

		epofwElementEdit: function() {
			var $editBtn = $(this);
			var elementId = $editBtn.data('element-id');
			var $element = $editBtn.closest('.epofw-element');
			var type = $element.data('element-type');
			var sectionId = $element.closest('.epofw-section').data('section-id') || '';

			// Check if element has validation errors (set during Save validation)
			var hasValidationErrors = $element.hasClass('epofw-element-error');

			var elementSettingsModal = $('#element-settings-modal-' + elementId);

			if (!elementSettingsModal.length) {
				// Modal doesn't exist - create it via AJAX
				AWS_ADMIN.loadElementModalViaAjax(elementId, type, sectionId, hasValidationErrors);
				return;
			}

			AWS_ADMIN.openElementModal(elementSettingsModal, hasValidationErrors);
		},

		// Load element modal via AJAX
		loadElementModalViaAjax: function(elementId, type, sectionId, hasValidationErrors) {
			// Clone the template modal
			var template = $( '#tmpl-epofw-element-settings-modal' ).html();
			var clonedModal = $( template );
			clonedModal.attr( 'id', 'element-settings-modal-' + elementId );

			// Build modal header with PRO badge for premium field types
			var headerText = type.charAt(0).toUpperCase() + type.slice(1) + ' ' + epofw_var.settings;
			var $modalHeader = clonedModal.find( '.epofw-modal-content .epofw-modal-header h3' );
			$modalHeader.text( headerText );

			// Check if this is a premium field type and user is not premium
			if ( !epofw_var.is_premium && epofw_var.premium_field_types && epofw_var.premium_field_types.indexOf( type ) !== -1 ) {
				// Add PRO badge and Upgrade button after the title
				var proBadgeHtml = '<span class="epofw-modal-pro-badge">' +
					'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="12" height="12"><path fill="currentColor" d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z"/></svg> ' +
					epofw_var.pro_label + '</span>' +
					'<a href="' + epofw_var.upgrade_url + '" target="_blank" class="epofw-modal-upgrade-btn">' +
					'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14"><path fill="currentColor" d="M13 5v6h6l-8 8-8-8h6V5h4z" transform="rotate(180 12 12)"/></svg> ' +
					epofw_var.upgrade_to_pro + '</a>';
				$modalHeader.after( proBadgeHtml );
				clonedModal.find( '.epofw-modal-header' ).addClass( 'epofw-premium-field-header' );
			}

			// Append modal to body
			$('body').append( clonedModal );

			// Show modal with loader
			clonedModal.show();
			AWS_ADMIN.showModalLoader( clonedModal, 'loading_settings' );
			clonedModal.data( 'loading', true );

			// Get addon_id
			var addonId = jQuery( 'input[name="addon_id"]' ).val() || new URLSearchParams( window.location.search ).get( 'post' ) || 0;

			// Fetch modal content via AJAX
			jQuery.ajax( {
				type    : 'post',
				url     : epofw_var.ajaxurl,
				data    : {
					action     : 'epofw_element_add',
					element_id : elementId,
					field_type : type,
					section_id : sectionId,
					addon_id   : addonId,
					nonce      : epofw_var.element_add_nonce
				},
				success : function ( response ) {
					clonedModal.data( 'loading', false );

					if ( response.success ) {
						clonedModal.find( '.epofw-modal-content-wrapper' ).html( response.data.content );

						// Initialize after content loads
						setTimeout(function() {
							clonedModal.find('.epofw_colorpicker').each(function() {
								if (!$(this).hasClass('wp-color-picker')) {
									$(this).wpColorPicker();
								}
							});
							AWS_ADMIN.initModalToggles(clonedModal);
							AWS_ADMIN.resetModalTabs(clonedModal);
							AWS_ADMIN.initRealTimeValidation(clonedModal);

							// If element had validation errors, run validation to show them
							if (hasValidationErrors) {
								AWS_ADMIN.validateForm(clonedModal);
							}
						}, 50);
					}
				},
				error   : function () {
					clonedModal.data( 'loading', false );
				}
			} );
		},

		// Helper function to open element modal
		openElementModal: function(elementSettingsModal, hasValidationErrors) {
			if ( !elementSettingsModal || !elementSettingsModal.length ) {
				return;
			}

			// Show the modal first
			elementSettingsModal.show();

			// Check if content is still loading
			if ( elementSettingsModal.data( 'loading' ) ) {
				// Loader is already showing, just wait
				return;
			}

			// Reset modal tabs to first tab
			AWS_ADMIN.resetModalTabs(elementSettingsModal);

			// Initialize real-time validation
			AWS_ADMIN.initRealTimeValidation(elementSettingsModal);

			// Initialize after modal is visible
			setTimeout(function() {
				var colorPickers = elementSettingsModal.find('.epofw_colorpicker');

				colorPickers.each(function() {
					if (!$(this).hasClass('wp-color-picker')) {
						$(this).wpColorPicker();
					}
				});

				AWS_ADMIN.initModalToggles(elementSettingsModal);

				// If element had validation errors, run validation to show them
				if (hasValidationErrors) {
					AWS_ADMIN.validateForm(elementSettingsModal);
				}
			}, 100);
		},

		epofwSaveElement: function() {
			var $modal = $(this).closest('.epofw-element-modal');
			var modalId = $modal.attr('id');
			var elementId = modalId.replace('element-settings-modal-', '');

			// Check if this is a premium field type and user is not premium.
			var $element = $('.epofw-element[data-element-id="' + elementId + '"]');
			var elementType = $element.attr('data-element-type');
			var premiumFieldTypes = epofw_var.premium_field_types || [];
			var isPremiumUser = epofw_var.is_premium || false;

			if ( ! isPremiumUser && premiumFieldTypes.indexOf( elementType ) !== -1 ) {
				// Show upgrade popup for premium fields - don't save.
				AWS_ADMIN.showPremiumUpgradePopup();
				return false;
			}

			// Validate form before saving
			if (!AWS_ADMIN.validateForm($modal)) {
				return false;
			}
			
			// Clear any validation errors since validation passed
			AWS_ADMIN.clearValidationErrors($modal);
			
			// Update the element title in the builder
			var labelTitle = $modal.find('input[name*="[label][title]"]').val();
			// $element is already defined above for premium check
			if (labelTitle && labelTitle.trim() && $element.length) {
					$element.find('.epofw-element-title').text(labelTitle.trim());
				}

			// Collect all field data as JSON object (instead of 259 hidden inputs)
			var fieldData = null;
			if ($element.length) {
				fieldData = AWS_ADMIN.collectFieldDataAsJSON($modal, elementId);

				// Remove old JSON input if exists
				$element.find('.epofw-field-json').remove();

				// Create single hidden input with JSON data
				var $jsonInput = $('<input type="hidden" class="epofw-field-json">');
				$jsonInput.attr('name', 'epofw_field_json[' + elementId + ']');
				$jsonInput.val(JSON.stringify(fieldData));
				$element.append($jsonInput);
			}

			// Update field status toggle and icon (in element or parent column header)
			if ($element.length) {
				var $fieldStatusCheckbox = $modal.find('input[name*="[field_status]"]');
				var isFieldEnabled = $fieldStatusCheckbox.is(':checked');
				var newStatus = isFieldEnabled ? 'on' : '';

				// Update the element's toggle checkbox and hidden input
				$element.find('.epofw-field-status-value').val(newStatus);
				$element.find('.epofw-field-status-checkbox').prop('checked', isFieldEnabled);

				// Update toggle tooltip
				var $toggle = $element.find('.epofw-field-status-toggle');
				$toggle.attr('title', isFieldEnabled ? 'Click to disable' : 'Click to enable');

				// Find status icon - first in element, then in parent column header
				var $statusIcon = $element.find('.epofw-element-status-icon, .epofw-column-status-icon');
				if (!$statusIcon.length) {
					// Look in parent column header
					var $column = $element.closest('.epofw-row-container');
					if ($column.length) {
						$statusIcon = $column.children('.epofw-column-header, .epofw-row-header').find('.epofw-column-status-icon');
					}
				}
				if ($statusIcon.length) {
					if (isFieldEnabled) {
						$statusIcon.removeClass('inactive').addClass('active');
						$statusIcon.attr('title', 'Active');
					} else {
						$statusIcon.removeClass('active').addClass('inactive');
						$statusIcon.attr('title', 'Inactive');
					}
				}

				/**
				 * Trigger after a field element is saved.
				 *
				 * Use this trigger to respond to field updates in custom modules.
				 *
				 * @since 4.4.5
				 * @event epofw_admin_field_saved
				 * @param {string} elementId The field element ID.
				 * @param {Object} fieldData The field data object.
				 * @param {jQuery} $element  The element jQuery object.
				 */
				$( document.body ).trigger( 'epofw_admin_field_saved', [ elementId, fieldData, $element ] );
			}

			// Close the modal
			AWS_ADMIN.closeElementModal(modalId);
		},

		// Collect all field data from modal as a JSON object
		collectFieldDataAsJSON: function($modal, elementId) {
			var fieldData = {
				field_id: elementId,
				field: {},
				label: {},
				epofw_field_settings: { options: [] },
				input_container_settings: {},
				field_container_settings: {},
				logical_operation: {},
				common: {}
			};

			// Get section_id, row_id, group_id, columns_id, columns_order, layout, columns, order from element
			// Use specific selector to avoid matching both .epofw-element and .epofw-edit-element
			var $element = $('.epofw-element[data-element-id="' + elementId + '"]');
			fieldData.section_id = $element.find('.epofw-field-section-id').val() || '';
			fieldData.row_id = $element.find('.epofw-field-row-id').val() || '';
			fieldData.group_id = $element.find('.epofw-field-group-id').val() || '';
			fieldData.columns_id = $element.find('.epofw-field-columns-id').val() || '';
			fieldData.columns_order = parseInt($element.find('.epofw-field-columns-order').val()) || 0;
			fieldData.layout = $element.find('.epofw-field-layout').val() || 'single';
			fieldData.columns = parseInt($element.find('.epofw-field-columns').val()) || 1;
			fieldData.order = $element.index(); // Capture position for drag-drop sorting
			fieldData.field_status = $element.find('.epofw-field-status-value').val() || '';

			// Collect field settings
			$modal.find('input, select, textarea').not(':button').each(function() {
				var $input = $(this);
				var name = $input.attr('name');
				if (!name) {
					return;
				}

				// Skip file inputs - they have fakepath values, use hidden inputs instead
				if ($input.attr('type') === 'file') {
					return;
				}

				// Skip field_status from modal - we get it from the toggle's hidden input above
				if (name.indexOf('[field_status]') !== -1) {
					return;
				}

				var value = '';
				if ($input.is(':checkbox')) {
					value = $input.is(':checked') ? $input.val() : '';
				} else if ($input.is(':radio')) {
					if (!$input.is(':checked')) {
						return;
					}
					value = $input.val();
				} else {
					value = $input.val();
				}

				// Parse the field name to extract keys
				// e.g., epofw_field[123][field][type] -> ['[123]', '[field]', '[type]']
				var match = name.match(/\[([^\]]+)\]/g);

				if (!match || match.length < 2) {
					return;
				}

				var keys = match.map(function(m) { return m.replace(/[\[\]]/g, ''); });
				keys.shift(); // Remove field_id

				// Handle options array specially
				if (keys[0] === 'epofw_field_settings' && keys[1] === 'options') {
					// Options have format: [epofw_field_settings][options][label][] or [opt_price_type][]
					var optKey = keys[2]; // 'label', 'opt_price_type', 'opt_price', 'epofw_cs_switcher'
					if (!fieldData._optionsTemp) {
						fieldData._optionsTemp = {};
					}
					if (!fieldData._optionsTemp[optKey]) {
						fieldData._optionsTemp[optKey] = [];
					}
					fieldData._optionsTemp[optKey].push(value);
					return;
				}

				// Build nested object
				var obj = fieldData;
				for (var i = 0; i < keys.length - 1; i++) {
					var key = keys[i];
					if (!obj[key]) {
						obj[key] = {};
					}
					obj = obj[key];
				}
				var lastKey = keys[keys.length - 1];
				if (lastKey === '') {
					// Array push (e.g., name="field[items][]")
					// Get the parent key to create array on parent object
					var parentKey = keys[keys.length - 2];
					if (parentKey && obj === fieldData[keys[0]]) {
						if (!Array.isArray(fieldData[keys[0]][parentKey])) {
							fieldData[keys[0]][parentKey] = [];
						}
						fieldData[keys[0]][parentKey].push(value);
					}
				} else {
					obj[lastKey] = value;
				}
			});

			// Convert options temp arrays to proper option objects
			if (fieldData._optionsTemp) {
				var labels = fieldData._optionsTemp.label || [];
				var priceTypes = fieldData._optionsTemp.opt_price_type || [];
				var prices = fieldData._optionsTemp.opt_price || [];
				var switchers = fieldData._optionsTemp.epofw_cs_switcher || [];
				var optIds = fieldData._optionsTemp.opt_id || [];
				var stocks = fieldData._optionsTemp.stock || [];
				var productIds = fieldData._optionsTemp.product_id || [];

				fieldData.epofw_field_settings.options = [];
				for (var i = 0; i < labels.length; i++) {
					var opt = {
						label: labels[i] || '',
						price_type: priceTypes[i] || 'fixed',
						price: prices[i] || ''
					};
					if (switchers[i]) {
						opt.swticher = switchers[i];
					}
					if (optIds[i]) {
						opt.id = optIds[i];
					}
					if (stocks[i]) {
						opt.stock = stocks[i];
					}
					if (productIds[i]) {
						opt.product_id = productIds[i];
					}
					fieldData.epofw_field_settings.options.push(opt);
				}
				delete fieldData._optionsTemp;
			}

			return fieldData;
		},

		epofwSaveSection: function() {
			var $modal = $(this).closest('.epofw-section-modal');
			var modalId = $modal.attr('id');
			var sectionId = modalId.replace('section-settings-modal-', '');

			// Validate form before saving
			if (!AWS_ADMIN.validateForm($modal)) {
				// Validation failed - don't save
				return false;
			}

			// Clear any validation errors since validation passed
			AWS_ADMIN.clearValidationErrors($modal);

			// Find the section in the builder - use specific selector to get only the section container
			var $section = $('.epofw-section[data-section-id="' + sectionId + '"]');

			if ($section.length) {
				// Remove any existing section hidden fields (except row_groups structure)
				$section.find('.epofw-section-header input[type="hidden"]').each(function() {
					var name = $(this).attr('name');
					// Keep row_groups structure, remove section properties
					if (name && !name.includes('[row_groups]')) {
						$(this).remove();
					}
				});

				// Get all form fields from the modal
				var $formFields = $modal.find('input, select, textarea').not(':button');

				// Clone form fields as hidden inputs and append to section header
				$formFields.each(function() {
					var $field = $(this);
					var fieldName = $field.attr('name');
					var fieldValue = '';

					if (!fieldName) {
						return; // Skip fields without names
					}

					// Get field value based on type
					if ($field.is(':checkbox')) {
						fieldValue = $field.is(':checked') ? $field.val() : '';
					} else if ($field.is(':radio')) {
						if ($field.is(':checked')) {
							fieldValue = $field.val();
						} else {
							return; // Skip unchecked radio buttons
						}
					} else {
						fieldValue = $field.val();
					}

					// Create hidden input with the same name and value
					var $hiddenInput = $('<input type="hidden">');
					$hiddenInput.attr('name', fieldName);
					$hiddenInput.val(fieldValue);

					// Append to section header
					$section.find('.epofw-section-header').prepend($hiddenInput);
				});

				// Update the section title display
				var sectionTitle = $modal.find('input[name*="[title]"]').val();
				if (sectionTitle && sectionTitle.trim()) {
					$section.find('.epofw-section-title span').text(sectionTitle.trim());
				}

				// Update section status icon
				var $sectionStatusCheckbox = $modal.find('input[name*="[section_status]"]');
				var $statusIcon = $section.find('.epofw-section-status-icon');
				if ($statusIcon.length) {
					if ($sectionStatusCheckbox.is(':checked')) {
						$statusIcon.removeClass('inactive').addClass('active');
						$statusIcon.attr('title', 'Active');
					} else {
						$statusIcon.removeClass('active').addClass('inactive');
						$statusIcon.attr('title', 'Inactive');
					}
				}

				/**
				 * Trigger after a section is saved.
				 *
				 * Use this trigger to respond to section updates in custom modules.
				 *
				 * @since 4.4.5
				 * @event epofw_admin_section_saved
				 * @param {string} sectionId The section ID.
				 * @param {jQuery} $section  The section jQuery object.
				 * @param {jQuery} $modal    The modal jQuery object.
				 */
				$( document.body ).trigger( 'epofw_admin_section_saved', [ sectionId, $section, $modal ] );
			}

			// Close the modal
			AWS_ADMIN.closeElementModal(modalId);
		},

		// Initialize toggle switch functionality
		initToggleSwitches: function() {
			// Handle toggle switch clicks (both old .toggle-switch and new .epofw-toggle-switch)
			$(document).on('click', '.toggle-switch, .epofw-toggle-switch', function(e) {
				e.preventDefault();
				var $toggleSwitch = $(this);
				var $checkbox = $toggleSwitch.prev('input[type="checkbox"]');

				if ($checkbox.length) {
					// Toggle the checkbox state
					$checkbox.prop('checked', !$checkbox.prop('checked')).trigger('change');
				}
			});
		},

		// Handle section status toggle
		handleSectionStatusToggle: function() {
			var $checkbox = $(this);
			var sectionId = $checkbox.data('section-id');
			var isChecked = $checkbox.is(':checked');
			var newStatus = isChecked ? 'on' : '';

			// Update the hidden input value - use .epofw-section class to avoid matching the checkbox itself
			var $section = $checkbox.closest('.epofw-section');

			// Try class first, then fallback to name selector
			var $hiddenInput = $section.find('.epofw-section-status-value');
			if (!$hiddenInput.length) {
				// Fallback: find by name pattern
				$hiddenInput = $section.find('input[name$="[status]"]').filter(function() {
					return $(this).attr('name').indexOf('epofw_section') === 0;
				});
			}

			$hiddenInput.val(newStatus);

			// Update tooltip
			var $toggle = $checkbox.closest('.epofw-section-status-toggle');
			$toggle.attr('title', isChecked ?
				(typeof epofw_var !== 'undefined' && epofw_var.strings ? epofw_var.strings.click_to_disable || 'Click to disable' : 'Click to disable') :
				(typeof epofw_var !== 'undefined' && epofw_var.strings ? epofw_var.strings.click_to_enable || 'Click to enable' : 'Click to enable')
			);

			// Also update the modal checkbox if it exists
			var $modal = $('#section-settings-modal-' + sectionId);
			if ($modal.length) {
				$modal.find('input[name*="[status]"]').prop('checked', isChecked);
			}
		},

		// Handle section modal status checkbox change - sync back to toggle
		handleModalSectionStatusChange: function() {
			var $checkbox = $(this);
			var isChecked = $checkbox.is(':checked');
			var newStatus = isChecked ? 'on' : '';

			// Find the section ID from the modal
			var $modal = $checkbox.closest('.epofw-section-modal');
			var modalId = $modal.attr('id');
			if (!modalId) {
				return;
			}
			var sectionId = modalId.replace('section-settings-modal-', '');

			// Update the toggle's hidden input and checkbox
			var $section = $('[data-section-id="' + sectionId + '"]');
			if ($section.length) {
				$section.find('.epofw-section-status-value').val(newStatus);
				$section.find('.epofw-section-status-checkbox').prop('checked', isChecked);

				// Update tooltip
				var $toggle = $section.find('.epofw-section-status-toggle');
				$toggle.attr('title', isChecked ? 'Click to disable' : 'Click to enable');
			}
		},

		// Handle field status toggle
		handleFieldStatusToggle: function() {
			var $checkbox = $(this);
			var fieldId = $checkbox.data('field-id');
			var isChecked = $checkbox.is(':checked');
			var newStatus = isChecked ? 'on' : '';

			// Update the hidden input value
			var $element = $checkbox.closest('.epofw-element');
			$element.find('.epofw-field-status-value').val(newStatus);

			// Update tooltip
			var $toggle = $checkbox.closest('.epofw-field-status-toggle');
			$toggle.attr('title', isChecked ?
				(typeof epofw_var !== 'undefined' && epofw_var.strings ? epofw_var.strings.click_to_disable || 'Click to disable' : 'Click to disable') :
				(typeof epofw_var !== 'undefined' && epofw_var.strings ? epofw_var.strings.click_to_enable || 'Click to enable' : 'Click to enable')
			);

			// Also update the modal checkbox if it exists
			var $modal = $('#element-settings-modal-' + fieldId);
			if ($modal.length) {
				$modal.find('input[name*="[field_status]"]').prop('checked', isChecked);
			}
		},

		// Handle modal field_status checkbox change - sync back to toggle
		handleModalFieldStatusChange: function() {
			var $checkbox = $(this);
			var isChecked = $checkbox.is(':checked');
			var newStatus = isChecked ? 'on' : '';

			// Find the element ID from the modal
			var $modal = $checkbox.closest('.epofw-element-modal');
			var modalId = $modal.attr('id');
			if (!modalId) {
				return;
			}
			var elementId = modalId.replace('element-settings-modal-', '');

			// Update the toggle's hidden input and checkbox
			// Use specific selector to avoid matching both .epofw-element and .epofw-edit-element
			var $element = $('.epofw-element[data-element-id="' + elementId + '"]');
			if ($element.length) {
				$element.find('.epofw-field-status-value').val(newStatus);
				$element.find('.epofw-field-status-checkbox').prop('checked', isChecked);

				// Update tooltip
				var $toggle = $element.find('.epofw-field-status-toggle');
				$toggle.attr('title', isChecked ? 'Click to disable' : 'Click to enable');
			}
		},

		// Initialize color pickers for colorswitcher fields
		initColorPickers: function() {
			// Initialize native HTML5 color pickers for colorswitcher fields
			$('.epofw-native-color-picker').each(function() {
				if (!$(this).hasClass('native-color-picker-initialized')) {
					// Set default color if no value is set
					if (!$(this).val()) {
						var defaultColor = $(this).data('default-color') || '#ffffff';
						$(this).val(defaultColor);
						$(this).attr('value', defaultColor);
					}
					
					// Ensure the color picker displays properly
					$(this).css({
						'min-height': '38px',
						'cursor': 'pointer'
					});
					
					// Add change event handler
					$(this).on('change', function() {
						// Handle color change - the value is automatically updated
					});
					
					$(this).addClass('native-color-picker-initialized');
				}
			});
		},

		// Refresh color pickers after dynamic content is added
		refreshColorPickers: function() {
			// Remove existing event handlers
			$('.epofw-native-color-picker').each(function() {
				if ($(this).hasClass('native-color-picker-initialized')) {
					$(this).off('change');
					$(this).removeClass('native-color-picker-initialized');
				}
			});
			
			// Reinitialize color pickers
			this.initColorPickers();
		},

		updateDynamicCodeExample: function() {
			var $input = $(this);
			var $code = $input.closest('.epofw-form-group').find('code');
			
			// Check if code element exists and has content
			if (!$code.length || !$code.html()) {
				return;
			}
			
			var html = $code.html();
			
			if (html && html.includes('name="')) {
				$code.html(html.replace(/name="[^"]*"/, 'name="' + $input.val() + '"'));
			}
			
			if (html && html.includes('id="')) {
				$code.html(html.replace(/id="[^"]*"/, 'id="' + $input.val() + '"'));
			}
			
			if (html && html.includes('class="')) {
				$code.html(html.replace(/class="[^"]*"/, 'class="' + $input.val() + '"'));
			}
		},

		updateUpdateCodeExample: function() {
			var $input = $(this);
			var selectedTag = $input.val();
			
			// Since we know code elements are in the next form group, go directly there
			var $codeElements = $input.closest('.epofw-form-group').next('.epofw-form-group').find('code');
			
			if (!$codeElements.length) {
				return;
			}
			
			// Update each code element
			$codeElements.each(function() {
				var $code = $(this);
				var html = $code.html();
				
				// Handle HTML entities and update the tag
				if (html && (html.includes('&lt;') || html.includes('<'))) {
					// First decode HTML entities if they exist
					var decodedHtml = html;
					if (html.includes('&lt;')) {
						decodedHtml = html.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
					}
					
					// Find any HTML tag and replace it with the selected tag
					var updatedHtml = decodedHtml.replace(/<(\w+)/, '<' + selectedTag);
					
					// Update the code content (re-encode for display)
					var finalHtml = updatedHtml.replace(/</g, '&lt;').replace(/>/g, '&gt;');
					$code.html(finalHtml);
				}
			});
		},

		closeElementModal: function( elementId ) {
			var modal;
			if ( elementId ) {
				modal = $( '#' + elementId );
				modal.hide();
			} else {
				modal = $( '#element-settings-modal, #section-settings-modal' );
				modal.hide();
			}
			
			// Reset tabs when closing modal to ensure clean state
			if (modal && modal.length) {
				AWS_ADMIN.resetModalTabs(modal);
			}
		},
		

		/**
		 * Handle edit button clicks in addon list page
		 */
		handleEditButtonClick: function ( e ) {
			e.preventDefault();
			var $this = $( this );
			var editUrl = $this.attr( 'href' );
			
			if ( editUrl ) {
				// Redirect to the edit page
				window.location.href = editUrl;
			}
		},

		epofwAddSection: function () {
			AWS_ADMIN.epofwAddSectionHtml();
		},

		epofwAddSectionHtml: function () {
			// Get addon post ID from hidden input to ensure unique section IDs across addons
			var addonPostId = $('input[name="addon_id"]').val() || '';
			var sectionId = addonPostId ? (addonPostId + '_' + Date.now()) : Date.now();
			var sectionHtml = $ ( '#tmpl-epofw-section-html' ).html();

			// Define IDs that will be used
			var groupId = 'group_' + sectionId;
			var rowId = 'row_' + sectionId + '_1';
			var columnsId = 'columns_' + sectionId + '_group_' + sectionId;

			// Replace ALL data-section-id attributes (including on edit button)
			sectionHtml = sectionHtml.replace(/data-section-id="[^"]*"/g, 'data-section-id="' + sectionId + '"');

			// Replace form input names (OPTIMIZED format)
			sectionHtml = sectionHtml.replace(/name="epofw_section\[[^\]]*\]/g, 'name="epofw_section[' + sectionId + ']');
			sectionHtml = sectionHtml.replace(/value="[^"]*Section [^"]*"/g, 'value="Section ' + sectionId + '"');

			// Replace the [id] and [section_id] input values (handles both numeric and post_id_timestamp formats)
			sectionHtml = sectionHtml.replace(/(\[id\]"\s+value=")[^"]+(")/g, '$1' + sectionId + '$2');
			sectionHtml = sectionHtml.replace(/(\[section_id\]"\s+value=")[^"]+(")/g, '$1' + sectionId + '$2');

			// Replace group IDs (match group_ followed by any combination of digits and underscores)
			sectionHtml = sectionHtml.replace(/data-group-id="group_[^"]*"/g, 'data-group-id="' + groupId + '"');
			sectionHtml = sectionHtml.replace(/group_[0-9_]+/g, groupId);

			// Replace row IDs (match row_ followed by any combination of digits and underscores, ending with _1)
			sectionHtml = sectionHtml.replace(/data-row-id="row_[^"]*"/g, 'data-row-id="' + rowId + '"');
			sectionHtml = sectionHtml.replace(/row_[0-9_]+_1/g, rowId);

			// Replace columns IDs (CRITICAL: this was missing and caused layout issues)
			sectionHtml = sectionHtml.replace(/data-columns-id="columns_[^"]*"/g, 'data-columns-id="' + columnsId + '"');
			sectionHtml = sectionHtml.replace(/columns_[0-9_]+_group_[0-9_]+/g, columnsId);
			// Also replace in input names for epofw_columns_group and epofw_column
			sectionHtml = sectionHtml.replace(/name="epofw_columns_group\[columns_[^\]]+\]/g, 'name="epofw_columns_group[' + columnsId + ']');
			sectionHtml = sectionHtml.replace(/name="epofw_column\[row_[^\]]+\]/g, 'name="epofw_column[' + rowId + ']');

            // Remove empty state if it exists.
            $('.epofw-empty-builder').remove();

            // Add a section to the container.
            var container = $('#sections-container');

            if (container.length) {
				var sectionHtmlEl = $(sectionHtml);
				container.append(sectionHtmlEl);

				// Set section order after append (matches premium version)
				var sectionOrder = $('.epofw-section').length;
				sectionHtmlEl.find('input[name="epofw_section[' + sectionId + '][order]"]').val(sectionOrder);

                // Refresh sortable functionality for the new section.
                AWS_ADMIN.refreshSortable();
            }
		},

		epofwDeleteElement: function ( e ) {
			e.preventDefault();
			if ( confirm( epofw_var.strings.delete_addon_field ) ) {
				var $elementsContainer = $( this ).closest('.epofw-elements-container' ).find('.epofw-element-add:hidden');
				if ( $elementsContainer.length ) {
					$elementsContainer.show();
				}
				$( this).closest('.epofw-element, .epofw-section').remove();
			}
		},

		/**
		 * Toggle status on list.
		 *
		 * @since 4.2
		 */
		epofwToggleStatusOnList: function () {
			var $this       = $( this );
			var $parent     = $this.closest( '.epofw-addon-card' );
			var $status     = $parent.find( '.epofw-card-status' );
			var $productId  = $parent.data('id');
			var oldStatus   = $status.hasClass( 'active' ) ? 'active' : 'inactive';

			// Show loader on card
			AWS_ADMIN.showCardLoader( $parent, 'updating' );

			jQuery.ajax(
				{
					type: 'post',
					url: epofw_var.ajaxurl,
					data: {
						action: 'epofw_toggle_status_on_list',
						product_id: $productId,
						toggle_status_nonce: epofw_var.toggle_status_nonce,
					},
					success: function ( response ) {
						// Hide loader
						AWS_ADMIN.hideCardLoader( $parent );

						if ( response ) {
							if ( true === response.success && response.data && response.data.content ) {
								var $statusElement = $parent.find( '.epofw-card-status' );
								var newStatus = response.data.content.class;

								$statusElement.removeClass( 'active' ).removeClass( 'inactive' ).addClass( newStatus );

								$statusElement.contents().filter( function() {
									return this.nodeType === 3;
								} ).remove();

								$statusElement.append( response.data.content.status );

								// Update card's data-status attribute
								$parent.attr('data-status', newStatus);

								// Update stats counters
								AWS_ADMIN.updateStatsAfterToggle(oldStatus, newStatus);
							}
						}
					},
					error: function () {
						// Hide loader on error
						AWS_ADMIN.hideCardLoader( $parent );
					}
				}
			);

		},

		handleMainAddElement: function ( e ) {
			e.preventDefault();
			
			// Just show the element selector - don't create section yet
			// Section will be created when user actually selects a field type
			AWS_ADMIN.showElementSelector(null, null, {});
		},

		epofwAddElement: function ( e ) {
			e.preventDefault();
			var elementExists = $(this).closest('.epofw-elements-container').find('.epofw-element');
			if ( 1 === elementExists.length ) {
				AWS_ADMIN.toastMessage( 'error', epofw_var.strings.limit_addon_message );
				return;
			}
			var section = $(this).closest('.epofw-section');
			var $rowGroup = $(this).closest('.epofw-row-group');
			var $rowContainer = $(this).closest('.epofw-row-container');
			var $columnsContainer = $(this).closest('.epofw-columns');

			// Get row data from DOM - use .closest() for single element selectors
			var groupId = $rowGroup.data('group-id');
			var rowCount = $rowGroup.data('rows-count');
			// FIX: Use data attribute from button directly or from closest .epofw-row-container
			// (NOT compound selector which doesn't work with .closest())
			var rowId = $(this).data('row-id') || $rowContainer.data('row-id');

			// v2.3: Get columns_id and columns_order from the columns container
			var columnsId = $columnsContainer.data('columns-id') || $rowContainer.data('columns-id') || '';
			var columnsOrder = $columnsContainer.data('columns-order') || $rowContainer.data('columns-order') || 0;

			var rowsData = {
					group_id: groupId,
					row_id: rowId,
					columns_id: columnsId,
					columns_order: columnsOrder,
					layout: rowCount > 1 ? 'multiple' : 'single',
					columns: rowCount
			};

			AWS_ADMIN.showElementSelector(section, groupId, rowsData);
		},

		showElementSelector: function (section, groupId, rowsData) {
			
			// Show the existing modal (already in HTML)
			var modal = $('.epofw-element-selector-modal');
			if (!modal.length) {
				return;
			}
            
            // Show the modal
            setTimeout(function() {
                modal.show();
            }, 10);

            // Bind events - Allow adding all field types (including premium) so users can explore settings.
            modal.find('.epofw-field-type-card').off('click').on('click', function() {
                var type = $(this).data('type');
                AWS_ADMIN.addFieldIntoSection(type, section, rowsData);
                modal.hide();
            });

            modal.find('.epofw-modal-close, .epofw-modal-overlay').off('click').on('click', function() {
                modal.hide();
            });
		},

		/**
		 * Show premium upgrade popup when user clicks on premium field type.
		 *
		 * @param {string} fieldType The field type that was clicked.
		 */
		showPremiumUpgradePopup: function( /* fieldType */ ) {
			var title = epofw_var.premium_feature_title || 'Premium Feature';
			var message = epofw_var.premium_feature_msg || 'This field type is available in the Pro version.';
			var upgradeText = epofw_var.upgrade_to_pro || 'Upgrade to Pro';
			var cancelText = epofw_var.cancel_text || 'Cancel';
			var upgradeUrl = epofw_var.upgrade_url || '#';
			var discountText = epofw_var.discount_offer_text || '';

			// Create popup HTML.
			var discountHtml = discountText ? '<div class="epofw-premium-popup-discount"><span class="dashicons dashicons-tag"></span> ' + discountText + '</div>' : '';

			var popupHtml = '<div class="epofw-premium-popup-overlay">' +
				'<div class="epofw-premium-popup">' +
					'<div class="epofw-premium-popup-icon">' +
						'<span class="dashicons dashicons-lock"></span>' +
					'</div>' +
					'<h3 class="epofw-premium-popup-title">' + title + '</h3>' +
					'<p class="epofw-premium-popup-message">' + message + '</p>' +
					'<div class="epofw-premium-popup-buttons">' +
						'<a href="' + upgradeUrl + '" class="epofw-btn epofw-btn-primary epofw-upgrade-btn" target="_blank">' + upgradeText + '</a>' +
						'<button type="button" class="epofw-btn epofw-btn-secondary epofw-popup-cancel">' + cancelText + '</button>' +
					'</div>' +
					discountHtml +
				'</div>' +
			'</div>';

			// Remove any existing popup.
			$( '.epofw-premium-popup-overlay' ).remove();

			// Add popup to body.
			$( 'body' ).append( popupHtml );

			// Bind close events.
			$( '.epofw-premium-popup-overlay' ).on( 'click', function( e ) {
				if ( $( e.target ).hasClass( 'epofw-premium-popup-overlay' ) || $( e.target ).hasClass( 'epofw-popup-cancel' ) ) {
					$( '.epofw-premium-popup-overlay' ).remove();
				}
			});

			$( '.epofw-popup-cancel' ).on( 'click', function() {
				$( '.epofw-premium-popup-overlay' ).remove();
			});
		},

		// Function to actually add the field to the section.
		addFieldIntoSection : function ( type, section, rowsData ) {
			// Ensure rowsData is an object
			rowsData = rowsData || {};

			var elementId    = Date.now();
			var section_id   = '';
			var rowId        = rowsData.row_id || '';
			var groupId      = rowsData.group_id || '';
			var columnsId    = rowsData.columns_id || '';
			var columnsOrder = rowsData.columns_order || 0;
			var layout       = rowsData.layout || 'single';
			var columns      = rowsData.columns || 1;
			var addButton = null;
			var $container = null;
			var $newElement = null;
			var elementToScroll = null;

			// Get section_id from section element if available.
			if ( section && section.length ) {
				section_id = section.attr('data-section-id');
			}

			// Build association data for hidden inputs.
			var associationData = {
				section_id: section_id,
				row_id: rowId,
				group_id: groupId,
				columns_id: columnsId,
				columns_order: columnsOrder,
				layout: layout,
				columns: columns
			};

			var elementHtml = AWS_ADMIN.getElementHtml(type, elementId, associationData);
			
			if ( section && section.length ) {
				section_id = section.attr('data-section-id');
				
				if ( rowId ) {
					// Add field to specific row
					addButton = section.find('.epofw-row-group .epofw-row-container[data-row-id="' + rowId + '"] .epofw-element-add');
					if (addButton.length) {
						addButton.before( elementHtml );
						$newElement = addButton.prev('.epofw-element');
						addButton.hide();
					} else {
						$container = section.find('.epofw-row-group .epofw-row-container[data-row-id="' + rowId + '"] .epofw-elements-container');
						$container.append( elementHtml );
						$newElement = section.find('.epofw-element[data-element-id="' + elementId + '"]');
						// Hide the add button in this container
						$container.find('.epofw-element-add').hide();
					}
				} else {
					// Add field to section (no specific row)
					$container = section.find( '.epofw-elements-container' );
					$container.append( elementHtml );
					$newElement = section.find('.epofw-element[data-element-id="' + elementId + '"]');
					// Hide the add button in this container
					$container.find('.epofw-element-add').hide();
				}
				// Refresh sortable functionality for the new element.
				AWS_ADMIN.refreshSortable();

				// Scroll to the newly added element
				if ($newElement && $newElement.length) {
					elementToScroll = $newElement;
					setTimeout(function() {
						elementToScroll[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
						// Add a slight highlight effect
						elementToScroll.addClass('epofw-element-highlight');
						setTimeout(function() {
							elementToScroll.removeClass('epofw-element-highlight');
						}, 2000);
					}, 100);
				}
			} else {
				// No section provided - find first empty column or create new section
					// First, try to find an empty column in existing sections
					var $emptyColumn = $('.epofw-elements-container').filter(function() {
						return $(this).find('.epofw-element').length === 0;
					}).first();

					if ($emptyColumn.length) {
						// Found an empty column - add element there
						var $targetSection = $emptyColumn.closest('.epofw-section');
						var targetSectionId = $targetSection.attr('data-section-id');
						var $targetRowContainer = $emptyColumn.closest('.epofw-row-container');
						var targetRowId = $targetRowContainer.attr('data-row-id') || '';
						var $targetRowGroup = $emptyColumn.closest('.epofw-row-group');
						var targetGroupId = $targetRowGroup.attr('data-group-id') || '';
						var $targetColumns = $emptyColumn.closest('.epofw-columns');
						var targetColumnsId = $targetColumns.attr('data-columns-id') || '';
						var targetColumnsOrder = $targetColumns.attr('data-columns-order') || 0;

						// Update association data
						associationData.section_id = targetSectionId;
						associationData.row_id = targetRowId;
						associationData.group_id = targetGroupId;
						associationData.columns_id = targetColumnsId;
						associationData.columns_order = targetColumnsOrder;

						elementHtml = AWS_ADMIN.getElementHtml(type, elementId, associationData);
						$emptyColumn.append(elementHtml);

						$newElement = $emptyColumn.find('.epofw-element[data-element-id="' + elementId + '"]');
						
						// Hide the add button in this container (only one element allowed per container)
						$emptyColumn.find('.epofw-element-add').hide();
						
						// Refresh sortable functionality
						AWS_ADMIN.refreshSortable();

						// Scroll to the newly added element
						if ($newElement && $newElement.length) {
							elementToScroll = $newElement;
							setTimeout(function() {
								elementToScroll[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
								elementToScroll.addClass('epofw-element-highlight');
								setTimeout(function() {
									elementToScroll.removeClass('epofw-element-highlight');
								}, 2000);
							}, 100);
						}
						return;
					} else {
						// No empty column found - create new section
						AWS_ADMIN.addSection();
					
						// Wait for section to be created, then add the field
						setTimeout(function() {
							// Fixed: Use .last() to get the newly created section, not .first()
							var newSection = $('.epofw-section').last();
					
					if (newSection.length) {
						// Update association data with the new section's ID.
						var newSectionId = newSection.attr('data-section-id');
						var newGroupId = newSection.find('.epofw-row-group').first().attr('data-group-id') || 'group_' + newSectionId;
						var newRowId = newSection.find('.epofw-row-container').first().attr('data-row-id') || 'row_' + newSectionId + '_1';

						// Rebuild association data and element HTML with correct section_id.
						var newAssociationData = {
							section_id: newSectionId,
							row_id: newRowId,
							group_id: newGroupId,
							columns_id: columnsId,
							columns_order: columnsOrder,
							layout: layout,
							columns: columns
						};
						var newElementHtml = AWS_ADMIN.getElementHtml(type, elementId, newAssociationData);

						if ( rowId ) {
							// Add field to specific row
							addButton = newSection.find('.epofw-row-group .epofw-row-container[data-row-id="' + rowId + '"] .epofw-element-add');
					if (addButton.length) {
								addButton.before( newElementHtml );
								$newElement = addButton.prev('.epofw-element');
								addButton.hide();
							} else {
								$container = newSection.find('.epofw-row-group .epofw-row-container[data-row-id="' + rowId + '"] .epofw-elements-container');
								$container.append( newElementHtml );
								$newElement = newSection.find('.epofw-element[data-element-id="' + elementId + '"]');
								// Hide the add button in this container
								$container.find('.epofw-element-add').hide();
							}
						} else {
							// Add field to section (no specific row)
							$container = newSection.find( '.epofw-elements-container' );
							$container.append( newElementHtml );
							$newElement = newSection.find('.epofw-element[data-element-id="' + elementId + '"]');
							// Hide the add button in this container
							$container.find('.epofw-element-add').hide();
						}
						// Refresh sortable functionality for the new element.
						AWS_ADMIN.refreshSortable();

						// Scroll to the newly added element
						if ($newElement && $newElement.length) {
							elementToScroll = $newElement;
							setTimeout(function() {
								elementToScroll[0].scrollIntoView({ behavior: 'smooth', block: 'center' });
								// Add a slight highlight effect
								elementToScroll.addClass('epofw-element-highlight');
								setTimeout(function() {
									elementToScroll.removeClass('epofw-element-highlight');
								}, 2000);
							}, 100);
						}
					}
				}, 100);
				return;
			}
		}
	},

		// Generate HTML for the element
		getElementHtml: function(type, elementId, associationData) {
			// Get the template HTML.
			var template = $('#tmpl-epofw-element-selector-output').html();
			
			// Get field data from localized data.
			var fieldData = epofw_var.fields_icon_description[type] || {};
			var iconClass = fieldData.icon || 'dashicons-admin-generic';
			var typeName = fieldData.name || type.charAt(0).toUpperCase() + type.slice(1).replace(/([A-Z])/g, ' $1');
			
			// Convert template string to jQuery object for manipulation.
			var $template = $( template );
			
			// Update the template.
			$template.attr('data-element-id', elementId);
			$template.attr('data-element-type', type);
			$template.find('.epofw-element-title').text(typeName);
			$template.find('.epofw-element-subtitle').text(type);
			$template.find('.epofw-element-icon i').attr('class', 'dashicons ' + iconClass);
			$template.find('.epofw-edit-element').attr('data-element-id', elementId);

			// Populate hidden inputs for field association (CRITICAL for form submission).
			// These inputs MUST have proper name/value to be included when form is submitted.
			associationData = associationData || {};
			var fieldPrefix = 'epofw_field[' + elementId + ']';

			// IMPORTANT: Use .attr('value', ...) instead of .val() because .val() sets DOM property,
			// not the HTML attribute, and .prop('outerHTML') only captures attributes.
			var $sectionInput = $template.find('.epofw-field-section-id');
			var $rowInput = $template.find('.epofw-field-row-id');
			var $groupInput = $template.find('.epofw-field-group-id');
			var $columnsIdInput = $template.find('.epofw-field-columns-id');
			var $columnsOrderInput = $template.find('.epofw-field-columns-order');
			var $layoutInput = $template.find('.epofw-field-layout');
			var $columnsInput = $template.find('.epofw-field-columns');

			$sectionInput.attr('name', fieldPrefix + '[section_id]').attr('value', associationData.section_id || '');
			$rowInput.attr('name', fieldPrefix + '[row_id]').attr('value', associationData.row_id || '');
			$groupInput.attr('name', fieldPrefix + '[group_id]').attr('value', associationData.group_id || '');
			$columnsIdInput.attr('name', fieldPrefix + '[columns_id]').attr('value', associationData.columns_id || '');
			$columnsOrderInput.attr('name', fieldPrefix + '[columns_order]').attr('value', associationData.columns_order || 0);
			$layoutInput.attr('name', fieldPrefix + '[layout]').attr('value', associationData.layout || 'single');
			$columnsInput.attr('name', fieldPrefix + '[columns]').attr('value', associationData.columns || 1);

			// Set field status (default to 'on' for new fields)
			var $fieldStatusInput = $template.find('.epofw-field-status-value');
			$fieldStatusInput.attr('name', fieldPrefix + '[field_status]').attr('value', 'on');

			// Set the checkbox data-field-id
			var $fieldStatusCheckbox = $template.find('.epofw-field-status-checkbox');
			$fieldStatusCheckbox.attr('data-field-id', elementId);

			// Return the HTML string
			return $template.prop('outerHTML');
		},

		showElementSettingsModal : function ( elementId, elementType ) {
            var modal = $( '#element-settings-modal' );
            if ( modal.length ) {
                modal.show();

                // Update the modal header based on field type
                var headerText = AWS_ADMIN.getFieldTypeHeaderText( elementType );
                modal.find( '.epofw-modal-header h3' ).text( headerText );
            }
		},

		/**
		 * Handle show/hide functionality for fields with sub-fields.
		 *
		 * @since 4.4.0
		 */
	handleShowHideFields                : function () {
		var $checkbox = $( this );
		var nextFieldId = $checkbox.attr( 'data-nextfe' );

		if (nextFieldId) {
			// Try multiple strategies to find the target field
			var $nextField = $();
			
			// Strategy 1: Find in closest modal (element, section, row, column)
			var $modal = $checkbox.closest('.epofw-element-modal, .epofw-section-modal, .epofw-row-modal, .epofw-column-modal, .epofw-modal-body');
			if ($modal.length) {
				$nextField = $modal.find('#' + nextFieldId);
			}
			
			// Strategy 2: Find in closest form
			if (!$nextField.length) {
				$nextField = $checkbox.closest('form').find('#' + nextFieldId);
			}
			
			// Strategy 3: Find anywhere in document as last resort
			if (!$nextField.length) {
				$nextField = $('#' + nextFieldId);
			}
			
			if ($nextField.length) {
				if ($checkbox.is(':checked')) {
					$nextField.slideDown(300);
				} else {
					$nextField.slideUp(300);
				}
			}
		}
	},

	// Initialize toggle switches in a modal or container
	initModalToggles: function($container) {
		$container.find('.epofw-has-sub').each(function() {
			var $checkbox = $(this);
			var nextFieldId = $checkbox.attr('data-nextfe');
			
			if (nextFieldId) {
				var $nextField = $container.find('#' + nextFieldId);
				
				if ($nextField.length) {
					if ($checkbox.is(':checked')) {
						$nextField.show();
					} else {
						$nextField.hide();
					}
				}
			}
		});
	},

		getFieldTypeHeaderText : function ( fieldType ) {
            return fieldType + ' ' + epofw_var.settings;
        },

		// Add a new section if needed.
		addSection: function() {
			var sectionId = Date.now();
			var sectionHtml = $('#tmpl-epofw-section-html').html();
			
			// Extract the old PHP-generated section ID from the template
			var oldIdMatch = sectionHtml.match(/data-section-id="([^"]*)"/);
			var oldSectionId = oldIdMatch ? oldIdMatch[1] : '';

			if (oldSectionId) {
				// Replace ALL occurrences of the old section ID with the new one
				// This includes: data attributes, hidden input names, hidden input values
				var oldIdRegex = new RegExp(oldSectionId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
				sectionHtml = sectionHtml.replace(oldIdRegex, sectionId);
			}

			// Define IDs for row group and column
			var groupId = 'group_' + sectionId;
			var rowId = 'row_' + sectionId + '_1';
			
			var sectionHtmlEl = $(sectionHtml);
			sectionHtmlEl.find('.epofw-section-title span').text(epofw_var.section_name + ' ' + ($('.epofw-section').length + 1));

			// Remove empty state if it exists.
			$('.epofw-empty-builder').remove();
			
			// Add a section to container.
			var container = $('#sections-container');
			if (container.length) {
				container.append(sectionHtmlEl);
				
				// Create modals
				AWS_ADMIN.createSectionModal(sectionId);
				AWS_ADMIN.createRowModal(sectionId, groupId);
				AWS_ADMIN.createColumnModal(sectionId, groupId, rowId);

				// Scroll to the newly added section
				setTimeout(function() {
					var $newSection = sectionHtmlEl;
					if ($newSection.length) {
						$newSection[0].scrollIntoView({ behavior: 'smooth', block: 'start' });
						// Add a slight highlight effect
						$newSection.addClass('epofw-section-highlight');
						setTimeout(function() {
							$newSection.removeClass('epofw-section-highlight');
						}, 2000);
					}
				}, 100);
			}
		},

		// Create section modal from template
		createSectionModal: function(sectionId) {
			var template = $('#tmpl-epofw-section-settings-modal').html();
			if (!template) {
				return;
			}
			
			var modalHtml = $(template);
			modalHtml.attr('id', 'section-settings-modal-' + sectionId);
			modalHtml.find('.epofw-save-section').attr('data-section-id', sectionId);
			
			$('body').append(modalHtml);
		},

		// Create row modal from template
		createRowModal: function(sectionId, groupId) {
			var template = $('#tmpl-epofw-row-settings-modal').html();
			if (!template) {
				return;
			}
			
			var modalHtml = template.replace(/\{\{ data\.group_id \}\}/g, groupId)
									.replace(/\{\{ data\.section_id \}\}/g, sectionId);
			
			$('body').append(modalHtml);
		},

		// Function to refresh sortable functionality after dynamic content addition.
		refreshSortable: function() {
			// Safely refresh sections sortable if initialized.
			if ($('.epofw-sections-container').hasClass('ui-sortable')) {
				$('.epofw-sections-container').sortable('refresh');
			}
			
			// Safely refresh elements sortable if initialized.
			$('.epofw-elements-container').each(function() {
				if ($(this).hasClass('ui-sortable')) {
					$(this).sortable('refresh');
				}
			});
			
			// Safely refresh options sortable if initialized.
			$('.epofw-options-container').each(function() {
				if ($(this).hasClass('ui-sortable')) {
					$(this).sortable('refresh');
				}
			});
			
			// Refresh color pickers for new colorswitcher fields.
			this.refreshColorPickers();
		},

		// Helper function to reset tabs to first tab.
		resetModalTabs: function(modal) {
			if ( !modal || !modal.length) {
				return;
			}
			
			// Remove active class from all tabs and contents.
			modal.find('.epofw-tab-btn').removeClass('active');
			modal.find('.epofw-tab-content').removeClass('active');
			
			// Activate first tab and its content.
			var firstTab = modal.find('.epofw-tab-btn').first();
			var firstTabId = firstTab.data('tab');
			
			if (firstTab.length && firstTabId) {
				firstTab.addClass('active');
				modal.find('.epofw-tab-content[data-tab="' + firstTabId + '"]').addClass('active');
			}
		},

		// Modern form validation system.
		validateForm: function(modal) {
			var hasErrors = false;
			var errorTabs = new Set();

			// Clear previous validation states.
			modal.find('.epofw-form-control').removeClass('epofw-error');
			modal.find('.epofw-tab-btn').removeClass('epofw-tab-error');

			// Get field type to determine validation rules
			var fieldType = modal.find('input[name*="[field][type]"]').val();

			// Fields that don't require a label (display-only fields)
			var fieldsWithoutLabel = ['heading', 'paragraph', 'html', 'separator'];

			// Explicitly validate label field for fields that require it
			if (fieldsWithoutLabel.indexOf(fieldType) === -1) {
				var $labelField = modal.find('input[name*="[label][title]"]');
				if ($labelField.length) {
					var labelValue = $labelField.val() ? $labelField.val().trim() : '';
					var tabId = $labelField.closest('.epofw-tab-content').data('tab');

					if (!labelValue) {
						hasErrors = true;
						$labelField.addClass('epofw-error');

						if (tabId) {
							errorTabs.add(tabId);
						}
					}
				}
			}

			// Validate all required fields (check both required and data-was-required attributes).
			modal.find('.epofw-form-control[required], .epofw-form-control[data-was-required="true"]').each(function() {
				var $field = $(this);
				var value = $field.val() ? $field.val().trim() : '';
				var tabId = $field.closest('.epofw-tab-content').data('tab');

				if (!value) {
					hasErrors = true;
					$field.addClass('epofw-error');

					// Mark tab as having errors.
					if (tabId) {
						errorTabs.add(tabId);
					}
				}
			});

			// Validate options for fields that require them (select, radio, checkbox group, multiselect, checkbox)
			var fieldsRequiringOptions = ['select', 'multiselect', 'radiogroup', 'checkboxgroup', 'checkbox', 'colorswitcher', 'textswitcher', 'imageswitcher'];

			if (fieldsRequiringOptions.indexOf(fieldType) !== -1) {
				var $optionsTab = modal.find('.epofw-tab-content[data-tab*="options"]');
				if ($optionsTab.length) {
					var $optionRows = $optionsTab.find('.epofw-option-row');
					var hasValidOptions = false;

					// Check if at least one option has a valid label or value
					$optionRows.each(function() {
						var $row = $(this);
						var optionLabel = $row.find('input[name*="[label]"]').val() || '';
						var optionValue = $row.find('input[name*="[value]"]').val() || '';
						if (optionLabel.trim() || optionValue.trim()) {
							hasValidOptions = true;
							return false; // break the loop
						}
					});

					// If no valid options, mark options tab with error
					if (!hasValidOptions) {
						hasErrors = true;
						var optionsTabId = $optionsTab.data('tab');
						if (optionsTabId) {
							errorTabs.add(optionsTabId);
						}
					}

					// Also check if option rows have filled required fields (check both required and data-was-required)
					$optionRows.each(function() {
						var $row = $(this);
						$row.find('.epofw-form-control[required], .epofw-form-control[data-was-required="true"]').each(function() {
							var $field = $(this);
							var value = $field.val() ? $field.val().trim() : '';

							if (!value) {
								hasErrors = true;
								$field.addClass('epofw-error');

								var optionsTabId = $optionsTab.data('tab');
								if (optionsTabId) {
									errorTabs.add(optionsTabId);
								}
							}
						});
					});
				}
			}
			
			// Highlight tabs with errors.
			errorTabs.forEach(function(tabId) {
				modal.find('.epofw-tab-btn[data-tab="' + tabId + '"]').addClass('epofw-tab-error');
			});
			
			// Show a summary message if there are errors.
			if (hasErrors) {
				this.showValidationSummary(modal, errorTabs.size);
			}
			
			return !hasErrors;
		},
		
		// Show validation summary.
		showValidationSummary: function(modal, errorTabCount) {
			// Remove existing summary.
			modal.find('.epofw-validation-summary').remove();
			
			var summaryHtml = '<div class="epofw-validation-summary">' +
				'<div class="epofw-validation-header">' +
				'<i class="dashicons dashicons-warning"></i>' +
				'<span>Please fix the following errors:</span>' +
				'</div>' +
				'<div class="epofw-validation-details">' +
				'<p>• ' + errorTabCount + ' tab(s) contain required fields that need attention</p>' +
				'<p>• Fields marked with red borders are required</p>' +
				'</div>' +
				'</div>';
			
			// Insert summary at the top of modal body.
			modal.find('.epofw-modal-body').prepend(summaryHtml);
			
			// Scroll to top to show summary.
			modal.find('.epofw-modal-body').scrollTop(0);
		},
		
		// Clear validation errors.
		clearValidationErrors: function(modal) {
			modal.find('.epofw-form-control').removeClass('epofw-error');
			modal.find('.epofw-tab-btn').removeClass('epofw-tab-error');
			modal.find('.epofw-validation-summary').remove();
		},
		
		// Real-time validation on field change
		initRealTimeValidation: function(modal) {
			var self = this;
			
			// Use event delegation to catch all required fields, including dynamically added ones
			modal.on('input change', '.epofw-form-control[required]', function() {
				var $field = $(this);
				var value = $field.val().trim();
				
				if (value) {
					$field.removeClass('epofw-error');
					
					// Check if tab still has errors
					var tabId = $field.closest('.epofw-tab-content').data('tab');
					if (tabId) {
						var tabHasErrors = $field.closest('.epofw-tab-content').find('.epofw-form-control[required].epofw-error').length > 0;
						if (!tabHasErrors) {
							modal.find('.epofw-tab-btn[data-tab="' + tabId + '"]').removeClass('epofw-tab-error');
						}
					}
					
					// Update validation summary in real-time
					self.updateValidationSummary(modal);
			} else {
					// Field is empty, add error class
					$field.addClass('epofw-error');
					
					// Update validation summary in real-time
					self.updateValidationSummary(modal);
				}
			});
			
			// Also monitor for dynamically added fields
			modal.on('DOMNodeInserted', '.epofw-form-control[required]', function() {
				// The field will automatically be monitored by the event delegation above
			});
		},
		
		// Update validation summary in real-time
		updateValidationSummary: function(modal) {
			var errorTabs = new Set();
			var totalErrors = 0;
			
			// Count current errors
			modal.find('.epofw-form-control[required].epofw-error').each(function() {
				totalErrors++;
				var tabId = $(this).closest('.epofw-tab-content').data('tab');
				if (tabId) {
					errorTabs.add(tabId);
				}
			});
			
			// Update or remove validation summary
			if (totalErrors > 0) {
				var currentSummary = modal.find('.epofw-validation-summary');
				if (currentSummary.length > 0) {
					// Update existing summary
					currentSummary.find('.epofw-validation-details p:first').text('• ' + errorTabs.size + ' tab(s) contain required fields that need attention');
				} else {
					// Show new summary
					this.showValidationSummary(modal, errorTabs.size);
				}
			} else {
				// No errors, remove summary
				modal.find('.epofw-validation-summary').remove();
			}
		},

		sectionTitleEdit: function(e) {
			e.preventDefault();
			var $input = $(this);
			var newText = $input.val().trim();
			if ( newText ) {
				var sectionId = $input.attr('data-section-id');
				$('input[name="epofw_section[' + sectionId + '][title]"]').val( newText );
			}
		},

		sectionEdit: function (e) {
			e.preventDefault();

			var sectionId = $(this).data('section-id');
			var sectionSettingsModal = $('#section-settings-modal-' + sectionId);
			
			if (!sectionSettingsModal.length) {
				return;
			}
			
			// Check if modal content is already loaded
			var hasContent = sectionSettingsModal.find('.epofw-modal-content-wrapper').children().length > 0;
			
			if (!hasContent) {
				// Load content via AJAX
				AWS_ADMIN.loadSectionSettingsContent(sectionSettingsModal, sectionId);
			} else {
				// Content already loaded, just show
				// Reset modal tabs to first tab
				AWS_ADMIN.resetModalTabs(sectionSettingsModal);
				
				// Initialize real-time validation
				AWS_ADMIN.initRealTimeValidation(sectionSettingsModal);
				
				// Initialize color pickers in modal
				sectionSettingsModal.find('.epofw_colorpicker').each(function() {
					if (!$(this).hasClass('wp-color-picker')) {
						$(this).wpColorPicker();
					}
				});
				
				// Initialize toggle switches in this modal
				AWS_ADMIN.initModalToggles(sectionSettingsModal);
				
				// Show the modal
				sectionSettingsModal.show();
			}
		},

		// Load section settings form content via AJAX
		loadSectionSettingsContent: function($modal, sectionId) {
			// Show loader
			AWS_ADMIN.showModalLoader( $modal, 'loading_settings' );
			$modal.show();

			// Get current section order from the section header hidden input
			var $section = $('.epofw-section[data-section-id="' + sectionId + '"]');
			var sectionOrder = $section.find('input[name="epofw_section[' + sectionId + '][order]"]').val() || '1';

			jQuery.ajax({
				type: 'post',
				url: epofw_var.ajaxurl,
				data: {
					action: 'epofw_get_section_settings',
					section_id: sectionId,
					section_order: sectionOrder,
					nonce: epofw_var.element_add_nonce
				},
				success: function(response) {
					if (response.success) {
						$modal.find('.epofw-modal-content-wrapper').html(response.data.content);
						
						// Initialize after content loaded
						setTimeout(function() {
							AWS_ADMIN.resetModalTabs($modal);
							
							$modal.find('.epofw_colorpicker').each(function() {
								if (!$(this).hasClass('wp-color-picker')) {
									$(this).wpColorPicker();
								}
							});
							
							AWS_ADMIN.initModalToggles($modal);
							$modal.show();
						}, 50);
					} else {
						// Show modal even if AJAX fails
						$modal.show();
					}
				},
				error: function() {
					$modal.show();
				}
			});
		},

		sectionTitleEditOnSpan: function (e) {
			e.preventDefault();
			var $span = $( this );
				var currentText = $span.text();
				var $input = $( '<input type="text" class="epofw-section-title-edit" value="' + currentText + '" data-section-id="' + $span.closest('.epofw-section').attr('data-section-id') + '" />' );

				$span.hide();
				$span.after( $input );
				$input.focus().select();

				$input.on( 'blur keypress', function( e ) {
					if ( e.type === 'blur' || e.which === 13 ) {
						var newText = $input.val().trim();
						if ( newText ) {
							$span.text( newText );
						}
						$input.remove();
						$span.show();
					}
				} );
		},

		// Toggle section accordion (collapse/expand)
		toggleSectionAccordion: function (e) {
			e.preventDefault();
			e.stopPropagation();

			var $icon = $(this);
			var $section = $icon.closest('.epofw-section');
			var $content = $section.find('.epofw-section-content');

			if ($section.hasClass('epofw-section-collapsed')) {
				// Expand
				$content.slideDown(200);
				$section.removeClass('epofw-section-collapsed');
				$icon.removeClass('dashicons-arrow-up-alt').addClass('dashicons-arrow-down-alt');
			} else {
				// Collapse
				$content.slideUp(200);
				$section.addClass('epofw-section-collapsed');
				$icon.removeClass('dashicons-arrow-down-alt').addClass('dashicons-arrow-up-alt');
			}
		},

		handleDeleteButtonClick: function () {
			var $this      = $( this );
			var $card      = $this.closest( '.epofw-addon-card' );
			var $productId = $card.data( 'id' );
			if ( confirm( epofw_var.strings.delete_addon_confirm ) ) {
				// Show loader on card
				AWS_ADMIN.showCardLoader( $card, 'deleting' );

				jQuery.ajax(
					{
						type: 'post',
						url: epofw_var.ajaxurl,
						data: {
							action: 'epofw_delete_addon',
							get_post_id: $productId,
							delete_addon_nonce: epofw_var.delete_addon_nonce,
						},
						success: function ( response ) {
							if ( response ) {
								if ( true === response.success ) {
								var $cardStatus = $card.data('status');

								// Remove the card
								$card.remove();
									AWS_ADMIN.toastMessage( 'success', response.data.msg );

								// Update stats counters
								AWS_ADMIN.updateAddonStats($cardStatus);

								// Check if no addons remain and show empty state
								AWS_ADMIN.checkAndShowEmptyState();
								} else {
									AWS_ADMIN.hideCardLoader( $card );
									AWS_ADMIN.toastMessage( 'error', response.data.msg );
								}
							}
						},
						error: function () {
							AWS_ADMIN.hideCardLoader( $card );
							// AJAX error occurred.
						}
					}
				);
			}
		},


		handleDuplicateButtonClick: function () {
			var $this      = $( this );
			var $card      = $this.closest( '.epofw-addon-card' );
			var $productId = $card.data( 'id' );
			if ( confirm( epofw_var.strings.duplicate_addon_confirm ) ) {
				// Show loader on card
				AWS_ADMIN.showCardLoader( $card, 'duplicating' );

				jQuery.ajax(
					{
						type: 'post',
						url: epofw_var.ajaxurl,
						data: {
							action: 'epofw_duplicate_addon',
							get_post_id: $productId,
							duplicate_addon_nonce: epofw_var.duplicate_addon_nonce,
						},
						success: function ( response ) {
							// Hide loader
							AWS_ADMIN.hideCardLoader( $card );

							if ( response ) {
								if ( true === response.success ) {
									// Show success message
									AWS_ADMIN.toastMessage( 'success', response.data.msg );


									var $originalCard = $( '.epofw-addon-card[data-id="' + $productId + '"]' );
									var $newCard = $originalCard.clone();

									// Remove any loader from cloned card
									$newCard.find('.epofw-card-loader-overlay').remove();

									// Update the new card with new ID and title
									$newCard.attr( 'data-id', response.data.new_product_id );
							$newCard.attr( 'data-status', 'inactive' );
									$newCard.find( '.epofw-card-header .epofw-card-type span' ).text( response.data.post_data.post_title );
									$newCard.find( '.epofw-card-header .epofw-card-status' ).removeClass( 'active inactive' ).addClass( 'inactive' );
									$newCard.find('.epofw-card-header .epofw-card-status').text(response.data.status);
									$newCard.find('.epofw-card-body .epofw-meta-item:first span').text( response.data.updated_at + ' ' + response.data.post_data.post_date );
									$newCard.find('.epofw-edit-btn').attr('href', response.data.edit_url);
									$originalCard.after( $newCard) ;

							// Update stats - new addon is inactive
							AWS_ADMIN.updateAddonStatsAfterAdd('inactive');

							// Hide empty state if it's showing
							$('#empty-state').hide();
							$('.epofw-addons-container').show();
								} else {
									AWS_ADMIN.toastMessage( 'error', response.data.msg );
								}
							}
						},
						error: function () {
							AWS_ADMIN.hideCardLoader( $card );
							// AJAX error occurred.
							AWS_ADMIN.toastMessage( 'error', 'An error occurred while duplicating the addon.' );
						}
					}
				);
			}
		},

	// Add duplicated addon card to the page
	/*jshint unused:true */
	addDuplicatedAddonCard: function( _originalId, _newId ) {
		// TODO: Implement addon card duplication functionality
		// Parameters reserved for future implementation
		void _originalId;
		void _newId;
	},

	handleExportButtonClick: function () {
		var $this = $( this );
		var addonId = $this.data( 'addon-id' );
		
		if ( !addonId ) {
			AWS_ADMIN.toastMessage( 'error', 'Addon ID not found.' );
			return;
		}

		// Show loading message
		AWS_ADMIN.toastMessage( 'info', 'Exporting addon configuration...' );

		jQuery.ajax({
			type: 'post',
			url: epofw_var.ajaxurl,
			data: {
				action: 'epofw_export_addon',
				addon_id: addonId,
				nonce: epofw_var.epofw_admin_nonce,
			},
			success: function ( response ) {
				if ( response.success ) {
					// Create a blob and trigger download
					var jsonData = JSON.stringify( response.data.addon_data, null, 2 );
					var blob = new Blob( [jsonData], { type: 'application/json' } );
					var url = window.URL.createObjectURL( blob );
					var a = document.createElement( 'a' );
					a.href = url;
					a.download = response.data.filename;
					document.body.appendChild( a );
					a.click();
					window.URL.revokeObjectURL( url );
					document.body.removeChild( a );
					
					AWS_ADMIN.toastMessage( 'success', 'Addon exported successfully!' );
				} else {
					AWS_ADMIN.toastMessage( 'error', response.data.msg || 'Export failed.' );
				}
			},
			error: function () {
				AWS_ADMIN.toastMessage( 'error', 'An error occurred while exporting the addon.' );
			}
		});
	},

	handleImportButtonClick: function ( e ) {
		e.preventDefault();
		e.stopPropagation();
		// Show confirmation modal
		AWS_ADMIN.showImportConfirmationModal();
	},

	showImportConfirmationModal: function() {
		// Remove any existing import modals
		$('.epofw-import-overlay, .epofw-import-modal-overlay').remove();

		// Use template for import modal
		var importModalTmpl = wp.template('epofw-import-modal');
		if ( ! importModalTmpl ) {
			return;
		}
		
		var $modal = $( importModalTmpl({
			title: epofw_var.strings.import_demo_addons || 'Import Demo Addons',
			message: epofw_var.strings.import_confirm_message || 'This will import demo addons with all field types.',
			will_import: epofw_var.strings.this_will_import || 'This will import:',
			demo_tshirt: epofw_var.strings.demo_tshirt || 'Demo T-Shirt',
			demo_pizza: epofw_var.strings.demo_pizza || 'Demo Pizza',
			demo_event: epofw_var.strings.demo_event || 'Demo Event',
			demo_premium: epofw_var.strings.demo_premium || 'Demo Premium',
			is_premium: epofw_var.is_premium || false,
			cancel: epofw_var.strings.cancel || 'Cancel',
			import_now: epofw_var.strings.import_now || 'Import Now'
		}) );
		$('body').append($modal);

		// Bind click handlers
		$('.epofw-import-cancel, .epofw-import-overlay').on('click', function(e) {
			if ($(e.target).hasClass('epofw-import-overlay') || $(e.target).hasClass('epofw-import-cancel')) {
				$('.epofw-import-overlay').fadeOut(300, function() {
					$(this).remove();
				});
			}
		});

		$('.epofw-import-confirm').on('click', function() {
			AWS_ADMIN.processImport();
		});
	},

	processImport: function() {
		// Hide confirmation modal content and show loading
		$('.epofw-import-info').html('<div class="epofw-import-loading"><span class="spinner is-active"></span><p>' + epofw_var.strings.importing + '</p></div>');
		$('.epofw-import-buttons').hide();

		// Make AJAX request
		$.ajax({
			url: epofw_var.ajaxurl,
			type: 'POST',
			data: {
				action: 'epofw_import_all_fields_ajax',
				nonce: epofw_var.import_fields_nonce
			},
			success: function(response) {
				// Check if response has the expected structure
				if (response && typeof response === 'object' && response.success) {
					// Show success message
					var message = (response.data && response.data.message) ? response.data.message : epofw_var.strings.imported;
					var redirectUrl = (response.data && response.data.redirect_url) ? response.data.redirect_url : window.location.href;

					$('.epofw-import-info').html('<div class="epofw-import-success"><i class="dashicons dashicons-yes-alt"></i><p>' + message + '</p></div>');

					// Redirect after 2 seconds
					setTimeout(function() {
						window.location.href = redirectUrl;
					}, 2000);
				} else {
					// Show error message
					var errorMessage = (response && response.data && response.data.message) ? response.data.message : epofw_var.strings.import_error;
					$('.epofw-import-info').html('<div class="epofw-import-error"><i class="dashicons dashicons-dismiss"></i><p>' + errorMessage + '</p></div>');
					$('.epofw-import-buttons').html('<button type="button" class="button button-primary epofw-import-close-final">OK</button>').show();

					$('.epofw-import-close-final').on('click', function() {
						$('.epofw-import-overlay').fadeOut(300, function() {
							$(this).remove();
						});
					});
				}
			},
			error: function() {
				// Show error message
				$('.epofw-import-info').html('<div class="epofw-import-error"><i class="dashicons dashicons-dismiss"></i><p>' + epofw_var.strings.import_error + '</p></div>');
				$('.epofw-import-buttons').html('<button type="button" class="button button-primary epofw-import-close-final">OK</button>').show();

				$('.epofw-import-close-final').on('click', function() {
					$('.epofw-import-overlay').fadeOut(300, function() {
						$(this).remove();
					});
				});
			}
		});
	},

	handleAddonFormSubmit: function (e) {
		// Only validate if this is the addon save form
		var $form = $(this);
		if ($form.find('.epofw-save-addon').length === 0) {
			return true; // Not the addon form, allow submission
		}

		// Check if any premium fields exist in the builder for free users.
		var premiumFieldTypes = epofw_var.premium_field_types || [];
		var isPremiumUser = epofw_var.is_premium || false;

		if ( ! isPremiumUser ) {
			var hasPremiumFields = false;
			var premiumFieldNames = [];

			$('.epofw-element').each(function() {
				var elementType = $(this).attr('data-element-type');
				if ( premiumFieldTypes.indexOf( elementType ) !== -1 ) {
					hasPremiumFields = true;
					var fieldTitle = $(this).find('.epofw-element-title').text() || elementType;
					premiumFieldNames.push( fieldTitle );
				}
			});

			if ( hasPremiumFields ) {
				e.preventDefault();
				AWS_ADMIN.showPremiumUpgradePopup();
				return false;
			}
		}

		// Disable browser's native required validation on ALL modal fields
		// We handle validation ourselves via JavaScript - this prevents
		// "An invalid form control is not focusable" errors on hidden fields
		var $requiredFields = $('.epofw-element-modal, .epofw-section-modal').find('[required]');
		$requiredFields.each(function() {
			$(this).removeAttr('required').attr('data-was-required', 'true');
		});

		var hasErrors = false;
		var requiredFields = [];
		var fieldsWithMissingOptions = [];

		// Validate addon name
		var $addonName = $('#epofw_addon_name');
		if ($addonName.length && !$addonName.val().trim()) {
			hasErrors = true;
			requiredFields.push('Addon Name');
			$addonName.addClass('epofw-error').css('border', '2px solid #dc3232');
		} else if ($addonName.length) {
			$addonName.removeClass('epofw-error').css('border', '');
		}

		// Validate that at least one section exists
		var $sections = $('.epofw-section');
		if ($sections.length === 0) {
			hasErrors = true;
			requiredFields.push('At least one Section');
		}

		// Track fields with missing labels and options
		var fieldsWithMissingLabels = [];
		var $firstErrorElement = null;

		// Validate that fields requiring options have at least one option
		var fieldsRequiringOptions = ['select', 'multiselect', 'radiogroup', 'checkboxgroup', 'checkbox', 'colorswitcher', 'textswitcher', 'imageswitcher'];

		// Fields that don't require a label (display-only fields)
		var fieldsWithoutLabel = ['heading', 'paragraph', 'html', 'separator'];

		$('.epofw-element').each(function() {
			var $element = $(this);
			var elementType = $element.attr('data-element-type');
			var elementId = $element.attr('data-element-id');
			var $modal = $('#element-settings-modal-' + elementId);
			var sectionTitle = $element.closest('.epofw-section').find('.epofw-section-title span').first().text() || 'Unnamed Section';
			var elementTitle = $element.find('.epofw-element-title').text() || '';
			var hasFieldError = false;
			var fieldIdentifier = '';

			// Check if field has a label (skip heading, paragraph, html)
			if (fieldsWithoutLabel.indexOf(elementType) === -1) {
				var fieldLabel = '';
				if ($modal.length) {
					fieldLabel = $modal.find('input[name*="[label][title]"]').val() || '';
				}
				// If modal doesn't exist, field hasn't been configured yet - no label

				if (!fieldLabel.trim()) {
					hasErrors = true;
					hasFieldError = true;
					fieldIdentifier = elementTitle.trim() ? elementTitle : elementType + ' (ID: ' + elementId.substr(-6) + ')';
					fieldsWithMissingLabels.push(fieldIdentifier + ' in "' + sectionTitle + '"');

					if (!$firstErrorElement) {
						$firstErrorElement = $element;
					}
				}
			}

			// Check if this field type requires options
			if (fieldsRequiringOptions.indexOf(elementType) !== -1) {
				var hasValidOptions = false;

				if ($modal.length) {
					var $optionsContainer = $modal.find('.epofw-options-container');
					var $optionRows = $optionsContainer.find('.epofw-option-row');

					// Check if any option row has a valid label/value
					$optionRows.each(function() {
						var $row = $(this);
						// Check for option label input (most common required field)
						var optionLabel = $row.find('input[name*="[label]"]').val() || '';
						var optionValue = $row.find('input[name*="[value]"]').val() || '';
						if (optionLabel.trim() || optionValue.trim()) {
							hasValidOptions = true;
							return false; // break the loop
						}
					});
				}
				// If modal doesn't exist, field hasn't been configured yet - no options

				// Check if no valid options exist
				if (!hasValidOptions) {
					hasErrors = true;
					hasFieldError = true;
					fieldIdentifier = elementTitle.trim() ? elementTitle : elementType + ' (ID: ' + elementId.substr(-6) + ')';
					fieldsWithMissingOptions.push(fieldIdentifier + ' in "' + sectionTitle + '"');

					if (!$firstErrorElement) {
						$firstErrorElement = $element;
					}
				}
			}

			// Highlight field with error or remove highlight
			if (hasFieldError) {
				$element.addClass('epofw-element-error').css('border', '2px solid #dc3232');
			} else {
				$element.removeClass('epofw-element-error').css('border', '');
			}
		});

		// If there are errors, show message and prevent submission
		if (hasErrors) {
			e.preventDefault();

			// Restore required attributes
			$('[data-was-required="true"]').each(function() {
				$(this).attr('required', 'required').removeAttr('data-was-required');
			});

			// Remove existing error message
			$('.epofw-addon-validation-error').remove();

			// Create error message
			var errorHtml = '<div class="epofw-addon-validation-error notice notice-error is-dismissible" style="margin: 15px 0; padding: 12px;">' +
				'<p><strong>' + epofw_var.strings.validation_error_title + '</strong></p>' +
				'<p>' + epofw_var.strings.required_fields_missing + '</p>' +
				'<ul style="list-style: disc; margin-left: 20px;">';

			requiredFields.forEach(function(field) {
				errorHtml += '<li>' + field + '</li>';
			});

			if (fieldsWithMissingLabels.length > 0) {
				errorHtml += '<li><strong>Fields missing label/title:</strong><ul style="margin-left: 20px;">';
				fieldsWithMissingLabels.forEach(function(field) {
					errorHtml += '<li>' + field + '</li>';
				});
				errorHtml += '</ul></li>';
			}

			if (fieldsWithMissingOptions.length > 0) {
				errorHtml += '<li><strong>Fields missing options:</strong><ul style="margin-left: 20px;">';
				fieldsWithMissingOptions.forEach(function(field) {
					errorHtml += '<li>' + field + '</li>';
				});
				errorHtml += '</ul></li>';
			}

			errorHtml += '</ul></div>';

			// Insert error message at the top of the addon configuration box
			$('.epofw-configuration-box .epofw-box-content').prepend(errorHtml);

			// Scroll to first error element if exists, otherwise to error message
			if ($firstErrorElement && $firstErrorElement.length) {
				$('html, body').animate({
					scrollTop: $firstErrorElement.offset().top - 150
				}, 500);
			} else {
				$('html, body').animate({
					scrollTop: $('.epofw-addon-validation-error').offset().top - 100
				}, 500);
			}

			return false;
		}
		
		// Form passes validation - use AJAX save to bypass max_input_vars limit
		e.preventDefault();

		// Show loading indicator
		var $saveBtn = $form.find('.epofw-save-addon');
		var originalBtnText = $saveBtn.val();
		$saveBtn.val( epofw_var.strings.saving ).prop('disabled', true);

		// Show full-page save overlay using template
		var saveOverlayTmpl = wp.template('epofw-save-overlay');
		var $saveOverlay = $( saveOverlayTmpl({ text: epofw_var.strings.saving_addon }) );
		$('body').append($saveOverlay);

		// CRITICAL 1: Update section order based on current DOM position
		$('.epofw-section').each(function(index) {
			var $section = $(this);
			var sectionId = $section.data('section-id');
			var newOrder = index + 1; // 1-based ordering
			$section.find('input[name="epofw_section[' + sectionId + '][order]"]').val(newOrder);
		});

		// CRITICAL 2: Before serialization, collect JSON for ALL fields (not just those with open modals).
		// This ensures existing fields that weren't edited don't get lost on save.
		$form.find('.epofw-element').each(function() {
			var $element = $(this);
			var elementId = $element.data('element-id');
			var $modal = $('#element-settings-modal-' + elementId);

			// Skip if no modal exists for this element
			if (!$modal.length) {
				return;
			}

			// Collect field data from modal and store as JSON
			var fieldData = AWS_ADMIN.collectFieldDataAsJSON($modal, elementId);

			// Remove old JSON input if exists
			$element.find('.epofw-field-json').remove();

			// Create single hidden input with JSON data
			var $jsonInput = $('<input type="hidden" class="epofw-field-json">');
			$jsonInput.attr('name', 'epofw_field_json[' + elementId + ']');
			$jsonInput.val(JSON.stringify(fieldData));
			$element.append($jsonInput);
		});

		// Collect form data - exclude modal inputs.
		// Field data is now sent as JSON (epofw_field_json) to reduce input count.
		// Disable modal inputs during serialization to avoid any duplication.
		var $modalInputs = $form.find('.epofw-element-modal input, .epofw-element-modal select, .epofw-element-modal textarea, .epofw-section-modal input, .epofw-section-modal select, .epofw-section-modal textarea');
		$modalInputs.prop('disabled', true);
		var formDataString = $form.serialize();
		$modalInputs.prop('disabled', false);

		// Get post ID - try multiple sources
		var postId = epofw_var.get_post_id || 0;

		// If not in epofw_var, try to get from URL (use 'post' param, which is the correct format)
		if (!postId || postId === '0' || postId === 0) {
			var urlParams = new URLSearchParams(window.location.search);
			postId = urlParams.get('post') || urlParams.get('id') || 0;
		}

		// Add post ID and action type
		formDataString += '&get_post_id=' + encodeURIComponent(postId);
		formDataString += '&action_type=' + encodeURIComponent((postId && parseInt(postId) > 0) ? 'edit' : 'add');

		// Send via AJAX - the form data is sent as a base64-encoded string to bypass max_input_vars
		$.ajax({
			url: epofw_var.ajaxurl,
			type: 'POST',
			data: {
				action: 'epofw_ajax_save_addon',
				ajax_save_nonce: epofw_var.ajax_save_nonce,
				form_data_encoded: btoa(decodeURIComponent(encodeURIComponent(formDataString)))
			},
			success: function(response) {
				if (response.success) {
					if (response.data && response.data.redirect_url) {
						window.location.href = response.data.redirect_url;
					} else {
						window.location.reload();
					}
				} else {
					var errorMsg = (response.data && response.data.msg) ? response.data.msg : epofw_var.strings.save_error;
					alert( epofw_var.strings.save_failed + ' ' + errorMsg );
					$saveOverlay.remove();
					$saveBtn.val(originalBtnText).prop('disabled', false);
				}
			},
			error: function(xhr, status, error) {
				alert( epofw_var.strings.save_failed + ' ' + error );
				$saveOverlay.remove();
				$saveBtn.val(originalBtnText).prop('disabled', false);
			}
		});

		return false;
		},
				
		toastMessage: function(icon, message) {
			toastr[icon](message, {}, { closeButton: true, positionClass: 'toast-bottom-right' });
		},

		// Show loader overlay on card using WordPress template
		showCardLoader: function( $card, textKey ) {
			var template = wp.template( 'epofw-card-loader' );
			if ( ! template ) {
				return;
			}
			var text = epofw_var.strings[ textKey ] || epofw_var.strings.loading || textKey;
			var loaderHtml = template( { text: text } );
			$card.css( 'position', 'relative' ).append( loaderHtml );
		},

		// Hide loader overlay from card
		hideCardLoader: function( $card ) {
			$card.find( '.epofw-card-loader-overlay' ).remove();
		},

		// Show loader in modal using WordPress template
		showModalLoader: function( $modal, textKey ) {
			var template = wp.template( 'epofw-modal-loader' );
			if ( ! template ) {
				return;
			}
			var text = epofw_var.strings[ textKey ] || epofw_var.strings.loading || textKey;
			var loaderHtml = template( { text: text } );
			$modal.find( '.epofw-modal-content-wrapper' ).css( 'position', 'relative' ).html( loaderHtml );
		},

		// Hide loader from modal
		hideModalLoader: function( $modal ) {
			$modal.find( '.epofw-modal-loader-overlay' ).remove();
		},

	// Update addon stats after deletion
	updateAddonStats: function(deletedStatus) {
		// Get current counts
		var $totalStat = $('.epofw-stats-grid .epofw-stat-item:first .epofw-stat-number');
		var $activeStat = $('.epofw-stats-grid .epofw-stat-item:nth-child(2) .epofw-stat-number');
		var $inactiveStat = $('.epofw-stats-grid .epofw-stat-item:nth-child(3) .epofw-stat-number');
		
		var totalCount = parseInt($totalStat.text()) || 0;
		var activeCount = parseInt($activeStat.text()) || 0;
		var inactiveCount = parseInt($inactiveStat.text()) || 0;
		
		// Decrement total
		totalCount = Math.max(0, totalCount - 1);
		
		// Decrement active or inactive based on deleted addon's status
		if (deletedStatus === 'active') {
			activeCount = Math.max(0, activeCount - 1);
		} else if (deletedStatus === 'inactive') {
			inactiveCount = Math.max(0, inactiveCount - 1);
		}
		
		// Update the DOM
		$totalStat.text(totalCount);
		$activeStat.text(activeCount);
		$inactiveStat.text(inactiveCount);
	},
	
	// Check if no addons remain and show empty state
	checkAndShowEmptyState: function() {
		var remainingAddons = $('.epofw-addon-card').length;
		
		if (remainingAddons === 0) {
			// Hide the addons container
			$('.epofw-addons-container').hide();
			
			// Show the empty state
			$('#empty-state').show();
		}
	},
	
	// Update addon stats after adding (duplication)
	updateAddonStatsAfterAdd: function(newStatus) {
		// Get current counts
		var $totalStat = $('.epofw-stats-grid .epofw-stat-item:first .epofw-stat-number');
		var $activeStat = $('.epofw-stats-grid .epofw-stat-item:nth-child(2) .epofw-stat-number');
		var $inactiveStat = $('.epofw-stats-grid .epofw-stat-item:nth-child(3) .epofw-stat-number');
		
		var totalCount = parseInt($totalStat.text()) || 0;
		var activeCount = parseInt($activeStat.text()) || 0;
		var inactiveCount = parseInt($inactiveStat.text()) || 0;
		
		// Increment total
		totalCount = totalCount + 1;
		
		// Increment active or inactive based on new addon's status
		if (newStatus === 'active') {
			activeCount = activeCount + 1;
		} else if (newStatus === 'inactive') {
			inactiveCount = inactiveCount + 1;
		}
		
		// Update the DOM
		$totalStat.text(totalCount);
		$activeStat.text(activeCount);
		$inactiveStat.text(inactiveCount);
	},
	
	// Update stats after toggling status
	updateStatsAfterToggle: function(oldStatus, newStatus) {
		// Get current counts
		var $activeStat = $('.epofw-stats-grid .epofw-stat-item:nth-child(2) .epofw-stat-number');
		var $inactiveStat = $('.epofw-stats-grid .epofw-stat-item:nth-child(3) .epofw-stat-number');
		
		var activeCount = parseInt($activeStat.text()) || 0;
		var inactiveCount = parseInt($inactiveStat.text()) || 0;
		
		// Update counts based on status change
		if (oldStatus === 'active' && newStatus === 'inactive') {
			activeCount = Math.max(0, activeCount - 1);
			inactiveCount = inactiveCount + 1;
		} else if (oldStatus === 'inactive' && newStatus === 'active') {
			inactiveCount = Math.max(0, inactiveCount - 1);
			activeCount = activeCount + 1;
		}
		
		// Update the DOM
		$activeStat.text(activeCount);
		$inactiveStat.text(inactiveCount);
	},
		
		// Initialize toast notifications from PHP
		initToastNotifications: function () {
			var urlParams = new URLSearchParams(window.location.search);
			var message   = urlParams.get('msg') || '';
			var tab = urlParams.get('tab') || '';
			var showToast = false;
			
			if ( message && 'field-section' === tab ) {
				if ( 'saved' === message ) {
					AWS_ADMIN.toastMessage('success', epofw_var.strings.saved );
					showToast = true;
				}
				if ( 'deleted' === message ) {
					AWS_ADMIN.toastMessage('success', epofw_var.strings.deleted );
					showToast = true;
				}
				if ( 'created' === message ) {
					AWS_ADMIN.toastMessage('success', epofw_var.strings.created );
					showToast = true;
				}
				if ( 'duplicated' === message ) {
					AWS_ADMIN.toastMessage('success', epofw_var.strings.duplicated );
					showToast = true;
				}
			if ( 'imported' === message ) {
				AWS_ADMIN.toastMessage('success', epofw_var.strings.imported );
				showToast = true;
			}
				if ( 'failed' === message ) {
					AWS_ADMIN.toastMessage('error', epofw_var.strings.failed );
					showToast = true;
				}
			} else if ( message && 'settings' === tab ) {
				if ('saved' === message) {
					AWS_ADMIN.toastMessage('success', epofw_var.strings.settings_saved );
					showToast = true;
				}
				if ( 'nonce_check' === message ) {
					AWS_ADMIN.toastMessage('error', epofw_var.strings.nonce_check );
					showToast = true;
				}
				if ( 'validated' === message ) {
					AWS_ADMIN.toastMessage('error', epofw_var.strings.validated );
					showToast = true;
				}
			}
			
			// Remove msg parameter from URL after showing toast.
			if ( showToast && message ) {
				urlParams.delete('msg');
				var newUrl = window.location.pathname + (urlParams.toString() ? '?' + urlParams.toString() : '');
				window.history.replaceState({}, document.title, newUrl);
			}
		},

		// Row Management Functions.
		showRowSelectionModal: function(e) {
			e.preventDefault();
			var sectionId = $(this).data('section-id');
			
			// Create modal from template
			var template = $('#tmpl-epofw-row-selection-modal').html();
			if (!template) {
				return;
			}
			
			var modal = $(template);
			
			// Add modal to body and show it
			$('body').append(modal);
			modal.attr('id', 'row-selection-modal-' + sectionId);
			modal.data('section-id', sectionId);
			
			// Auto-select the first option (1 row) by default
			var $firstOption = modal.find('.epofw-row-option').first();
			$firstOption.addClass('active');
			var rowsCount = $firstOption.data('rows');
			modal.data('selected-rows', rowsCount);
			
			// Handle modal close/cancel specifically for row selection modal
			modal.find('.epofw-modal-close, .epofw-modal-cancel, .epofw-modal-overlay').on('click', function(e) {
				e.preventDefault();
				e.stopPropagation();
				modal.hide();
				modal.remove();
			});
			
			modal.show();
		},

		selectRowOption: function(e) {
			e.preventDefault();
			var $option = $(this);
			var $modal = $option.closest('.epofw-row-selection-modal');
			
			// Remove active class from all options and add to selected
			$modal.find('.epofw-row-option').removeClass('active');
			$option.addClass('active');
			
			// Store selected rows count
			var rowsCount = $option.data('rows');
			$modal.data('selected-rows', rowsCount);
		},

		createRows: function(e) {
			e.preventDefault();
			var $modal = $(this).closest('.epofw-row-selection-modal');
			var sectionId = $modal.data('section-id');
			var rowsCount = $modal.data('selected-rows');
			var isColumnsModal = $modal.data('is-columns-modal'); // Check if this is for adding columns to existing row
			var existingRowId = $modal.data('row-id'); // group_id of existing row

			if (!rowsCount) {
				return;
			}

			// If this is adding columns to an existing row group
			if (isColumnsModal && existingRowId) {
				AWS_ADMIN.addColumnsToExistingRow(sectionId, existingRowId, rowsCount);
				$modal.hide();
				$modal.remove();
				return;
			}

			// Find the section - try multiple selectors to ensure we find it
			var $section = $('.epofw-section[data-section-id="' + sectionId + '"]');
			if (0 === $section.length) {
				$section = $('[data-section-id="' + sectionId + '"]');
			}

			if (0 === $section.length) {
				$modal.hide();
				$modal.remove();
				return;
			}

			// Find or create section content container
			var $sectionContent = $section.find('.epofw-section-content');
			if (0 === $sectionContent.length) {
				// Create section content if it doesn't exist (shouldn't happen, but just in case)
				$sectionContent = $('<div class="epofw-section-content"></div>');
				// Insert after section header
				$section.find('.epofw-section-header').after($sectionContent);
			}

			// Create a container for row groups (separate from existing elements)
			var $rowsContainer = $section.find('.epofw-rows-container');
			if (0 === $rowsContainer.length) {
				$rowsContainer = $('<div class="epofw-rows-container"></div>');
				// Always append to section content
				$sectionContent.append($rowsContainer);
			}
			
			// Get existing row group count to continue numbering
			var existingGroupCount = $rowsContainer.find('.epofw-row-group').length;
			var groupNumber = existingGroupCount + 1;
			var groupId = 'group_' + Date.now() + '_' + groupNumber;
			
			// Create a row group container (Row = horizontal group containing columns)
			var groupClass = rowsCount === 1 ? 'epofw-single-group' : 'epofw-multi-group';
			var $rowGroup = $('<div class="epofw-row-group ' + groupClass + '" data-group-id="' + groupId + '" data-rows-count="' + rowsCount + '"></div>');
			
			// Add row group header with drag, edit, delete icons
			// Note: "Add Column" button is only shown for saved rows (added via PHP template)
			var $rowGroupHeader = $('<div class="epofw-row-group-header">' +
				'<div class="epofw-row-group-drag"><i class="dashicons dashicons-menu"></i></div>' +
				'<div class="epofw-row-group-edit" data-group-id="' + groupId + '" data-section-id="' + sectionId + '"><i class="dashicons dashicons-edit"></i></div>' +
				'<div class="epofw-row-group-title"><span>Row</span></div>' +
				'<div class="epofw-row-group-actions">' +
					'<button type="button" class="epofw-row-group-delete" data-group-id="' + groupId + '" title="Delete Row">' +
						'<i class="dashicons dashicons-no-alt"></i>' +
					'</button>' +
				'</div>' +
			'</div>');
			
			var $rowGroupContent = $('<div class="epofw-row-group-content"></div>');

			// Create columns inside the row group
			var template = $('#tmpl-epofw-row-container').html();
			if (!template) {
				$modal.hide();
				$modal.remove();
				return;
			}

			// Generate columns_id for the columns group
			var timestamp = Date.now();
			var columnsId = 'columns_' + timestamp + '_' + groupId;
			var columnsClass = rowsCount === 1 ? 'epofw-columns-single' : 'epofw-columns-multi';
			var layoutType = 'single';
			if (rowsCount === 2) {
				layoutType = 'two';
			} else if (rowsCount === 3) {
				layoutType = 'three';
			} else if (rowsCount === 4) {
				layoutType = 'four';
			}

			// Create the columns container with header
			var $columnsContainer = $('<div class="epofw-columns ' + columnsClass + '" data-columns-id="' + columnsId + '" data-columns-order="0" data-columns-count="' + rowsCount + '" data-layout-type="' + layoutType + '"></div>');

			// Add columns group header
			var $columnsHeader = $('<div class="epofw-columns-header">' +
				'<span class="epofw-columns-drag" title="Drag to reorder"><i class="dashicons dashicons-move"></i></span>' +
				'<div class="epofw-columns-title"><i class="dashicons dashicons-columns"></i><span>Columns (' + rowsCount + ')</span></div>' +
				'<div class="epofw-columns-actions">' +
					'<button type="button" class="epofw-columns-delete" data-columns-id="' + columnsId + '" title="Delete Columns"><i class="dashicons dashicons-no-alt"></i></button>' +
				'</div>' +
			'</div>');

			// Add hidden inputs for columns group
			var $columnsHiddenInputs = $(
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][section_id]" value="' + sectionId + '">' +
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][group_id]" value="' + groupId + '">' +
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][columns_id]" value="' + columnsId + '">' +
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][columns_order]" value="0">' +
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][layout_type]" value="' + layoutType + '">' +
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][columns_count]" value="' + rowsCount + '">'
			);

			// Create columns content wrapper
			var $columnsContent = $('<div class="epofw-columns-content"></div>');

			// Create individual columns
			for (var i = 1; i <= rowsCount; i++) {
				var columnNumber = i;
				var rowId = 'row_' + timestamp + '_' + columnNumber;
				var columnClass = rowsCount === 1 ? 'epofw-single-column' : 'epofw-multi-column';
				var rowHtml = template.replace(/\{\{ data\.row_id \}\}/g, rowId)
									.replace(/\{\{ data\.row_number \}\}/g, columnNumber)
									.replace(/\{\{ data\.section_id \}\}/g, sectionId)
									.replace(/\{\{ data\.group_id \}\}/g, groupId)
									.replace(/\{\{ data\.columns_id \}\}/g, columnsId)
									.replace(/\{\{ data\.columns_order \}\}/g, '0');

				var $column = $(rowHtml);
				$column.addClass(columnClass);
				$columnsContent.append($column);

				// Create column settings modal for this column
				AWS_ADMIN.createColumnModal(sectionId, groupId, rowId, columnsId, 0);
			}

			// Add the "Add Column" button container (hidden if already at 2 columns - maximum allowed)
			var hideAddBtn = rowsCount >= 2 ? ' style="display: none;"' : '';
			var $addColumnContainer = $('<div class="epofw-add-column-container"' + hideAddBtn + '>' +
				'<button type="button" class="epofw-add-column-btn" data-columns-id="' + columnsId + '" data-row-id="' + groupId + '" data-section-id="' + sectionId + '" title="Add Column">' +
					'<i class="dashicons dashicons-plus-alt2"></i>' +
				'</button>' +
			'</div>');
			$columnsContent.append($addColumnContainer);

			// Assemble the columns container
			$columnsContainer.append($columnsHeader);
			$columnsContainer.append($columnsHiddenInputs);
			$columnsContainer.append($columnsContent);

			// Add to row group content
			$rowGroupContent.append($columnsContainer);

			// Add "Add Columns" button at the bottom of row group content
			var $addColumnsContainer = $('<div class="epofw-add-columns-container">' +
				'<button type="button" class="epofw-add-columns-btn" data-row-id="' + groupId + '" data-section-id="' + sectionId + '" title="Add Columns">' +
					'<i class="dashicons dashicons-plus-alt2"></i>' +
					'<span>Add Columns</span>' +
				'</button>' +
			'</div>');
			$rowGroupContent.append($addColumnsContainer);

			// Append header and content to row group
			$rowGroup.append($rowGroupHeader).append($rowGroupContent);

			// Create row settings modal for this row group
			AWS_ADMIN.createRowModal(sectionId, groupId);

			// Ensure all "Add Element" buttons in the group are visible
			$rowGroup.find('.epofw-element-add').show();

			// Initialize sortable for the new columns container
			$columnsContainer.sortable({
				items: '> .epofw-columns-content > .epofw-column, > .epofw-columns-content > .epofw-row-container',
				handle: '.epofw-column-drag',
				placeholder: 'epofw-column-placeholder',
				tolerance: 'pointer',
				axis: 'x',
				containment: 'parent',
				start: function(event, ui) {
					ui.placeholder.height(ui.item.height());
					ui.item.addClass('dragging');
				},
				stop: function(event, ui) {
					ui.item.removeClass('dragging');
					// Update column numbers after reordering
					AWS_ADMIN.updateColumnNumbers($(this));
				}
			});

			$rowsContainer.append($rowGroup);

			// Close modal and remove from DOM
			$modal.hide();
			$modal.remove();
		},

		// Show columns selection modal (for adding columns container within a row)
		// Uses the same modal template as "Add Row" button
		showColumnsSelectionModal: function(e) {
			e.preventDefault();
			e.stopPropagation();

			var $btn = $(this);
			var rowId = $btn.data('row-id'); // This is the group_id
			var sectionId = $btn.data('section-id');

			// Use the same row selection modal template
			var template = $('#tmpl-epofw-row-selection-modal').html();
			if (!template) {
				return;
			}

			var modal = $(template);

			// Set modal ID and store data for columns context
			modal.attr('id', 'row-selection-modal-columns-' + rowId);
			modal.data('row-id', rowId);
			modal.data('section-id', sectionId);
			modal.data('is-columns-modal', true); // Flag to identify this is for adding columns to existing row

			// Add modal to body and show it
			$('body').append(modal);

			// Auto-select the first option (1 column) by default
			var $firstOption = modal.find('.epofw-row-option').first();
			$firstOption.addClass('active');
			var columnsCount = $firstOption.data('rows');
			modal.data('selected-rows', columnsCount);

			// Handle modal close/cancel
			modal.find('.epofw-modal-close, .epofw-modal-cancel, .epofw-modal-overlay').on('click', function(ev) {
				ev.preventDefault();
				ev.stopPropagation();
				modal.hide();
				modal.remove();
			});

			modal.show();
		},

		// Add columns container to an existing row group
		addColumnsToExistingRow: function(sectionId, groupId, columnsCount) {
			// Find the existing row group
			var $rowGroup = $('.epofw-row-group[data-group-id="' + groupId + '"]');
			if (!$rowGroup.length) {
				return;
			}

			var $rowGroupContent = $rowGroup.find('.epofw-row-group-content');
			var $addColumnsContainer = $rowGroupContent.find('.epofw-add-columns-container');

			// Get column template
			var template = $('#tmpl-epofw-row-container').html();
			if (!template) {
				return;
			}

			// Calculate columns order (0-based index of existing columns containers)
			var existingColumnsContainers = $rowGroupContent.find('.epofw-columns').length;
			var columnsOrder = existingColumnsContainers;

			// Generate unique columns ID
			var timestamp = Date.now();
			var columnsId = 'columns_' + timestamp + '_' + groupId;
			var columnsClass = columnsCount === 1 ? 'epofw-columns-single' : 'epofw-columns-multi';
			var layoutType = 'single';
			if (columnsCount === 2) {
				layoutType = 'two';
			} else if (columnsCount === 3) {
				layoutType = 'three';
			} else if (columnsCount === 4) {
				layoutType = 'four';
			}

			// Create the columns container with header
			var $columnsContainer = $('<div class="epofw-columns ' + columnsClass + '" data-columns-id="' + columnsId + '" data-columns-order="' + columnsOrder + '" data-columns-count="' + columnsCount + '" data-layout-type="' + layoutType + '"></div>');

			// Add columns group header
			var $columnsHeader = $('<div class="epofw-columns-header">' +
				'<span class="epofw-columns-drag" title="Drag to reorder"><i class="dashicons dashicons-move"></i></span>' +
				'<div class="epofw-columns-title"><i class="dashicons dashicons-columns"></i><span>Columns (' + columnsCount + ')</span></div>' +
				'<div class="epofw-columns-actions">' +
					'<button type="button" class="epofw-columns-delete" data-columns-id="' + columnsId + '" title="Delete Columns"><i class="dashicons dashicons-no-alt"></i></button>' +
				'</div>' +
			'</div>');

			// Add hidden inputs for columns group
			var $columnsHiddenInputs = $(
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][section_id]" value="' + sectionId + '">' +
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][group_id]" value="' + groupId + '">' +
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][columns_id]" value="' + columnsId + '">' +
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][columns_order]" value="' + columnsOrder + '">' +
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][layout_type]" value="' + layoutType + '">' +
				'<input type="hidden" name="epofw_columns_group[' + columnsId + '][columns_count]" value="' + columnsCount + '">'
			);

			// Create columns content wrapper
			var $columnsContent = $('<div class="epofw-columns-content"></div>');

			// Create individual columns
			for (var i = 1; i <= columnsCount; i++) {
				var columnNumber = i;
				var rowId = 'row_' + timestamp + '_' + columnNumber;
				var columnClass = columnsCount === 1 ? 'epofw-single-column' : 'epofw-multi-column';
				var rowHtml = template.replace(/\{\{ data\.row_id \}\}/g, rowId)
									.replace(/\{\{ data\.row_number \}\}/g, columnNumber)
									.replace(/\{\{ data\.section_id \}\}/g, sectionId)
									.replace(/\{\{ data\.group_id \}\}/g, groupId)
									.replace(/\{\{ data\.columns_id \}\}/g, columnsId)
									.replace(/\{\{ data\.columns_order \}\}/g, columnsOrder);

				var $column = $(rowHtml);
				$column.addClass(columnClass);
				$columnsContent.append($column);

				// Create column settings modal for this column
				AWS_ADMIN.createColumnModal(sectionId, groupId, rowId, columnsId, columnsOrder);
			}

			// Add the "Add Column" button container (hidden if already at 2 columns - maximum allowed)
			var hideAddBtn = columnsCount >= 2 ? ' style="display: none;"' : '';
			var $addColumnContainer = $('<div class="epofw-add-column-container"' + hideAddBtn + '>' +
				'<button type="button" class="epofw-add-column-btn" data-columns-id="' + columnsId + '" data-row-id="' + groupId + '" data-section-id="' + sectionId + '" title="Add Column">' +
					'<i class="dashicons dashicons-plus-alt2"></i>' +
				'</button>' +
			'</div>');
			$columnsContent.append($addColumnContainer);

			// Assemble the columns container
			$columnsContainer.append($columnsHeader);
			$columnsContainer.append($columnsHiddenInputs);
			$columnsContainer.append($columnsContent);

			// Insert before the "Add Columns" button container
			if ($addColumnsContainer.length) {
				$addColumnsContainer.before($columnsContainer);
			} else {
				$rowGroupContent.append($columnsContainer);
			}

			// Initialize sortable for the new columns container
			$columnsContainer.sortable({
				items: '> .epofw-columns-content > .epofw-column, > .epofw-columns-content > .epofw-row-container',
				handle: '.epofw-column-drag',
				placeholder: 'epofw-column-placeholder',
				tolerance: 'pointer',
				axis: 'x',
				containment: 'parent',
				start: function(event, ui) {
					ui.placeholder.height(ui.item.height());
					ui.item.addClass('dragging');
				},
				stop: function(event, ui) {
					ui.item.removeClass('dragging');
					// Update column numbers after reordering
					AWS_ADMIN.updateColumnNumbers($(this));
				}
			});

			AWS_ADMIN.toastMessage('success', 'Columns added successfully');
		},

		updateRowsContainerLayout: function($rowsContainer) {
			// Remove all layout classes
			$rowsContainer.removeClass('epofw-single-row-layout epofw-multi-row-layout epofw-mixed-layout');

			// Determine layout based on row configurations
			var singleRows = $rowsContainer.find('.epofw-single-row').length;
			var multiRows = $rowsContainer.find('.epofw-multi-row').length;

			if (singleRows > 0 && multiRows > 0) {
				// Mixed layout - some single, some multi
				$rowsContainer.addClass('epofw-mixed-layout');
			} else if (singleRows > 0) {
				// All single rows - stack vertically
				$rowsContainer.addClass('epofw-single-row-layout');
			} else {
				// All multi rows - display horizontally
				$rowsContainer.addClass('epofw-multi-row-layout');
			}
		},

		/**
		 * Update column numbers after drag-and-drop reordering
		 * Updates: data-row-number attribute, hidden input value, and column title text
		 * @param {jQuery} $columnsContainer - The columns container element
		 */
		updateColumnNumbers: function($columnsContainer) {
			var $columns = $columnsContainer.find('.epofw-columns-content > .epofw-column, .epofw-columns-content > .epofw-row-container');

			$columns.each(function(index) {
				var $column = $(this);
				var newNumber = index + 1; // 1-based index
				var rowId = $column.data('row-id');

				// Update data attribute
				$column.attr('data-row-number', newNumber);

				// Update hidden input value - create if doesn't exist
				var $rowNumberInput = $column.find('.epofw-column-row-number');

				if ($rowNumberInput.length) {
					$rowNumberInput.val(newNumber);
				} else if (rowId) {
					// Create the hidden input if it doesn't exist (for backward compatibility)
					var hiddenInput = $('<input type="hidden" name="epofw_column[' + rowId + '][row_number]" value="' + newNumber + '" class="epofw-column-row-number">');
					$column.prepend(hiddenInput);
				}

				// Update column title text (e.g., "Column 1" -> "Column 2")
				var $titleSpan = $column.find('.epofw-column-title span, .epofw-row-title span').first();
				if ($titleSpan.length) {
					var titleText = $titleSpan.text();
					// Replace the number at the end of "Column X" with the new number
					var newTitle = titleText.replace(/\d+$/, newNumber);
					$titleSpan.text(newTitle);
				}
			});
		},

		deleteRow: function(e) {
			e.preventDefault();
			if (confirm( epofw_var.strings.delete_column_confirm )) {
				// Handle both old (.epofw-row-container) and new (.epofw-column) class names
				var $column = $(this).closest('.epofw-column, .epofw-row-container');
				var $columnsContainer = $column.closest('.epofw-columns');
				var $row = $column.closest('.epofw-row, .epofw-row-group');
				var $section = $column.closest('.epofw-section');
				var $rowsContainer = $section.find('.epofw-rows-container');

				// Check if column is in a columns container
				if ($columnsContainer.length) {
					// If this is the only column in the columns container, delete the entire columns container
					if ($columnsContainer.find('.epofw-column, .epofw-row-container').length === 1) {
						$columnsContainer.remove();
					} else {
						// Just delete this column
						$column.remove();
						// Update columns count and layout_type (max 2 columns)
						var remainingColumns = $columnsContainer.find('.epofw-column, .epofw-row-container').length;
						var layoutType = 'single';
						if (remainingColumns === 2) {
							layoutType = 'two';
						}

						$columnsContainer.attr('data-columns-count', remainingColumns);
						$columnsContainer.attr('data-layout-type', layoutType);
						$columnsContainer.find('input[name*="[columns_count]"]').val(remainingColumns);
						$columnsContainer.find('input[name*="[layout_type]"]').val(layoutType);
						$columnsContainer.removeClass('epofw-columns-single epofw-columns-multi');
						$columnsContainer.addClass(remainingColumns === 1 ? 'epofw-columns-single' : 'epofw-columns-multi');

						// Show "Add Column" button container if remaining columns < 2 (maximum allowed)
						if (remainingColumns < 2) {
							$columnsContainer.find('.epofw-add-column-container').show();
						}
					}
				} else {
					// Legacy: If this is the only row in the group, delete the entire group
					if ($row.find('.epofw-row-container').length === 1) {
						$row.remove();
					} else {
						// If there are multiple rows in the group, just delete this row
						$column.remove();
						// Update row group class based on remaining columns
						AWS_ADMIN.updateRowGroupClass($row);
					}
				}

				// If no rows or columns left, remove the rows container and show the original "Add Element" button
				if ($rowsContainer.length && $rowsContainer.find('.epofw-row, .epofw-row-group').length === 0) {
					$rowsContainer.remove();
					$section.find('.epofw-element-add').show();
				}
			}
		},

		// Add single column to existing columns container
		addColumnToRowGroup: function(e) {
			e.preventDefault();
			e.stopPropagation();

			var $btn = $(this);
			var columnsId = $btn.data('columns-id');
			var rowId = $btn.data('row-id');
			var sectionId = $btn.data('section-id');

			var $columnsContainer = $('.epofw-columns[data-columns-id="' + columnsId + '"]');
			if (!$columnsContainer.length) {
				return;
			}

			// Get current column count (check both old and new class names)
			var currentCount = $columnsContainer.find('.epofw-column, .epofw-row-container').not('.epofw-add-column-btn, .epofw-add-column-container').length;
			if (currentCount >= 2) {
				AWS_ADMIN.toastMessage('warning', 'Maximum 2 columns allowed');
				$btn.closest('.epofw-add-column-container').hide();
				return;
			}

			// Get column template
			var template = $('#tmpl-epofw-column').html();
			if (!template) {
				template = $('#tmpl-epofw-row-container').html();
			}
			if (!template) {
				return;
			}

			var columnsOrder = $columnsContainer.data('columns-order') || 0;
			var columnNumber = currentCount + 1;
			var timestamp = Date.now();
			var columnId = 'row_' + timestamp + '_' + columnNumber;
			var newColumnsCount = currentCount + 1;

			// Update layout_type based on new column count (max 2 columns)
			var layoutType = 'single';
			if (newColumnsCount === 2) {
				layoutType = 'two';
			}

			var columnHtml = template.replace(/\{\{ data\.column_id \}\}/g, columnId)
								.replace(/\{\{ data\.row_id \}\}/g, columnId)
								.replace(/\{\{ data\.row_number \}\}/g, columnNumber)
								.replace(/\{\{ data\.column_number \}\}/g, columnNumber)
								.replace(/\{\{ data\.section_id \}\}/g, sectionId)
								.replace(/\{\{ data\.group_id \}\}/g, rowId)
								.replace(/\{\{ data\.columns_id \}\}/g, columnsId)
								.replace(/\{\{ data\.columns_order \}\}/g, columnsOrder);

			var $column = $(columnHtml);
			$column.attr('data-columns-id', columnsId);
			$column.attr('data-columns-order', columnsOrder);

			// Update columns container data attributes and hidden inputs
			$columnsContainer.attr('data-columns-count', newColumnsCount);
			$columnsContainer.attr('data-layout-type', layoutType);
			$columnsContainer.find('input[name*="[columns_count]"]').val(newColumnsCount);
			$columnsContainer.find('input[name*="[layout_type]"]').val(layoutType);
			$column.addClass('epofw-multi-column');
			$column.removeClass('epofw-single-column epofw-single-row epofw-multi-row');

			// Insert before the add button container (not inside it)
			$btn.closest('.epofw-add-column-container').before($column);

			// Update columns container class
			$columnsContainer.removeClass('epofw-columns-single').addClass('epofw-columns-multi');

			// Update all columns in this container to multi
			$columnsContainer.find('.epofw-column').removeClass('epofw-single-column').addClass('epofw-multi-column');

			// Create column settings modal
			AWS_ADMIN.createColumnModal(sectionId, rowId, columnId, columnsId, columnsOrder);

			// Hide the "Add Column" button container if we've reached 2 columns (maximum allowed)
			if (newColumnsCount >= 2) {
				$btn.closest('.epofw-add-column-container').hide();
			}

			// Refresh sortable for the columns container
			AWS_ADMIN.refreshSortable();

			AWS_ADMIN.toastMessage('success', 'Column added');
		},

		// Update row group class based on number of columns
		updateRowGroupClass: function($rowGroup) {
			var columnCount = $rowGroup.find('.epofw-row-container').length;

			// Update group class
			$rowGroup.removeClass('epofw-single-group epofw-multi-group');
			if (columnCount === 1) {
				$rowGroup.addClass('epofw-single-group');
			} else {
				$rowGroup.addClass('epofw-multi-group');
			}

			// Update individual column classes
			$rowGroup.find('.epofw-row-container').each(function() {
				$(this).removeClass('epofw-single-row epofw-multi-row');
				if (columnCount === 1) {
					$(this).addClass('epofw-single-row');
				} else {
					$(this).addClass('epofw-multi-row');
				}
			});

			// Update data attribute
			$rowGroup.attr('data-rows-count', columnCount);
		},

		rowGroupEdit: function(e) {
			e.preventDefault();
			e.stopPropagation();
			
			var groupId = $(this).data('group-id');
			var sectionId = $(this).data('section-id');
			var $rowModal = $('#row-settings-modal-' + groupId);
			
			if (!$rowModal.length) {
				return;
			}
			
			// Check if modal content is already loaded
			var hasContent = $rowModal.find('.epofw-modal-content-wrapper').children().length > 0;
			
			if (!hasContent) {
				// Load content via AJAX
				AWS_ADMIN.loadRowSettingsContent($rowModal, sectionId, groupId);
			} else {
				// Content already loaded, just show
				// Initialize real-time validation
				AWS_ADMIN.initRealTimeValidation($rowModal);
				
				// Initialize color pickers in modal
				$rowModal.find('.epofw_colorpicker').each(function() {
					if (!$(this).hasClass('wp-color-picker')) {
						$(this).wpColorPicker();
					}
				});
				
				// Initialize toggle switches in this modal
				AWS_ADMIN.initModalToggles($rowModal);
				
				// Show the modal
				$rowModal.show();
			}
		},

		// Load row settings form content via AJAX
		loadRowSettingsContent: function($modal, sectionId, groupId) {
			// Show loader
			AWS_ADMIN.showModalLoader( $modal, 'loading_settings' );
			$modal.show();

			jQuery.ajax({
				type: 'post',
				url: epofw_var.ajaxurl,
				data: {
					action: 'epofw_get_row_settings',
					section_id: sectionId,
					group_id: groupId,
					nonce: epofw_var.element_add_nonce
				},
				success: function(response) {
					if (response.success) {
						$modal.find('.epofw-modal-content-wrapper').html(response.data.content);
						
						// Initialize after content loaded
						setTimeout(function() {
							$modal.find('.epofw_colorpicker').each(function() {
								if (!$(this).hasClass('wp-color-picker')) {
									$(this).wpColorPicker();
								}
							});
							
							AWS_ADMIN.initModalToggles($modal);
							$modal.show();
						}, 50);
					} else {
						// Show modal even if AJAX fails
						$modal.show();
					}
				},
				error: function() {
					$modal.show();
				}
			});
		},

		rowGroupDelete: function(e) {
			e.preventDefault();
			e.stopPropagation();

			if (confirm( epofw_var.strings.delete_row_confirm )) {
				var groupId = $(this).data('group-id');
				var $rowGroup = $('.epofw-row-group[data-group-id="' + groupId + '"]');

				if ($rowGroup.length) {
					// Delete the entire row group (which includes all columns)
					$rowGroup.remove();

					// Check if there are no more row groups in the section
					var $section = $rowGroup.closest('.epofw-section');
					var $rowsContainer = $section.find('.epofw-rows-container');
					if ($rowsContainer.length && $rowsContainer.find('.epofw-row-group').length === 0) {
						$rowsContainer.remove();
						$section.find('.epofw-element-add').show();
					}
				}
			}
		},

		deleteColumnsGroup: function(e) {
			e.preventDefault();
			e.stopPropagation();

			var $btn = $(this);
			var $columnsGroup = $btn.closest('.epofw-columns');

			if (!$columnsGroup.length) {
				return;
			}

			// Count fields in this columns group
			var fieldCount = $columnsGroup.find('.epofw-element').length;
			var confirmMsg = epofw_var.strings.delete_columns_confirm || 'Are you sure you want to delete this columns group?';
			if (fieldCount > 0) {
				confirmMsg = (epofw_var.strings.delete_columns_with_fields || 'This columns group contains %d field(s). Are you sure you want to delete it?').replace('%d', fieldCount);
			}

			if (confirm(confirmMsg)) {
				$columnsGroup.remove();
				AWS_ADMIN.toastMessage('success', epofw_var.strings.columns_deleted || 'Columns deleted successfully');
			}
		},

		saveRowSettings: function(e) {
			e.preventDefault();
			e.stopPropagation();
			
			var $modal = $(this).closest('.epofw-section-modal');
			var modalId = $modal.attr('id');
			var groupId = modalId.replace('row-settings-modal-', '');
			
			// Find the row group in the builder
			var $rowGroup = $('[data-group-id="' + groupId + '"]');
			if ($rowGroup.length) {
				// Remove any existing row group hidden fields
				$rowGroup.find('> input[type="hidden"][name*="[row_group_settings]"]').remove();
				
				// Get all form fields from the modal
				var $formFields = $modal.find('input, select, textarea').not(':button');
				
				// Clone form fields as hidden inputs and prepend to row group
				$formFields.each(function() {
					var $field = $(this);
					var fieldName = $field.attr('name');
					var fieldValue = '';
					
					if (!fieldName) {
						return; // Skip fields without names
					}
					
					// Get field value based on type
					if ($field.is(':checkbox')) {
						fieldValue = $field.is(':checked') ? $field.val() : '';
					} else if ($field.is(':radio')) {
						if ($field.is(':checked')) {
							fieldValue = $field.val();
						} else {
							return; // Skip unchecked radio buttons
						}
					} else {
						fieldValue = $field.val();
					}
					
					// Create hidden input with the same name and value
					var $hiddenInput = $('<input type="hidden">');
					$hiddenInput.attr('name', fieldName);
					$hiddenInput.val(fieldValue);
					
					// Prepend to row group
					$rowGroup.prepend($hiddenInput);
				});
			}
			
			// Close the modal
			if ($modal.length) {
				$modal.hide();
			}
		},

		columnEdit: function(e) {
			e.preventDefault();
			e.stopPropagation();
			
			var rowId = $(this).data('row-id');
			var sectionId = $(this).data('section-id');
			var groupId = $(this).data('group-id');
			
			var $columnModal = $('#column-settings-modal-' + rowId);
			
			// If modal doesn't exist, create it via AJAX
			if (!$columnModal.length) {
				AWS_ADMIN.loadColumnSettingsModal(sectionId, groupId, rowId);
				return;
			}
			
			// Check if modal content is already loaded
			var hasContent = $columnModal.find('.epofw-modal-content-wrapper').children().length > 0;
			
			if (!hasContent) {
				// Load content via AJAX
				AWS_ADMIN.loadColumnContentOnly($columnModal, sectionId, groupId, rowId);
			} else {
				// Content already loaded, just show
				// Initialize real-time validation
				AWS_ADMIN.initRealTimeValidation($columnModal);
				
				// Initialize color pickers in modal
				$columnModal.find('.epofw_colorpicker').each(function() {
					if (!$(this).hasClass('wp-color-picker')) {
						$(this).wpColorPicker();
					}
				});
				
				// Initialize toggle switches in this modal
				AWS_ADMIN.initModalToggles($columnModal);
				
				// Show the modal
				$columnModal.show();
			}
		},

		// Load column content into existing modal
		loadColumnContentOnly: function($modal, sectionId, groupId, rowId) {
			jQuery.ajax({
				type: 'post',
				url: epofw_var.ajaxurl,
				data: {
					action: 'epofw_get_column_settings',
					section_id: sectionId,
					group_id: groupId,
					row_id: rowId,
					nonce: epofw_var.element_add_nonce
				},
				success: function(response) {
					if (response.success) {
						var $wrapper = $modal.find('.epofw-modal-content-wrapper');
						$wrapper.html(response.data.content);
						
						// Initialize color pickers
						setTimeout(function() {
							$modal.find('.epofw_colorpicker').each(function() {
								if (!$(this).hasClass('wp-color-picker')) {
									$(this).wpColorPicker();
								}
							});
							
							// Initialize toggles
							AWS_ADMIN.initModalToggles($modal);
							
							// Show modal
							$modal.show();
						}, 50);
					} else {
						// If AJAX fails, just show empty modal
						$modal.show();
					}
				},
				error: function() {
					// If AJAX fails, just show empty modal
					$modal.show();
				}
			});
		},

		// Create column modal from template
		createColumnModal: function(sectionId, groupId, rowId) {
			var template = $('#tmpl-epofw-column-settings-modal').html();
			if (!template) {
				return;
			}
			
			var modalHtml = template.replace(/\{\{ data\.row_id \}\}/g, rowId)
									.replace(/\{\{ data\.group_id \}\}/g, groupId)
									.replace(/\{\{ data\.section_id \}\}/g, sectionId);
			
			$('body').append(modalHtml);
		},

		// Load column settings modal content via AJAX
		loadColumnSettingsModal: function(sectionId, groupId, rowId) {
			// First create the modal
			AWS_ADMIN.createColumnModal(sectionId, groupId, rowId);

			var $modal = $('#column-settings-modal-' + rowId);

			// Show loader
			AWS_ADMIN.showModalLoader( $modal, 'loading_settings' );
			$modal.show();

			// Load content via AJAX
			jQuery.ajax({
				type: 'post',
				url: epofw_var.ajaxurl,
				data: {
					action: 'epofw_get_column_settings',
					section_id: sectionId,
					group_id: groupId,
					row_id: rowId,
					nonce: epofw_var.element_add_nonce
				},
				success: function(response) {
					if (response.success) {
						$modal.find('.epofw-modal-content-wrapper').html(response.data.content);
						
						// Initialize color pickers
						setTimeout(function() {
							$modal.find('.epofw_colorpicker').each(function() {
								if (!$(this).hasClass('wp-color-picker')) {
									$(this).wpColorPicker();
								}
							});
							
							// Initialize toggles
							AWS_ADMIN.initModalToggles($modal);
							
							// Show modal
							$modal.show();
						}, 50);
					} else {
						// If AJAX fails, just show empty modal
						$modal.show();
					}
				},
				error: function() {
					// If AJAX fails, just show empty modal
					$modal.show();
				}
			});
		},

		saveColumnSettings: function(e) {
			e.preventDefault();
			e.stopPropagation();
			
			var $modal = $(this).closest('.epofw-section-modal');
			var modalId = $modal.attr('id');
			var rowId = modalId.replace('column-settings-modal-', '');
			
			// Find the row container in the builder
			var $rowContainer = $('[data-row-id="' + rowId + '"]');
			if ($rowContainer.length) {
				// Remove any existing column hidden fields
				$rowContainer.find('> input[type="hidden"][name*="[column_settings]"]').remove();
				
				// Get all form fields from the modal
				var $formFields = $modal.find('input, select, textarea').not(':button');
				
				// Clone form fields as hidden inputs and prepend to row container
				$formFields.each(function() {
					var $field = $(this);
					var fieldName = $field.attr('name');
					var fieldValue = '';
					
					if (!fieldName) {
						return; // Skip fields without names
					}
					
					// Get field value based on type
					if ($field.is(':checkbox')) {
						fieldValue = $field.is(':checked') ? $field.val() : '';
					} else if ($field.is(':radio')) {
						if ($field.is(':checked')) {
							fieldValue = $field.val();
						} else {
							return; // Skip unchecked radio buttons
						}
					} else {
						fieldValue = $field.val();
					}
					
					// Create hidden input with the same name and value
					var $hiddenInput = $('<input type="hidden">');
					$hiddenInput.attr('name', fieldName);
					$hiddenInput.val(fieldValue);
					
					// Prepend to row container
					$rowContainer.prepend($hiddenInput);
				});
			}
			
			// Close the modal
			if ($modal.length) {
				$modal.hide();
			}
		}
	};
	$(
		function () {
			var epofwHiddenValue = $( '.epofw_hidden_value' );
			if ( epofwHiddenValue.length ) {
				epofwHiddenValue.parent().parent().hide();
			}
			var classDatePicker = $( '.epofw_condition_data_class_date_picker' );
			if ( classDatePicker.length ) {
				classDatePicker.datepicker( { dateFormat : 'dd-mm-yy' } );
			}

			// Initialize drag and drop for sections ONLY (not rows)
			$( '.epofw-sections-container' ).sortable(
				{
					handle               : '.epofw-section-drag',
					items                : '> .epofw-section',
					placeholder          : 'epofw-section-placeholder',
					forcePlaceholderSize : true,
					axis                 : 'y',
					opacity              : 0.8,
					start                : function ( event, ui ) {
						void event; // Required by jQuery UI but unused
						// Store the initial height of the item being dragged.
						ui.placeholder.height( ui.item.height() );
						// Add a class to indicate dragging state.
						ui.item.addClass( 'dragging' );
					},
					stop                 : function ( event, ui ) {
						void event; // Required by jQuery UI but unused
						// Remove the dragging state class.
						ui.item.removeClass( 'dragging' );
						// Don't update section numbers - keep original titles
					},
					update               : function () {
						// Update section_order hidden inputs after drag-drop
						$('.epofw-section').each(function(index) {
							var $section = $(this);
							var sectionId = $section.data('section-id');
							var newOrder = index + 1; // 1-based ordering
							$section.find('input[name="epofw_section[' + sectionId + '][order]"]').val(newOrder);
						});
					}
				}
			);
			
			// Disable drag for row groups - only sections can be dragged
			// Row groups should NOT be sortable/draggable

			// Initialize drag and drop for elements within sections
			$( '.epofw-elements-container' ).sortable(
				{
					handle               : '.epofw-element-drag',
					items                : '> .epofw-element',
					placeholder          : 'epofw-element-placeholder',
					forcePlaceholderSize : true,
					axis                 : 'y',
					opacity              : 0.8,
					connectWith          : '.epofw-elements-container',
					start                : function ( event, ui ) {
						void event; // Required by jQuery UI but unused
						// Store the initial height of the item being dragged.
						ui.placeholder.height( ui.item.height() );
						// Add a class to indicate dragging state.
						ui.item.addClass( 'dragging' );
					},
					stop                 : function ( event, ui ) {
						void event; // Required by jQuery UI but unused
						// Remove the dragging state class.
						ui.item.removeClass( 'dragging' );
					}
				}
			);

			$( '.epofw-options-container' ).sortable(
				{
					handle               : '.heading_nu_move',
					items                : '> .epofw-option-row',
					placeholder          : 'sortable-placeholder',
					forcePlaceholderSize : true,
					axis                 : 'y',
					opacity              : 0.8,
					start                : function ( event, ui ) {
						void event; // Required by jQuery UI but unused
						// Store the initial height of the item being dragged.
						ui.placeholder.height( ui.item.height() );
						// Add a class to indicate dragging state.
						ui.item.addClass( 'dragging' );
					},
					stop                 : function ( event, ui ) {
						void event; // Required by jQuery UI but unused
						// Remove the dragging state class.
						ui.item.removeClass( 'dragging' );
					}
				}
			);
			var epofwColorpicker = $( '.epofw_colorpicker' );
			if ( epofwColorpicker.length ) {
				epofwColorpicker.wpColorPicker();
			}
			if ( $( '#epofw_custom_css' ).length > 0 ) {
				var content_mode = $( '#epofw_custom_css' ).attr( 'data-mode' );
				var options      = {
					lineNumbers       : true,
					mode              : content_mode,
					matchBrackets     : true,
					autoCloseBrackets : true,
				};
				CodeMirror.fromTextArea( document.getElementById( 'epofw_custom_css' ), options );
			}

			// Initialize the notice visibility on page load.
			$( '.epofw_addon_price_type' ).each(
				function () {
					handlePriceTypeNotice( this );
				}
			);

			// Handle price type changes for custom formula info - already handled by AWS_ADMIN.handleAddonPriceTypeChange

			// Initialize show/hide functionality for all toggles on page load
			$( '.epofw-has-sub' ).each(
				function () {
					var $checkbox = $( this );
					var nextFieldId = $checkbox.attr( 'data-nextfe' );
					var epofw_addon_price_type = '';
					if ( nextFieldId ) {
						var $nextField = $( '#' + nextFieldId );
						if ( $nextField.length ) {
							// Show if checked, hide if not checked
							if ( $checkbox.is( ':checked' ) ) {
								$nextField.show();
								
								// If this is the pricing section, ensure custom formula info is hidden
								if ( nextFieldId === 'price_extra' ) {
									var $customFormulaInfo = $nextField.find( '.epofw-custom-price-formula-info' );
									if ( $customFormulaInfo.length ) {
										epofw_addon_price_type = $nextField.find( '.epofw_addon_price_type' ).val();
										if ( 'cpf' === epofw_addon_price_type ) {
											$customFormulaInfo.addClass( 'active' ).removeClass( 'show' ).removeAttr( 'style' );
										} else {
											$customFormulaInfo.removeClass( 'active show' ).attr( 'style', 'display: none;' );
										}
									}
								}
							} else {
								// Hide if not checked
								$nextField.hide();
							}
						}
					}
				}
			);

			// Initialize toggle switch functionality
			AWS_ADMIN.initToggleSwitches();
			
			// Initialize native color pickers for proper display and default colors
			AWS_ADMIN.initColorPickers();

			AWS_ADMIN.init();

			// Initialize toast notifications from PHP
			AWS_ADMIN.initToastNotifications();

			/**
			 * Trigger after all EPOFW admin initialization is complete.
			 *
			 * Use this trigger to initialize custom modules that depend on EPOFW admin.
			 *
			 * @since 4.4.5
			 * @event epofw_admin_init_complete
			 */
			$( document.body ).trigger( 'epofw_admin_init_complete' );
		}
	);
} )( jQuery );
