/**
 * Epofw front js.
 *
 * @version 1.0.0
 * @package Extra_Product_Options_For_WooCommerce
 */

( function ( $ ) {
	'use strict';
	var currencySymbol    = epofw_front_var.currency;
	var decimalSeparator  = epofw_front_var.decimal_separator;
	var thousandSeparator = epofw_front_var.thousand_separator;
	var decimals          = epofw_front_var.decimals;
	var position          = epofw_front_var.position;

	var AWS_Front = {
		init: function () {
			/* Start New */
			$( 'form.cart' ).submit(
				function () {
					var epofwPass = AWSF.checkValidationForEachFields();
					if ( jQuery.inArray( false, epofwPass ) !== -1 ) {
							return false;
					}
				}
			);
			/* End New */
			$( document ).click(
				function ( e ) {
					if ( ! $( e.target ).is( '.epofw_dft_colorpicker' ) ) {
							$( '.epofw_dft_colorpicker' ).iris( 'hide' );
					}
				}
			);
			$( '.epofw_dft_colorpicker' ).click(
				function () {
					$( '.epofw_dft_colorpicker' ).iris( 'hide' );
					$( this ).iris( 'show' );
					return false;
				}
			);
			if ( $( '.epofw_dft_multiselect' ).length ) {
				$( '.epofw_dft_multiselect' ).select2();
			}
			if ( $( '.epofw_dft_datepicker' ).length ) {
				$( '.epofw_dft_datepicker' ).each(
					function () {
						var fieldID    = $( this ).attr( 'id' );
						var element    = $( this ).closest( '.epofw_tr_se' ).attr( 'id' );
						var docElemnt  = document.getElementById( element );
						var tdElement  = docElemnt ? ( docElemnt.querySelector( 'td.value' ) || docElemnt.querySelector( '.value' ) ) : null;
						var errorColor = '#ff0000';

						var $this                          = $( this );
						var getUniqueDivId                 = $this.closest( '.epofw_addon_html' ).data( 'uqd-attr' );
						var fieldPrice                     = AWSF.epofwFieldsMatchParameter( $this, 'addon_price', '' );
						var fieldType                      = AWSF.epofwFieldsMatchParameter( $this, 'data_inp_type', '' );
						var inputfieldName                 = $( this ).attr( 'name' );
						var inputfieldNameReplaceWithValue = inputfieldName.replace( '[value]', '' );
						var inputfieldNameReplaced         = inputfieldNameReplaceWithValue.replace( '[]', '' );
						var labelName                      = $( this ).attr( 'data-label-name' );
						$( '#' + fieldID ).datepicker(
							{
								dateFormat: 'dd-mm-yy',
								onSelect: function ( dateText ) {
									if ( $( '#' + element + ' .epofw_error' ).length > 0 ) {
										$( '#' + element + ' .epofw_error' ).remove();
									}
									if ( dateText !== '' && ! AWS_Front.isValidDate( dateText ) ) {
										// Clear the input or display an error message.
										$( this ).val( '' );
										var errorElement         = document.createElement( 'p' );
										errorElement.className   = 'epofw_error';
										errorElement.style.color = errorColor;
										var errorMessage         = document.createTextNode( epofw_front_var.datepicker_select_validation );
										errorElement.appendChild( errorMessage );
										tdElement.append( errorElement );
									} else {
										var trFieldName = labelName + ' - ' + dateText;
										var checkTr     = $( 'tr#tr_' + inputfieldNameReplaced ).length;
										if ( checkTr === 0 ) {
											var firstTr = AWSF.createTr( dateText, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
											$( '#addon_total #addon_subtotal' ).before( firstTr );
										} else {
											AWSF.addTrInAddonDetails( dateText, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
										}
										AWSF.calculateAddonPrice();
									}
								}
							}
						).on(
							'change',
							function () {
								if ( $( '#' + element + ' .epofw_error' ).length > 0 ) {
									$( '#' + element + ' .epofw_error' ).remove();
								}
								var dateText = $( this ).val();
								if ( dateText !== '' && ! AWS_Front.isValidDate( dateText ) ) {
									var errorElement         = document.createElement( 'p' );
									errorElement.className   = 'epofw_error';
									errorElement.style.color = errorColor;
									var errorMessage         = document.createTextNode( epofw_front_var.datepicker_change_validation );
									errorElement.appendChild( errorMessage );
									tdElement.append( errorElement );
									$( this ).val( '' ); // Clear the input field if an invalid date is entered.
								} else {
									var trFieldName = labelName + ' - ' + dateText;
									var checkTr     = $( 'tr#tr_' + inputfieldNameReplaced ).length;
									if ( checkTr === 0 ) {
										var firstTr = AWSF.createTr( dateText, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
										$( '#addon_total #addon_subtotal' ).before( firstTr );
									} else {
										AWSF.addTrInAddonDetails( dateText, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
									}
									AWSF.calculateAddonPrice();
								}
							}
						);
					}
				);
			}
			if ( $( '.epofw_dft_timepicker' ).length ) {
				$( '.epofw_dft_timepicker' ).each(
					function () {
						var fieldID    = $( this ).attr( 'id' );
						var element    = $( this ).closest( '.epofw_tr_se' ).attr( 'id' );
						var docElemnt  = document.getElementById( element );
						var tdElement  = docElemnt ? ( docElemnt.querySelector( 'td.value' ) || docElemnt.querySelector( '.value' ) ) : null;
						var errorColor = '#ff0000';
						$( '#' + fieldID ).timepicker(
							{
								timeFormat: 'hh:mm:ss TT',
								onSelect: function ( timeText ) {
									if ( $( '#' + element + ' .epofw_error' ).length > 0 ) {
										$( '#' + element + ' .epofw_error' ).remove();
									}
									if ( timeText !== '' && ! AWS_Front.isValidTime( timeText ) ) {
										// Clear the input or display an error message.
										$( this ).val( '' );
										var errorElement         = document.createElement( 'p' );
										errorElement.className   = 'epofw_error';
										errorElement.style.color = errorColor;
										var errorMessage         = document.createTextNode( epofw_front_var.timepicker_select_validation );
										errorElement.appendChild( errorMessage );
										tdElement.append( errorElement );
									}
								}
							}
						).on(
							'change',
							function () {
								if ( $( '#' + element + ' .epofw_error' ).length > 0 ) {
									$( '#' + element + ' .epofw_error' ).remove();
								}
								var timeText = $( this ).val();
								if ( timeText !== '' && ! AWS_Front.isValidTime( timeText ) ) {
									var errorElement         = document.createElement( 'p' );
									errorElement.className   = 'epofw_error';
									errorElement.style.color = errorColor;
									var errorMessage         = document.createTextNode( epofw_front_var.timepicker_change_validation );
									errorElement.appendChild( errorMessage );
									tdElement.append( errorElement );
									$( this ).val( '' ); // Clear the input field if an invalid date is entered.
								}
							}
						);
					}
				);
			}
			// Initialize slider fields.
			if ( $( '.epofw-slider-control' ).length && $.fn.slider ) {
				$( '.epofw-slider-control:not(.slider-initialized)' ).each(
					function () {
						var $this = $( this );

						// Skip if already initialized.
						if ( $this.hasClass( 'slider-initialized' ) ) {
							return;
						}

						// Find the hidden input and value display within the same container.
						var $container = $this.closest( '.epofw-slider-container' );
						if ( ! $container.length ) {
							$container = $this.parent();
						}
						var $hiddenInput = $container.find( 'input[type="hidden"]' );
						var $valueDisplay = $container.find( '.epofw-slider-value' );

						// Get slider parameters from data attributes.
						var min = parseFloat( $this.data( 'min' ) ) || 0;
						var max = parseFloat( $this.data( 'max' ) ) || 100;
						var step = parseFloat( $this.data( 'step' ) ) || 1;
						var defaultVal = parseFloat( $this.data( 'default' ) ) || min;

						// Clamp default value to valid range.
						if ( defaultVal < min ) {
							defaultVal = min;
						}
						if ( defaultVal > max ) {
							defaultVal = max;
						}

						// Ensure the slider div has a width for proper rendering.
						if ( ! $this.width() ) {
							$this.css( 'width', '100%' );
						}

						try {
							// Initialize the jQuery UI slider.
							$this.slider( {
								min: min,
								max: max,
								step: step,
								value: defaultVal,
								range: 'min',
								create: function () {
									// Set initial value in hidden input and display.
									if ( $hiddenInput.length ) {
										$hiddenInput.val( defaultVal );
									}
									if ( $valueDisplay.length ) {
										$valueDisplay.text( defaultVal );
									}
									$this.addClass( 'slider-initialized' );

									// Trigger change to calculate initial price.
									if ( $hiddenInput.length ) {
										$hiddenInput.trigger( 'change' );
									}
								},
								slide: function ( event, ui ) {
									// Update hidden input and display during slide.
									if ( $hiddenInput.length ) {
										$hiddenInput.val( ui.value );
									}
									if ( $valueDisplay.length ) {
										$valueDisplay.text( ui.value );
									}
								},
								change: function ( event, ui ) {
									// Update hidden input and display on change.
									if ( $hiddenInput.length ) {
										$hiddenInput.val( ui.value ).trigger( 'change' );
									}
									if ( $valueDisplay.length ) {
										$valueDisplay.text( ui.value );
									}
								}
							} );
						} catch ( e ) {
							// Slider initialization failed - log error.
							if ( typeof console !== 'undefined' ) {
								console.error( 'Slider initialization failed:', e );
							}
						}
					}
				);
			}
			if ( $( '.epofw_dft_colorpicker' ).length ) {
				$( '.epofw_dft_colorpicker' ).each(
					function () {
						var $this                          = $( this );
						var getUniqueDivId                 = $this.closest( '.epofw_addon_html' ).data( 'uqd-attr' );
						var fieldPrice                     = AWSF.epofwFieldsMatchParameter( $this, 'addon_price', '' );
						var fieldType                      = AWSF.epofwFieldsMatchParameter( $this, 'data_inp_type', '' );
						var fieldID                        = $( this ).attr( 'id' );
						var inputfieldName                 = $( this ).attr( 'name' );
						var inputfieldNameReplaceWithValue = inputfieldName.replace( '[value]', '' );
						var inputfieldNameReplaced         = inputfieldNameReplaceWithValue.replace( '[]', '' );
						var labelName                      = $( this ).attr( 'data-label-name' );

						var element    = $( this ).closest( '.epofw_tr_se' ).attr( 'id' );
						var docElemnt  = document.getElementById( element );
						var tdElement  = docElemnt ? ( docElemnt.querySelector( 'td.value' ) || docElemnt.querySelector( '.value' ) ) : null;
						var errorColor = '#ff0000';
						$( '#' + fieldID ).iris(
							{
								defaultColor: true,
								change: function ( event, ui ) {
									var color = ui.color.toString();
									if ( $( '#' + element + ' .epofw_error' ).length > 0 ) {
										$( '#' + element + ' .epofw_error' ).remove();
									}
									if ( color !== '' && ! AWSF.isValidColor( color ) ) {
										var errorElement         = document.createElement( 'p' );
										errorElement.className   = 'epofw_error';
										errorElement.style.color = errorColor;
										var errorMessage         = document.createTextNode( epofw_front_var.colorpicker_select_validation );
										errorElement.appendChild( errorMessage );
										tdElement.append( errorElement );
										$( this ).iris( 'color', '' ); // Clear the color if an invalid color is selected.
									}

									var trFieldName = labelName + ' - ' + color;
									var checkTr     = $( 'tr#tr_' + inputfieldNameReplaced ).length;
									if ( checkTr === 0 ) {
										var firstTr       = AWSF.createTr( color, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
										var addonSubtotal = document.querySelector( '#addon_total #addon_subtotal' );
										addonSubtotal.insertAdjacentHTML( 'beforebegin', firstTr.outerHTML );
									} else {
										AWSF.addTrInAddonDetails( color, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
									}
									AWSF.calculateAddonPrice();
								},
								clear: function ( event ) {
									var element = jQuery( event.target ).siblings( '.wp-color-picker' )[0];
									if ( element ) {
										$( 'tr#tr_' + inputfieldNameReplaced ).remove();
										AWSF.calculateAddonPrice();
									}
								},
								// hide the color picker controls on load.
								hide: true,
								// show a group of common colors beneath the square.
								palettes: true
							}
						).on(
							'change',
							function () {
								var color = $( this ).val();
								if ( $( '#' + element + ' .epofw_error' ).length > 0 ) {
									$( '#' + element + ' .epofw_error' ).remove();
								}
								if ( color !== '' && ! AWSF.isValidColor( color ) ) {
									var errorElement         = document.createElement( 'p' );
									errorElement.className   = 'epofw_error';
									errorElement.style.color = errorColor;
									var errorMessage         = document.createTextNode( epofw_front_var.colorpicker_change_validation );
									errorElement.appendChild( errorMessage );
									tdElement.append( errorElement );
									$( this ).val( '' ); // Clear the color if an invalid color is selected.
								}
							}
						);
					}
				);
			}
			var productId  = AWSF.epofwGetProductId();
			var currentQty = $( '.cart .quantity input[name="quantity"]' ).val();
			if ( $( 'form.cart' ).hasClass( 'variations_form' ) ) {
				var $variationSelect = $( '.variations_form .variations select' );
				var hasSelectedVariation = false;
				var selectedVariationId = '';
				$variationSelect.each( function () {
					var val = $( this ).val();
					if ( val && val !== '' ) {
						hasSelectedVariation = true;
						selectedVariationId = $( 'input[name="variation_id"]' ).val() || '';
						return false;
					}
				} );
				if ( ! hasSelectedVariation ) {
					AWSF.epofwCheckTable( productId, '', currentQty );
				} else if ( selectedVariationId ) {
					AWSF.epofwCheckTable( productId, selectedVariationId, currentQty );
				} else {
					AWSF.epofwCheckTable( productId, '', currentQty );
				}
			} else {
				AWSF.epofwCheckTable( productId, '', currentQty );
			}
			$( document ).on( 'input', '.epofw_fields_table:visible input[type="text"], .epofw_fields_table:visible input[type="email"], .epofw_fields_table:visible input[type="url"], .epofw_fields_table:visible input[type="tel"], .epofw_fields_table:visible input[type="password"], .epofw_fields_table:visible textarea', AWS_Front.onKeyUpChangeAddon );
			$( document ).on( 'change', '.epofw_fields_table:visible input, .epofw_fields_table:visible textarea', AWS_Front.onKeyUpChangeAddon );
			$( document ).on( 'change', '.epofw_fields_table:visible select', AWS_Front.onKeyUpChangeSelectAddon );
			$( document ).on( 'change', '.variations_form .variations select', AWS_Front.getSelectedVariation );
			$( document ).on( 'found_variation', '.variations_form', AWS_Front.onVariationFound );
			$( document ).on( 'change', '.cart.variations_form .quantity .qty', AWS_Front.getProductQty );
			$( document ).on( 'change', '.cart input[name="quantity"]', AWS_Front.updateProductPriceInAddonDetailsOnQtyChange );

			// Hide addon totals on page load if no addon items selected
			AWSF.calculateAddonPrice();
		},
		isValidTime: function ( timeString ) {
			// Support both 12-hour format (hh:mm:ss AM/PM) and 24-hour format (HH:mm:ss)
			var time12HourRegex = /^(0?[1-9]|1[0-2]):[0-5][0-9]:[0-5][0-9] (AM|PM)$/i;
			var time24HourRegex = /^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/;
			return time12HourRegex.test( timeString ) || time24HourRegex.test( timeString );
		},
		isValidDate: function ( dateString ) {
			// Parse the date string and check if it's a valid date.
			var dateFormat = 'dd-mm-yy'; // Date format should match the one used in the datepicker.
			var dateParts  = dateString.split( '-' );
			var day        = parseInt( dateParts[0], 10 );
			var month      = parseInt( dateParts[1], 10 ) - 1; // Month is zero-based.
			var year       = parseInt( dateParts[2], 10 );

			var date = new Date( year, month, day );

			return (
				date.getDate() === day &&
				date.getMonth() === month &&
				date.getFullYear() === year &&
				dateString === $.datepicker.formatDate( dateFormat, date )
			);
		},
		isValidColor: function ( colorString ) {
			var colorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
			return colorRegex.test( colorString );
		},
		updateProductPriceInAddonDetailsOnQtyChange: function () {
			var productId   = $( 'input[name="product_id"]' ).val();
			var variationId = $( 'input[name="variation_id"]' ).val();
			if ( 'undefined' === typeof productId ) {
				productId = $( '.single_add_to_cart_button' ).val() || $( 'button[name="add-to-cart"]' ).val();
			}
			if ( 'undefined' === typeof productId ) {
				variationId = '';
			}
			var currentQty = $( '.variations_form .quantity input[name="quantity"]' ).val();
			AWSF.epofwCheckTable( productId, variationId, currentQty );
		},
		updateProductPriceInAddonDetails: function () {
			var $addonPrice = $( '#addon_total #addon_prd_details .addon_price' );
			// Exit early if no addon price element found.
			if ( ! $addonPrice.length ) {
				return;
			}
			var qty        = $( '.quantity input[name="quantity"]' ).val();
			var addonPrice = $addonPrice.attr( 'data-epofw-prd-price' );
			// Ensure addonPrice is a valid number.
			if ( undefined === addonPrice || null === addonPrice || '' === addonPrice ) {
				addonPrice = 0;
			}
			addonPrice = parseFloat( addonPrice ) || 0;
			if ( $( 'form.cart' ).hasClass( 'bundle_form' ) && 1 < qty ) {
				addonPrice = $( '.bundle_price .price span.woocommerce-Price-amount.amount:last' ).text();
				addonPrice = addonPrice.replace( currencySymbol, '' );
				addonPrice = parseFloat( addonPrice ) || 0;
			}
			var updatedAddonPrice = addonPrice;
			qty = parseFloat( qty ) || 1;
			if ( 0 < qty ) {
				updatedAddonPrice = addonPrice * qty;
			}
			$addonPrice.attr( 'data-addon-price', updatedAddonPrice );
			if ( undefined !== updatedAddonPrice && ! isNaN( updatedAddonPrice ) ) {
				updatedAddonPrice = AWSF.number_format( updatedAddonPrice, decimals, decimalSeparator, thousandSeparator );
			}
			var newAddonPrice          = AWSF.setCurrencyPosition( updatedAddonPrice );
			var addonPriceSpan         = document.querySelector( '#addon_prd_details .addon_price strong span' );
			if ( addonPriceSpan ) {
				addonPriceSpan.textContent = newAddonPrice;
			}
		},
		checkValidationForEachFields: function () {
			var epofwPass = [];
			$( '.epofw_fields_table:visible .epofw_td_value' ).each(
				function () {
					var required = AWSF.epofwFieldsMatchParameter( $( this ), 'required', 'logical_operation' );
					var inpType  = AWSF.epofwFieldsMatchParameter( $( this ), 'data_inp_type', 'logical_operation' );
					var fieldType;
					if ( 'radiogroup' === inpType ) {
							fieldType = 'radio';
					}
					if ( 'checkbox' === inpType ||
					'checkboxgroup' === inpType ||
					'switch' === inpType ) {
						fieldType = 'checkbox';
					}
					if ( 'text' === inpType ||
					'datepicker' === inpType ||
					'colorpicker' === inpType ||
					'timepicker' === inpType ) {
							fieldType = 'text';
					}
					if ( 'slider' === inpType ) {
						fieldType = 'hidden';
					}
					if ( 'textarea' === inpType ||
					'number' === inpType ||
					'password' === inpType ||
					'select' === inpType ||
					'multiselect' === inpType ) {
							fieldType = inpType;
					}
					if ( required ) {
						if ( 'rd_status' in required ) {
							if ( 'on' === required.rd_status ) {
								var rd_text_color, rd_text;
								rd_text_color = '#ff0000';
								rd_text       = 'This is required field';

								epofwPass = AWSF.validateField( fieldType, rd_text_color, rd_text, this, epofwPass );
							}
						}
					}

				}
			);
			return epofwPass;
		},
		validateField: function ( fieldType, rd_text_color, rd_text, element, epofwPass ) {
			var isValid = true;

			switch ( fieldType ) {
				case 'radio':
				case 'checkbox':
				case 'switch':
					isValid = $( element ).find( 'input[type="' + fieldType + '"]' ).filter( ':checked' ).length > 0;
					break;
				case 'text':
				case 'textarea':
				case 'number':
				case 'password':
					isValid = $( element ).find( 'input[type="' + fieldType + '"]' ).val() !== '';
					break;
				case 'hidden':
					// For slider fields (hidden inputs).
					isValid = $( element ).find( 'input[type="hidden"]' ).val() !== '';
					break;
				case 'select':
					isValid = $( element ).find( 'select' ).val() !== '';
					break;
				case 'multiselect':
					isValid = $( element ).find( 'select > option:selected' ).length > 0;
					break;
				default:
					break;
			}

			if ( ! isValid ) {
				if ( $( element ).find( '.epofw_error' ).length < 1 ) {
					var errorElement         = document.createElement( 'p' );
					errorElement.className   = 'epofw_error';
					errorElement.style.color = rd_text_color;
					var errorMessage         = document.createTextNode( rd_text );
					errorElement.appendChild( errorMessage );
					element.appendChild( errorElement );
				}
				epofwPass.push( false );
			} else {
				var errorToRemove = $( element ).find( '.epofw_error' );
				if ( errorToRemove.length > 0 ) {
					errorToRemove.remove();
				}
			}

			return epofwPass;
		},
		getProductQty: function () {
			var productId  = AWSF.epofwGetProductId();
			var currentVal = $( this ).val();
			if ( $( 'form.cart' ).hasClass( 'variations_form' ) ) {
				var variationData       = $( '.variations_form' ).data( 'product_variations' );
				var currentAttributes   = AWSF.getChosenAttributes();
				var matching_variations = AWSF.findMatchingVariations( variationData, currentAttributes.data );
				if ( matching_variations ) {
					if ( currentAttributes.count == currentAttributes.chosenCount ) {
						if ( matching_variations.hasOwnProperty( 0 ) ) {
							var $epofwFieldsTable = $( '.epofw_fields_table' );
							if ( $epofwFieldsTable.length && $epofwFieldsTable.is( ':visible' ) ) {
								var variationId                     = matching_variations[0].variation_id;
								var variationPrice                  = matching_variations[0].display_price;
								var variationPriceWithFormat        = variationPrice.toFixed( decimals );
								var variationPriceWithFormatReplace = variationPriceWithFormat.replace( '.', decimalSeparator );
								$( '#addon_prd_details .addon_price' ).attr( 'data-addon-price', variationPrice );
								$( '#addon_prd_details .addon_price' ).attr( 'data-epofw-prd-price', variationPrice );
								var variablePrice             = AWSF.setCurrencyPosition( variationPriceWithFormatReplace );
								var variablePriceSpan         = document.querySelector( '#addon_prd_details .addon_price strong span' );
								variablePriceSpan.textContent = variablePrice;
								AWSF.calculateAddonPrice();
								AWSF.epofwCheckTable( productId, variationId, currentVal );
							}
						}
					} else {
						AWSF.epofwCheckTable( productId, '', currentVal );
					}
				}
			} else {
				$( '.epofw_fields_table:visible input.epofw_field_quantity' ).trigger( 'click' );
				AWSF.epofwCheckTable( productId, '', currentVal );
			}
		},
		getSelectedVariation: function () {
			var currentQty          = $( '.variations_form .quantity input[name="quantity"]' ).val();
			var productId           = $( 'input[name="product_id"]' ).val();
			var variationData       = $( '.variations_form' ).data( 'product_variations' );
			var currentAttributes   = AWSF.getChosenAttributes();
			var matching_variations = AWSF.findMatchingVariations( variationData, currentAttributes.data );
			if ( matching_variations ) {
				if ( currentAttributes.count == currentAttributes.chosenCount ) {
					if ( matching_variations.hasOwnProperty( 0 ) ) {
						var variationId    = matching_variations[0].variation_id;
						var variationPrice = matching_variations[0].display_price;
						var $addonTables   = $( '.epofw_fields_table' );
						if ( $addonTables.length ) {
							if ( variationPrice !== undefined && variationPrice !== null && ! isNaN( variationPrice ) ) {
								$( '#addon_prd_details .addon_price' ).attr( 'data-epofw-prd-price', variationPrice );
								var variationPriceWithFormat        = variationPrice.toFixed( decimals );
								var variationPriceWithFormatReplace = variationPriceWithFormat.replace( '.', decimalSeparator );
								$( '#addon_prd_details .addon_price' ).attr( 'data-addon-price', variationPrice );
								var variablePrice             = AWSF.setCurrencyPosition( variationPriceWithFormatReplace );
								var variablePriceSpan         = document.querySelector( '#addon_prd_details .addon_price strong span' );
								variablePriceSpan.textContent = variablePrice;
								AWSF.calculateAddonPrice();
								AWSF.epofwCheckTable( productId, variationId, currentQty );
							}
						}
					}
				} else {
					AWSF.epofwCheckTable( productId, '', currentQty );
				}
			}
		},
		onVariationFound: function ( event, variation ) {
			var $addonTables = $( '.epofw_fields_table' );
			if ( $addonTables.length && variation && variation.variation_id ) {
				var currentQty = $( '.variations_form .quantity input[name="quantity"]' ).val();
				var productId = $( 'input[name="product_id"]' ).val();
				var variationId = variation.variation_id;
				var variationPrice = variation.display_price;
				
				if ( variationPrice !== undefined && variationPrice !== null && ! isNaN( variationPrice ) ) {
					$( '#addon_prd_details .addon_price' ).attr( 'data-epofw-prd-price', variationPrice );
					var variationPriceWithFormat = variationPrice.toFixed( decimals );
					var variationPriceWithFormatReplace = variationPriceWithFormat.replace( '.', decimalSeparator );
					$( '#addon_prd_details .addon_price' ).attr( 'data-addon-price', variationPrice );
					var variablePrice = AWSF.setCurrencyPosition( variationPriceWithFormatReplace );
					$( '#addon_prd_details .addon_price strong span' ).html( variablePrice );
					AWSF.calculateAddonPrice();
					AWSF.epofwCheckTable( productId, variationId, currentQty );
				}
			}
		},
		onKeyUpChangeAddon: function () {
			var getUniqueDivId = $( this ).closest( '.epofw_addon_html' ).data( 'uqd-attr' );
			var qty            = $( '.quantity input[name="quantity"]' ).val();
			AWSF.epofwDisplayFiledsDataAndDisplay( $( this ), qty, getUniqueDivId );
		},
		onKeyUpChangeSelectAddon: function () {
			var getUniqueDivId = $( this ).closest( '.epofw_addon_html' ).data( 'uqd-attr' );
			var qty            = $( '.quantity input[name="quantity"]' ).val();
			AWSF.epofwDisplayAnotherFiledsDataAndDisplay( $( this ), qty, getUniqueDivId );
		},
		addonPriceChangeToDecimalForCalc: function ( fieldPrice ) {
			var addonPrice = fieldPrice;
			fieldPrice     = fieldPrice.toString();
			if ( fieldPrice.indexOf( decimalSeparator ) != -1 ) {
				addonPrice = fieldPrice.replace( decimalSeparator, '.' );
			}
			return addonPrice;
		},
		changeAddonDetailsIfTrExists: function ( fieldID, trFieldName, fieldPriceForAddonAttr, fieldPrice, getUniqueDivId ) {
			var trElement = document.getElementById( 'tr_' + fieldID );
			if ( trElement ) {
				var tdElement = trElement.querySelector( 'td:first-child' );
				if ( tdElement ) {
					var dvElement = tdElement.querySelector( 'div#dv_' + fieldID );
					if ( dvElement ) {
						dvElement.textContent = trFieldName;
					}
				}
			}
			// Addon field Qty.
			var currentQuantity = $( '#' + fieldID + '_afq' ).val();
			if ( currentQuantity ) {
				fieldPrice = fieldPrice * currentQuantity;
			}
			if ( undefined !== fieldPrice ) {
				fieldPrice = AWSF.number_format( fieldPrice, decimals, decimalSeparator, thousandSeparator );
			}
			$( 'tr#tr_' + fieldID ).attr( 'data-udi', getUniqueDivId );
			var trElement1 = document.getElementById( 'tr_' + fieldID );
			if ( trElement1 ) {
				var tdElements    = trElement1.getElementsByTagName( 'td' );
				var lastTdElement = tdElements[tdElements.length - 1];
				if ( lastTdElement ) {
					lastTdElement.textContent = AWSF.setCurrencyPosition( fieldPrice );
				}
			}
			var addonPrice = AWSF.addonPriceChangeToDecimalForCalc( fieldPrice );
			$( 'tr#tr_' + fieldID ).find( 'td:last' ).attr( 'data-addon-price', addonPrice );
			$( 'tr#tr_' + fieldID ).find( 'td:last' ).attr( 'data-addon-og-price', fieldPriceForAddonAttr );
		},
		createTr: function ( fieldValue, fieldID, trFieldName, fieldPrice, fieldImage, fieldType, getUniqueDivId ) {
			var firstTr = document.createElement( 'tr' );
			firstTr.setAttribute( 'id', 'tr_' + fieldID );
			firstTr.setAttribute( 'class', 'addon_item' );
			firstTr.setAttribute( 'data-udi', getUniqueDivId );
			var firstTd      = document.createElement( 'td' );
			var firstTrTdDiv = document.createElement( 'div' );
			firstTrTdDiv.setAttribute( 'id', 'dv_' + fieldID );
			var firstTrTdSpan = document.createElement( 'span' );
			firstTrTdSpan.setAttribute( 'class', 'span_field_lable' );
			// For colorpicker.
			if ( 'colorpicker' === fieldType ) {
				var trFieldNameReplace = trFieldName.replace( fieldValue, '' );
				trFieldName            = trFieldNameReplace;
			}
			var firstTrTdSpanText = document.createTextNode( trFieldName );
			firstTrTdSpan.appendChild( firstTrTdSpanText );
			// For colorpicker.
			if ( 'colorpicker' === fieldType ) {
				var firstTrTdSpan2 = document.createElement( 'span' );
				firstTrTdSpan2.setAttribute( 'style', 'color: ' + fieldValue + '; font-size:20px; padding: 0;line-height: 0' );
				var firstTrTdSpan2Text = document.createTextNode( '■' );
				firstTrTdSpan2.appendChild( firstTrTdSpan2Text );

				var firstTrTdBlankText = document.createTextNode( ' ' );
				firstTrTdSpan2.appendChild( firstTrTdBlankText );

				var firstTrTdLabel = document.createElement( 'label' );
				firstTrTdLabel.setAttribute( 'class', 'label_field_lable' );
				var firstTrTdLabelText = document.createTextNode( fieldValue );
				firstTrTdLabel.appendChild( firstTrTdLabelText );

				firstTrTdSpan.appendChild( firstTrTdSpan2 );
				firstTrTdSpan.appendChild( firstTrTdLabel );
			}
			firstTrTdDiv.appendChild( firstTrTdSpan );
			firstTd.appendChild( firstTrTdDiv );
			var firstTrSecondTd = document.createElement( 'td' );
			firstTrSecondTd.setAttribute( 'class', 'addon_price' );
			var originalAddonPrice = AWSF.addonPriceChangeToDecimalForCalc( fieldPrice );
			// Addon field Qty.
			var currentQuantity = $( '#' + fieldID + '_afq' ).val();
			if ( currentQuantity ) {
				fieldPrice = fieldPrice * currentQuantity;
			}
			var addonPrice = AWSF.addonPriceChangeToDecimalForCalc( fieldPrice );
			firstTrSecondTd.setAttribute( 'data-addon-price', addonPrice );
			firstTrSecondTd.setAttribute( 'data-addon-og-price', originalAddonPrice );
			if ( undefined !== fieldPrice ) {
				fieldPrice = AWSF.number_format( fieldPrice, decimals, decimalSeparator, thousandSeparator );
			}
			var firstSecondTdText;
			fieldPrice        = AWSF.setCurrencyPosition( fieldPrice );
			firstSecondTdText = document.createTextNode( fieldPrice );
			firstTrSecondTd.appendChild( firstSecondTdText );
			firstTr.appendChild( firstTd );
			firstTr.appendChild( firstTrSecondTd );
			return firstTr;
		},
		setCurrencyPosition: function ( fieldPrice ) {
			// Ensure fieldPrice is a string to prevent undefined errors.
			if ( undefined === fieldPrice || null === fieldPrice ) {
				fieldPrice = '0';
			}

			// Validate fieldPrice is numeric before formatting.
			if ( typeof fieldPrice === 'string' && isNaN( parseFloat( fieldPrice ) ) ) {
				// Log warning for debugging non-numeric values like "1 minuto".
				if ( typeof console !== 'undefined' && console.warn ) {
					console.warn( 'EPOFW: setCurrencyPosition received non-numeric value:', fieldPrice );
				}
				return '';
			}

			fieldPrice = String( fieldPrice );
			if ( 'left_space' == position ) {
				if ( fieldPrice.indexOf( '-' ) != -1 ) {
					fieldPrice = fieldPrice.replace( '-', '' );
					fieldPrice = '-' + currencySymbol + ' ' + fieldPrice;
				} else {
					fieldPrice = currencySymbol + ' ' + fieldPrice;
				}
			} else if ( 'left' == position ) {
				if ( fieldPrice.indexOf( '-' ) != -1 ) {
					fieldPrice = fieldPrice.replace( '-', '' );
					fieldPrice = '-' + currencySymbol + fieldPrice;
				} else {
					fieldPrice = currencySymbol + fieldPrice;
				}
			} else if ( 'right_space' == position ) {
				if ( fieldPrice.indexOf( '-' ) != -1 ) {
					fieldPrice = fieldPrice.replace( '-', '' );
					fieldPrice = '-' + fieldPrice + ' ' + currencySymbol;
				} else {
					fieldPrice = fieldPrice + ' ' + currencySymbol;
				}
			} else if ( 'right' == position ) {
				if ( fieldPrice.indexOf( '-' ) != -1 ) {
					fieldPrice = fieldPrice.replace( '-', '' );
					fieldPrice = '-' + fieldPrice + currencySymbol;
				} else {
					fieldPrice = fieldPrice + currencySymbol;
				}
			}
			return fieldPrice;
		},
		addTrInAddonDetails: function ( fieldValue, fieldID, trFieldName, fieldPrice, fieldImage, fieldType, getUniqueDivId ) {
			var firstTr;
			var mainTableID = $( '#addon_total' );
			if ( '' !== fieldValue ) {
				var checkTr = mainTableID.find( 'tr#tr_' + fieldID ).length;
				if ( 0 === checkTr ) {
					firstTr = AWSF.createTr( fieldValue, fieldID, trFieldName, fieldPrice, fieldImage, fieldType, getUniqueDivId );
				} else {
					if ( mainTableID.find( '#dv_' + fieldID ).length ) {
						mainTableID.find( '#dv_' + fieldID ).remove();
					}
					var mainTr       = document.getElementById( 'tr_' + fieldID );
					var firstTd      = mainTr.getElementsByTagName( 'td' )[0];
					var firstTrTdDiv = document.createElement( 'div' );
					firstTrTdDiv.setAttribute( 'id', 'dv_' + fieldID );
					var firstTrTdSpan = document.createElement( 'span' );
					firstTrTdSpan.setAttribute( 'class', 'span_field_lable' );
					// For colorpicker.
					if ( 'colorpicker' === fieldType ) {
						var trFieldNameReplace = trFieldName.replace( fieldValue, '' );
						trFieldName            = trFieldNameReplace;
					}
					var firstTrTdSpanText = document.createTextNode( trFieldName );
					firstTrTdSpan.appendChild( firstTrTdSpanText );
					// For colorpicker.
					if ( 'colorpicker' === fieldType ) {
						var firstTrTdSpan2 = document.createElement( 'span' );
						firstTrTdSpan2.setAttribute( 'style', 'color: ' + fieldValue + '; font-size:20px; padding: 0;line-height: 0' );
						var firstTrTdSpan2Text = document.createTextNode( '■' );
						firstTrTdSpan2.appendChild( firstTrTdSpan2Text );

						var firstTrTdBlankText = document.createTextNode( ' ' );
						firstTrTdSpan2.appendChild( firstTrTdBlankText );

						var firstTrTdLabel = document.createElement( 'label' );
						firstTrTdLabel.setAttribute( 'class', 'label_field_lable' );
						var firstTrTdLabelText = document.createTextNode( fieldValue );
						firstTrTdLabel.appendChild( firstTrTdLabelText );

						firstTrTdSpan.appendChild( firstTrTdSpan2 );
						firstTrTdSpan.appendChild( firstTrTdLabel );
					}
					firstTrTdDiv.appendChild( firstTrTdSpan );
					firstTd.appendChild( firstTrTdDiv );
					var secondTd           = mainTr.getElementsByTagName( 'td' )[1];
					var originalAddonPrice = AWSF.addonPriceChangeToDecimalForCalc( fieldPrice );
					// Addon field Qty.
					var currentQuantity = $( '#' + fieldID + '_afq' ).val();
					if ( currentQuantity ) {
						fieldPrice = fieldPrice * currentQuantity;
					}
					if ( fieldPrice ) {
						var formattedPrice = fieldPrice;
						if ( undefined !== fieldPrice ) {
							formattedPrice = AWSF.number_format( fieldPrice, decimals, decimalSeparator, thousandSeparator );
						}
						var fieldPriceDisplay = AWSF.setCurrencyPosition( formattedPrice );
						secondTd.textContent  = fieldPriceDisplay;
					}
					var thirdTd    = mainTr.getElementsByTagName( 'td' )[1];
					var addonPrice = AWSF.addonPriceChangeToDecimalForCalc( fieldPrice );
					thirdTd.setAttribute( 'data-addon-price', addonPrice );
					thirdTd.setAttribute( 'data-addon-og-price', originalAddonPrice );
				}
				var addonTotalRow    = document.getElementById( 'addon_total' );
				var addonSubtotalRow = document.getElementById( 'addon_subtotal' );
				if ( addonTotalRow && addonSubtotalRow && firstTr ) {
					addonSubtotalRow.insertAdjacentHTML( 'beforebegin', firstTr.outerHTML );
				}
			} else {
				mainTableID.find( 'tr#tr_' + fieldID ).remove();
			}
		},
		number_format: function ( number, decimals, dec_point, thousands_point ) {
			if ( number == null ) {
				return '0';
			}

			// Validate input is a number or numeric string.
			if ( typeof number === 'string' && isNaN( parseFloat( number ) ) ) {
				// Log warning for debugging non-numeric values like "1 minuto".
				if ( typeof console !== 'undefined' && console.warn ) {
					console.warn( 'EPOFW: number_format received non-numeric value:', number );
				}
				return '0';
			}

			number = number.toString();
			// Need when use space as thousand separator.
			number         = ( number + '' ).replace( /[^0-9+\-Ee.]/g, '' );
			var n          = ! isFinite( +number ) ? 0 : +number,
				prec       = ! isFinite( +decimals ) ? 0 : Math.abs( decimals ),
				sep        = ( typeof thousands_point === 'undefined' ) ? ',' : thousands_point,
				dec        = ( typeof dec_point === 'undefined' ) ? '.' : dec_point,
				s          = '',
				toFixedFix = function ( n, prec ) {
					var k = Math.pow( 10, prec );
					return '' + Math.round( n * k ) / k;
				};
			// Fix for IE parseFloat(0.55).toFixed(0) = 0.
			s = ( prec ? toFixedFix( n, prec ) : '' + Math.round( n ) ).split( '.' ); // '.'
			if ( s[0].length > 3 ) {
				s[0] = s[0].replace( /\B(?=(?:\d{3})+(?!\d))/g, sep );
			}
			if ( ( s[1] || '' ).length < prec ) {
				s[1]  = s[1] || '';
				s[1] += new Array( prec - s[1].length + 1 ).join( '0' );
			}
			return s.join( dec );
		},
		calculateAddonPrice: function () {
			AWSF.updateProductPriceInAddonDetails();
			var visibleAddonFieldsCount = $( '.epofw_fields_table:visible' ).length;
			var checkData = visibleAddonFieldsCount > 0;
			if ( true === checkData ) {
				var addonItemCount = $( '#addon_total tr.addon_item' ).length;
				if ( addonItemCount === 0 ) {
					$( '#addon_total' ).hide();
				} else {
					$( '#addon_total' ).removeClass( 'addon_total_hd' );
					$( '#addon_total' ).show();
					var addonSubtotal = 0;
					$( '.epofw_addon_totals #addon_total:visible:not(.addon_total_hd) .addon_price' ).each(
						function () {
							addonSubtotal = parseFloat( addonSubtotal ) + parseFloat( $( this ).attr( 'data-addon-price' ) );
						}
					);

					if ( undefined !== addonSubtotal ) {
						addonSubtotal = AWSF.number_format( addonSubtotal, decimals, decimalSeparator, thousandSeparator );
					}
					var addonSubtotalElement = document.getElementById( 'addon_subtotal' );
					if ( addonSubtotalElement ) {
						var tdElements    = addonSubtotalElement.getElementsByTagName( 'td' );
						var lastTdElement = tdElements[tdElements.length - 1];
						if ( lastTdElement ) {
							var strongElement = lastTdElement.querySelector( 'strong' );
							if ( strongElement ) {
								strongElement.textContent = AWSF.setCurrencyPosition( addonSubtotal );
							}
						}
					}

				}
			} else {
				$( '#addon_total' ).hide();
			}

			/**
			 * Trigger after addon total is updated.
			 *
			 * Use this trigger to respond to price changes in custom modules.
			 *
			 * @since 4.4.5
			 * @event epofw_addon_total_updated
			 * @param {number} total     The calculated addon total.
			 * @param {string} productId The product ID.
			 */
			var productId = AWSF.epofwGetProductId();
			var total = 0;
			$( '.epofw_addon_totals #addon_total:visible:not(.addon_total_hd) .addon_price' ).each(
				function () {
					total = parseFloat( total ) + parseFloat( $( this ).attr( 'data-addon-price' ) );
				}
			);
			$( document.body ).trigger( 'epofw_addon_total_updated', [ total, productId ] );
		},
		getFieldInputBasedOnType: function ( get_field_type ) {
			var fieldInput = '';
			if ( 'select' === get_field_type || 'multiselect' === get_field_type ) {
				fieldInput = 'select';
			} else if (
				'radiogroup' === get_field_type
			) {
				fieldInput = 'input[type="radio"]:checked';
			} else if (
				'checkboxgroup' === get_field_type ||
				'checkbox' === get_field_type ) {
				fieldInput = 'input[type="checkbox"]:checked';
			} else if ( 'password' === get_field_type ) {
				fieldInput = 'input[type="password"]';
			} else if ( 'slider' === get_field_type ) {
				fieldInput = 'input[type="hidden"]';
			} else if (
				'text' === get_field_type ||
				'hidden' === get_field_type ||
				'number' === get_field_type ||
				'datepicker' === get_field_type ||
				'colorpicker' === get_field_type ||
				'timepicker' === get_field_type
			) {
				// Include email, url, tel types for text fields with restrictions.
				fieldInput = 'input[type="text"], input[type="email"], input[type="url"], input[type="tel"]';
			} else if ( 'textarea' === get_field_type ) {
				fieldInput = 'textarea';
			}
			return fieldInput;
		},
		findMatchingVariations: function ( variations, attributes ) {
			var matching         = [];
			var variationsLength = variations.length;

			for ( var i = 0; i < variationsLength; i++ ) {
				var variation = variations[ i ];
				if ( AWSF.isMatch( variation.attributes, attributes ) ) {
					matching.push( variation );
				}
			}
			return matching;
		},
		isMatch: function ( variation_attributes, attributes ) {
			var match = true;
			for ( var attr_name in variation_attributes ) {
				if ( variation_attributes.hasOwnProperty( attr_name ) ) {
					var val1 = variation_attributes[attr_name];
					var val2 = attributes[attr_name];// attributes.
					if ( val1 !== undefined && val2 !== undefined && val1.length !== 0 && val2.length !== 0 && val1 !== val2 ) {
						match = false;
					}
				}
			}
			return match;
		},
		getChosenAttributes: function () {
			var data   = {};
			var count  = 0;
			var chosen = 0;
			$( '.variations_form' ).find( '.variations select' ).each(
				function () {
					var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
					var value          = $( this ).val() || '';
					if ( value.length > 0 ) {
							chosen++;
					}
					count++;
					data[attribute_name] = value;
				}
			);
			return {
				'count': count,
				'chosenCount': chosen,
				'data': data
			};
		},
		epofwMatchParameter: function ( epofwData, productId, variationId, qty, trIds ) {
			// Free version: Always return true (premium conditions not supported in free version).
			// Handle both old flat array format and new nested structure format gracefully.
			if ( trIds && trIds.length ) {
				$( trIds ).each(
					function () {
						AWSF.calculateAddonPrice();
					}
				);
			}
			return true;
		},
		epofwFieldsMatchParameter: function ( $this, key, action ) {
			var epofwData;
			if ( 'logical_operation' === action ) {
				epofwData = $this.attr( 'data-epofw_sa' );
			} else {
				epofwData = $this.parent().closest( '.epofw_td_value' ).attr( 'data-epofw_sa' );
			}
			if ( epofwData ) {
				var epofwDataJson = JSON.parse( epofwData );
				return epofwDataJson[0][key];
			}
		},
		epofwCheckTable: function ( productId, variationId, qty ) {
			$( '.epofw_fields_table' ).each(
				function () {
					var $this          = $( this );
					var getEopfwAttr   = $( this ).data( 'epofw_attr' );
					var getUniqueDivId = $( this ).closest( '.epofw_addon_html' ).data( 'uqd-attr' );
					var trIds          = [];
					$( this ).find( '.epofw_tr_se:visible' ).each(
						function () {
							trIds.push( $( this ).find( 'input, select, textarea' ).attr( 'id' ) );
						}
					);
					var matchData = AWSF.epofwMatchParameter( getEopfwAttr, productId, variationId, qty, trIds );
					if ( true === matchData ) {
						if ( ( $this ).hasClass( 'epofw_field_qty_hd' ) ) {
							$this.removeClass( 'epofw_field_qty_hd' );
						}
						if ( ( $this ).hasClass( 'epofw_field_dnl' ) ) {
							$this.removeClass( 'epofw_field_dnl' );
						}
						AWSF.epofwGetFieldData( $this, qty, getUniqueDivId );
						AWSF.calculateAddonPrice();
						$this.show();

						// Enable all inputs in visible container so they can be submitted
						$this.find( 'input, select, textarea' ).each( function() {
							var $input = $( this );
							// Only enable if it was disabled by conditional logic (has our marker class)
							if ( $input.hasClass( 'epofw-condition-disabled' ) ) {
								$input.prop( 'disabled', false ).removeClass( 'epofw-condition-disabled' );
							}
						} );
					} else {
						$this.hide();

						// Disable all inputs in hidden container so they won't be submitted
						// This prevents hidden fields with default values from being added to cart
						$this.find( 'input, select, textarea' ).each( function() {
							var $input = $( this );
							if ( ! $input.prop( 'disabled' ) ) {
								$input.prop( 'disabled', true ).addClass( 'epofw-condition-disabled' );
							}
						} );

						AWSF.epofwGetFieldData( $this, qty, getUniqueDivId );
						$( '#addon_total tr[data-udi="' + getUniqueDivId + '"]' ).each(
							function () {
								$( '#' + $( this ).attr( 'id' ) ).remove();
							}
						);
						AWSF.calculateAddonPrice();
					}
				}
			);
		},
		getFieldPriceBasedOnPriceOptions: function ( fieldValue, fieldPriceType, fieldPrice ) {
			fieldPrice = fieldPrice;
			return AWSF.addonPriceChangeToDecimalForCalc( fieldPrice );
		},
		epofwGetFieldData: function ( thisData, qty, getUniqueDivId ) {
			$( thisData ).find( '.epofw_tr_se:visible input, .epofw_tr_se:visible textarea' ).each(
				function () {
					AWSF.epofwDisplayFiledsDataAndDisplay( $( this ), qty, getUniqueDivId );
				}
			);
			$( thisData ).find( '.epofw_tr_se:visible select' ).each(
				function () {
					AWSF.epofwDisplayAnotherFiledsDataAndDisplay( $( this ), qty, getUniqueDivId );
				}
			);
		},
		epofwMatchOptionsBasedOnCheckedValue: function ( fieldOptions, fieldValue ) {
			var fieldValueTrimmed = ( typeof fieldValue === 'string' ) ? fieldValue.trim() : fieldValue;

			// Handle object-based options (keyed by label or switcher value)
			if ( fieldOptions && typeof fieldOptions === 'object' && !Array.isArray( fieldOptions ) ) {
				if ( fieldOptions.hasOwnProperty( fieldValue ) ) {
					return fieldOptions[ fieldValue ];
				}
				// Fallback: match by trimmed key (option labels may have trailing/leading spaces from DB)
				for ( var key in fieldOptions ) {
					if ( fieldOptions.hasOwnProperty( key ) && ( key.trim ? key.trim() : key ) === fieldValueTrimmed ) {
						return fieldOptions[ key ];
					}
				}
			}

			// Handle array-based options (legacy format)
			if ( Array.isArray( fieldOptions ) ) {
				for ( var i = 0; i < fieldOptions.length; i++ ) {
					if ( Array.isArray( fieldOptions[ i ] ) ) {
						var optLabel = fieldOptions[ i ][ 0 ];
						var optLabelTrimmed = ( typeof optLabel === 'string' ) ? optLabel.trim() : optLabel;
						if ( optLabel === fieldValue || optLabelTrimmed === fieldValueTrimmed ) {
							return fieldOptions[ i ];
						}
					}
				}
			}

			return undefined;
		},
		epofwDisplayFiledsDataAndDisplay: function ( $this, qty, getUniqueDivId ) {
			if ( $this.closest( '.epofw_tr_se' ).is( ':hidden' ) ) {
				return;
			}
			var dataInpType = AWSF.epofwFieldsMatchParameter( $this, 'data_inp_type', '' );
			if ( 'select' === dataInpType || 'multiselect' === dataInpType ) {
				return;
			}
			var fieldType = AWSF.epofwFieldsMatchParameter( $this, 'data_inp_type', '' );
			var fieldName, fieldValue, fieldPrice, fieldPriceType, fieldID, trFieldName, firstTr,
				trID, getFieldData, inputfieldName, inputfieldNameReplaceWithValue,
				inputfieldNameReplaced, fieldOptions;
			qty = $( '.quantity input[name="quantity"]' ).val();
			if ( 'checkbox' === fieldType ) {
				fieldID                   = $this.attr( 'id' );
				var multiSelectValueArray = {};
				$( $( 'input[name="' + $this.attr( 'name' ) + '"]:checked' ) ).each(
					function () {
						fieldValue   = $( this ).val();
						fieldOptions = AWSF.epofwFieldsMatchParameter( $( this ), 'options', '' );
						getFieldData = AWSF.epofwMatchOptionsBasedOnCheckedValue( fieldOptions, fieldValue );
						if ( getFieldData ) {
								fieldPriceType = getFieldData[1];
								fieldPrice     = AWSF.getFieldPriceBasedOnPriceOptions( fieldValue, fieldPriceType, getFieldData[2] );
						}
						multiSelectValueArray[fieldValue] = fieldPrice;
					}
				);
				var multiSelectPrice = 0;
				var multiFieldValue  = [];
				for ( var key in multiSelectValueArray ) {
					multiFieldValue.push( key );
					multiSelectPrice = parseFloat( multiSelectPrice ) + parseFloat( multiSelectValueArray[key] );
				}
				if ( multiFieldValue ) {
					fieldValue = multiFieldValue.join();
				}
				fieldPrice                     = multiSelectPrice;
				fieldName                      = $this.attr( 'data-label-name' );
				trFieldName                    = fieldName + ' - ' + fieldValue;
				inputfieldName                 = $this.attr( 'name' );
				inputfieldNameReplaceWithValue = inputfieldName.replace( '[value]', '' );
				inputfieldNameReplaced         = inputfieldNameReplaceWithValue.replace( '[]', '' );
				if ( '' !== fieldValue ) {
					if ( $( 'tr#tr_' + inputfieldNameReplaced ).length === 0 ) {
						firstTr = AWSF.createTr( fieldValue, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
					} else {
						AWSF.changeAddonDetailsIfTrExists( inputfieldNameReplaced, trFieldName, multiSelectPrice, fieldPrice, getUniqueDivId );
					}
					var addonTotalRow    = document.getElementById( 'addon_total' );
					var addonSubtotalRow = document.getElementById( 'addon_subtotal' );
					if ( addonTotalRow && addonSubtotalRow && firstTr ) {
						addonSubtotalRow.insertAdjacentHTML( 'beforebegin', firstTr.outerHTML );
					}
				} else {
					$( 'tr#tr_' + inputfieldNameReplaced ).remove();
				}
			} else if ( 'checkboxgroup' === fieldType ) {
				fieldValue                     = '';
				inputfieldName                 = $this.attr( 'name' );
				inputfieldNameReplaceWithValue = inputfieldName.replace( '[value]', '' );
				inputfieldNameReplaced         = inputfieldNameReplaceWithValue.replace( '[]', '' );
				if ( $this.is( ':checked' ) ) {
					fieldValue   = $this.val();
					fieldOptions = AWSF.epofwFieldsMatchParameter( $this, 'options', '' );
					getFieldData = AWSF.epofwMatchOptionsBasedOnCheckedValue( fieldOptions, fieldValue );
					if ( getFieldData ) {
						fieldPriceType = getFieldData[1];
						fieldPrice     = AWSF.getFieldPriceBasedOnPriceOptions( fieldValue, fieldPriceType, getFieldData[2] );

						fieldName = $this.attr( 'data-label-name' );
						trID      = $this.parent().parent().parent().attr( 'id' );
						
						// Find all other checkboxes in the same group
						var $otherCheckboxes = $( '#' + trID + ' .epofw_field_checkboxgroup' ).not( $this );
						
						// Remove addon details for other checkboxes before unchecking them
						$otherCheckboxes.each( function() {
							var $otherCheckbox = $( this );
							var otherInputName = $otherCheckbox.attr( 'name' );
							if ( otherInputName ) {
								var otherInputNameReplaced = otherInputName.replace( '[value]', '' ).replace( '[]', '' );
								$( 'tr#tr_' + otherInputNameReplaced ).remove();
							}
						} );
						
						// Uncheck all other checkboxes in the same group
						$otherCheckboxes.prop( 'checked', false );
						
						// Ensure current checkbox is checked
						$this.prop( 'checked', true );
						
						fieldID     = $this.attr( 'id' );
						trFieldName = fieldName + ' - ' + fieldValue;
						AWSF.addTrInAddonDetails( fieldValue, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
					}
				} else {
					$( 'tr#tr_' + inputfieldNameReplaced ).remove();
				}
			} else if ( 'radiogroup' === fieldType ) {
				fieldValue                     = '';
				inputfieldName                 = $this.attr( 'name' );
				inputfieldNameReplaceWithValue = inputfieldName.replace( '[value]', '' );
				inputfieldNameReplaced         = inputfieldNameReplaceWithValue.replace( '[]', '' );
				if ( $this.is( ':checked' ) ) {
					fieldValue   = $this.val();
					fieldOptions = AWSF.epofwFieldsMatchParameter( $this, 'options', '' );
					getFieldData = AWSF.epofwMatchOptionsBasedOnCheckedValue( fieldOptions, fieldValue );
					if ( getFieldData ) {
						fieldPriceType = getFieldData[1];
						fieldPrice     = AWSF.getFieldPriceBasedOnPriceOptions( fieldValue, fieldPriceType, getFieldData[2] );

						fieldName   = $this.attr( 'data-label-name' );
						fieldID     = $this.attr( 'id' );
						trFieldName = fieldName + ' - ' + fieldValue;
						AWSF.addTrInAddonDetails( fieldValue, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
					}
				}
			} else if ( 'html' === fieldType ) {
				fieldID        = $this.attr( 'id' );
				fieldName      = AWSF.epofwFieldsMatchParameter( $this, 'data-label-name', '' );
				fieldValue     = $this.val();
				fieldPrice     = AWSF.epofwFieldsMatchParameter( $this, 'addon_price', '' );
				fieldPriceType = AWSF.epofwFieldsMatchParameter( $this, 'addon_price_type', '' );
				fieldPrice     = AWSF.getFieldPriceBasedOnPriceOptions( fieldValue, fieldPriceType, fieldPrice );
				trFieldName    = fieldName + ' - ' + fieldValue;
				if ( fieldValue ) {
					AWSF.addTrInAddonDetails( fieldValue, fieldID, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
				}
			} else if ( 'switch' === fieldType ) {
				fieldValue                     = $this.val();
				inputfieldName                 = $this.attr( 'name' );
				inputfieldNameReplaceWithValue = inputfieldName.replace( '[value]', '' );
				inputfieldNameReplaced         = inputfieldNameReplaceWithValue.replace( '[]', '' );

				fieldName      = AWSF.epofwFieldsMatchParameter( $this, 'data-label-name', '' );
				fieldPrice     = AWSF.epofwFieldsMatchParameter( $this, 'addon_price', '' );
				fieldPriceType = AWSF.epofwFieldsMatchParameter( $this, 'addon_price_type', '' );

				if ( $this.is( ':checked' ) ) {
					var element         = $this.closest( '.epofw_tr_se' ).attr( 'id' ),
						$epfowErrorElem = $( '#' + element + ' .epofw_error' );
					if ( $epfowErrorElem.length > 0 ) {
						$epfowErrorElem.remove();
					}
					$this.val( epofw_front_var.switch_on_text );
					fieldValue  = epofw_front_var.switch_on_text;
					trFieldName = fieldName + ' - ' + fieldValue;
					AWSF.addTrInAddonDetails( fieldValue, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
				} else {
					$this.val( '' );
					fieldValue = $this.val();
					$( 'tr#tr_' + inputfieldNameReplaced ).remove();
				}
			} else if ( 'slider' === fieldType ) {
				// Handle slider field type.
				fieldValue                     = $this.val();
				inputfieldName                 = $this.attr( 'name' );
				inputfieldNameReplaceWithValue = inputfieldName.replace( '[value]', '' );
				inputfieldNameReplaced         = inputfieldNameReplaceWithValue.replace( '[]', '' );

				fieldName      = $this.attr( 'data-label-name' );
				fieldPrice     = AWSF.epofwFieldsMatchParameter( $this, 'addon_price', '' );
				fieldPriceType = AWSF.epofwFieldsMatchParameter( $this, 'addon_price_type', '' );
				fieldPrice     = AWSF.getFieldPriceBasedOnPriceOptions( fieldValue, fieldPriceType, fieldPrice );

				if ( fieldValue && '' !== fieldValue ) {
					trFieldName = fieldName + ' - ' + fieldValue;
					AWSF.addTrInAddonDetails( fieldValue, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
				} else {
					$( 'tr#tr_' + inputfieldNameReplaced ).remove();
				}
			} else {
				if ( 'undefined' === typeof fieldType ) {
					return;
				}
				// Show Addon Field Quantity Box.
				fieldID                        = $this.attr( 'id' );
				fieldName                      = $this.attr( 'data-label-name' );
				fieldValue                     = $this.val();
				inputfieldName                 = $this.attr( 'name' );
				inputfieldNameReplaceWithValue = inputfieldName.replace( '[value]', '' );
				inputfieldNameReplaced         = inputfieldNameReplaceWithValue.replace( '[]', '' );
				fieldPrice                     = AWSF.epofwFieldsMatchParameter( $this, 'addon_price', '' );
				fieldPriceType                 = AWSF.epofwFieldsMatchParameter( $this, 'addon_price_type', '' );
				fieldPrice                     = AWSF.getFieldPriceBasedOnPriceOptions( fieldValue, fieldPriceType, fieldPrice );

				// Mask password value for display - show dots instead of actual value.
				var displayValue = fieldValue;
				if ( 'password' === fieldType && fieldValue ) {
					displayValue = '●'.repeat( fieldValue.length );
				}
				trFieldName                    = fieldName + ' - ' + displayValue;
				AWSF.addTrInAddonDetails( displayValue, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
			}
			AWSF.calculateAddonPrice();
		},
		epofwMultiSelectData: function ( $this, fieldName, fieldValue, fieldType, fieldPrice, trFieldName, firstTr, fieldID, fieldOptions, qty, getUniqueDivId ) {
			if ( $this.closest( '.epofw_tr_se' ).is( ':hidden' ) ) {
				return;
			}
			var selectionsData = $( '#' + $this.attr( 'id' ) ).select2( 'data' );
			if ( selectionsData ) {
				var multiSelectValueArray = {};
				$( selectionsData ).each(
					function ( index, value ) {
						var getMultiSelectFieldData = AWSF.epofwMatchOptionsBasedOnCheckedValue( fieldOptions, value.id );
						if ( getMultiSelectFieldData ) {
								var fieldPriceType              = getMultiSelectFieldData[1];
								var multiSelectOptionPrice      = AWSF.getFieldPriceBasedOnPriceOptions( fieldValue, fieldPriceType, getMultiSelectFieldData[2] );
								multiSelectValueArray[value.id] = multiSelectOptionPrice;
						}
					}
				);
				var multiSelectPrice = 0;
				var multiFieldValue  = [];
				for ( var key in multiSelectValueArray ) {
					multiFieldValue.push( key );
					multiSelectPrice = parseFloat( multiSelectPrice ) + parseFloat( multiSelectValueArray[key] );
				}
				if ( multiFieldValue ) {
					fieldValue = multiFieldValue.join();
				}
				fieldPrice  = multiSelectPrice;
				trFieldName = fieldName + ' - ' + fieldValue;
				if ( 'All' === $.trim( fieldValue ) ) {
					$( '#' + fieldID + ' > option' ).prop( 'selected', 'selected' );
					$( '#' + fieldID ).trigger( 'change' );
				}
				var inputfieldName                 = $this.attr( 'name' );
				var inputfieldNameReplaceWithValue = inputfieldName.replace( '[value]', '' );
				var inputfieldNameReplaced         = inputfieldNameReplaceWithValue.replace( '[]', '' );
				if ( '' !== fieldValue ) {
					if ( $( 'tr#tr_' + inputfieldNameReplaced ).length === 0 ) {
						firstTr = AWSF.createTr( fieldValue, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
					} else {
						AWSF.changeAddonDetailsIfTrExists( inputfieldNameReplaced, trFieldName, multiSelectPrice, fieldPrice, getUniqueDivId );
					}
					var addonTotalRow    = document.getElementById( 'addon_total' );
					var addonSubtotalRow = document.getElementById( 'addon_subtotal' );
					if ( addonTotalRow && addonSubtotalRow && firstTr ) {
						addonSubtotalRow.insertAdjacentHTML( 'beforebegin', firstTr.outerHTML );
					}
				} else {
					$( 'tr#tr_' + inputfieldNameReplaced ).remove();
				}
				AWSF.calculateAddonPrice();
			}
		},
		epofwDisplayAnotherFiledsDataAndDisplay: function ( $this, qty, getUniqueDivId ) {
			if ( $this.closest( '.epofw_tr_se' ).is( ':hidden' ) ) {
				return;
			}
			var fieldType = AWSF.epofwFieldsMatchParameter( $this, 'data_inp_type', '' );
			var fieldName = $this.parent().children().attr( 'data-label-name' );
			if ( undefined === fieldName ) {
				fieldName = $this.parent().parent().children().children().attr( 'data-label-name' );
			}
			var fieldID                        = $this.attr( 'id' );
			var inputfieldName                 = $this.attr( 'name' );
			var inputfieldNameReplaceWithValue = inputfieldName.replace( '[value]', '' );
			var inputfieldNameReplaced         = inputfieldNameReplaceWithValue.replace( '[]', '' );
			var checkTr                        = $( 'tr#tr_' + inputfieldNameReplaced ).length;
			var trFieldName, firstTr, fieldOptions, fieldValue, fieldPrice, fieldPriceType, fieldPriceForAddonAttr;
			if ( 'multiselect' === fieldType ) {
				fieldOptions = AWSF.epofwFieldsMatchParameter( $this, 'options', '' );
				fieldValue   = '';
				$( '#' + $this.attr( 'id' ) ).on(
					'select2:select',
					function () {
						AWSF.epofwMultiSelectData( $this, fieldName, fieldValue, fieldType, fieldPrice, trFieldName, firstTr, fieldID, fieldOptions, qty, getUniqueDivId );
					}
				);
				$( '#' + $this.attr( 'id' ) ).on(
					'select2:unselect',
					function () {
						AWSF.epofwMultiSelectData( $this, fieldName, fieldValue, fieldType, fieldPrice, trFieldName, firstTr, fieldID, fieldOptions, qty, getUniqueDivId );
					}
				);
			} else if ( 'select' === fieldType ) {
				fieldValue       = $this.val();
				fieldOptions     = AWSF.epofwFieldsMatchParameter( $this, 'options', '' );
				var getFieldData = AWSF.epofwMatchOptionsBasedOnCheckedValue( fieldOptions, fieldValue );
				if ( getFieldData ) {
					fieldPriceType         = getFieldData[1];
					fieldPriceForAddonAttr = getFieldData[2];
					fieldPrice             = AWSF.getFieldPriceBasedOnPriceOptions( fieldValue, fieldPriceType, getFieldData[2] );
					if ( '' !== fieldValue && undefined !== fieldValue ) {
						trFieldName = fieldName + ' - ' + fieldValue;
					}
				}
				if ( '' !== fieldValue ) {
					if ( checkTr === 0 ) {
						firstTr = AWSF.createTr( fieldValue, inputfieldNameReplaced, trFieldName, fieldPrice, '', fieldType, getUniqueDivId );
					} else {
						AWSF.changeAddonDetailsIfTrExists( inputfieldNameReplaced, trFieldName, fieldPriceForAddonAttr, fieldPrice, getUniqueDivId );
					}
					var addonTotalRow    = document.getElementById( 'addon_total' );
					var addonSubtotalRow = document.getElementById( 'addon_subtotal' );
					if ( addonTotalRow && addonSubtotalRow && firstTr ) {
						addonSubtotalRow.insertAdjacentHTML( 'beforebegin', firstTr.outerHTML );
					}
				} else {
					$( 'tr#tr_' + inputfieldNameReplaced ).remove();
				}
				AWSF.calculateAddonPrice();
			}
		},
		epofwGetProductId: function () {
			var productId;
			if ( $( 'form.cart' ).hasClass( 'variations_form' ) ) {
				productId = $( 'input[name="product_id"]' ).val();
			}
			if ( $( 'form.cart' ).hasClass( 'bundle_form' ) ) {
				productId = $( 'input[name="add-to-cart"]' ).val();
			} else {
				productId = $( 'button[name="add-to-cart"]' ).val();
			}
			return productId;
		},
		epofwGetFieldsExtraAttr: function ( $this ) {
			return $this.parent().closest( '.epofw_td_value' ).attr( 'data-epofw_sa' );
		},
	};
	$(
		function () {
			AWS_Front.init();

			/**
			 * Trigger after all EPOFW frontend initialization is complete.
			 *
			 * Use this trigger to initialize custom modules that depend on EPOFW fields.
			 *
			 * @since 4.4.5
			 * @event epofw_init_complete
			 * @param {string} productId The current product ID.
			 */
			$( document.body ).trigger( 'epofw_init_complete', [ AWS_Front.epofwGetProductId() ] );
		}
	);
	window.AWSF = AWS_Front;
} )( jQuery );
