( function ( $ ) {
	let payments = null;
	let walletPaymentRequest = null;
	let paymentInProgress = false;
	let initializationInProgress = false;
	let sdkLoadPromise = null;

	let alreadyInitialized = false; // Guard for initial load

	// Debounce timer
	let squareInitTimeout = null;
	const DEBOUNCE_DELAY = 300; // Increased from 20ms to 300ms for better stability

	// Cached jQuery selectors
	const $cachedSelectors = {};

	// Helper to get cached jQuery selector
	function getCached(selector) {
		if (!$cachedSelectors[selector]) {
			$cachedSelectors[selector] = $(selector);
		}
		return $cachedSelectors[selector];
	}

	// Clear cached selectors on checkout update
	function clearSelectorCache() {
		for (let key in $cachedSelectors) {
			delete $cachedSelectors[key];
		}
	}

	// We remove lastKnownTotal logic & the booleans, allowing each partial refresh to re-init

	/**
	 * Wait for Square SDK to be loaded
	 */
	function waitForSquareSDK() {
		if (sdkLoadPromise) {
			return sdkLoadPromise;
		}

		sdkLoadPromise = new Promise((resolve, reject) => {
			let attempts = 0;
			const maxAttempts = 50; // 5 seconds total wait time

			const checkSquare = () => {
				if (typeof Square !== 'undefined' && Square.payments) {
					resolve(Square);
				} else if (attempts >= maxAttempts) {
					reject(new Error('Square SDK failed to load after 5 seconds'));
				} else {
					attempts++;
					setTimeout(checkSquare, 100);
				}
			};

			checkSquare();
		});

		return sdkLoadPromise;
	}

	/**
	 * Debounces the Square init calls so multiple near-simultaneous triggers
	 * only cause a single actual initialization attempt.
	 */
	function scheduleSquareInit() {
		if ( squareInitTimeout ) {
			clearTimeout( squareInitTimeout );
		}
		squareInitTimeout = setTimeout( handleSquareInit, DEBOUNCE_DELAY );
	}

	/**
	 * Main initialization if squaresync_credit is chosen.
	 * Called after the debounce timer.
	 */
	async function handleSquareInit() {
		// Prevent concurrent initialization attempts
		if (initializationInProgress) {
			console.log('Square initialization already in progress, skipping...');
			return;
		}

		const selectedMethod = $(
			'#payment input[name="payment_method"]:checked'
		).val();
		if ( selectedMethod !== 'squaresync_credit' ) {
			return;
		}

		initializationInProgress = true;
		clearStoredTokens();

		try {
			// Wait for Square SDK to be fully loaded
			await waitForSquareSDK();
			console.log('Square SDK loaded successfully');
			// Create 'payments' once if not done yet
			if ( ! payments ) {
				const applicationId = SquareConfig.applicationId;
				const locationId = SquareConfig.locationId;

				if (!applicationId || !locationId) {
					throw new Error('Square configuration missing: applicationId or locationId');
				}

				payments = await Square.payments( applicationId, locationId );
				console.log( 'Square payments instance created:', payments );
				if ( ! payments ) {
					throw new Error( 'Square payments init failed' );
				}
			}

			const needsShipping = await checkNeedsShipping();
			const couponApplied = false;
			// Build or refresh the PaymentRequest object
			walletPaymentRequest = await initPaymentRequest(
				payments,
				needsShipping,
				couponApplied
			);

			// Show/hide card fields
			toggleCardFields();

			// Only clean and reinitialize card if it doesn't exist or is broken
			const cardContainer = document.getElementById('card-container');
			const existingCardIframe = cardContainer ? cardContainer.querySelector('.sq-card-iframe-container iframe') : null;

			if (!existingCardIframe || !window.squareCard) {
				// Card needs initialization
				forceCleanCardContainer();
				initCreditCardPayment( payments, walletPaymentRequest );
			} else {
				// Card already exists and is working, skip reinitialization
				console.log('Credit card form already initialized, keeping existing instance');
			}

			// Also forcibly remove leftover wallet buttons, then re-init
			if ( walletPaymentRequest ) {
				forceCleanWalletButtons();
				initWalletPayments(
					payments,
					walletPaymentRequest,
					needsShipping,
					couponApplied
				);
			}

			alreadyInitialized = true;
		} catch ( err ) {
			console.error( 'Square init error:', err );
			// Reset payments on error to allow retry
			if (err.message && err.message.includes('Square SDK')) {
				sdkLoadPromise = null; // Allow retry of SDK loading
			}
			logPaymentError('Payment system initialization failed. Please refresh the page.');
		} finally {
			initializationInProgress = false;
		}
	}

	/**
	 * Remove any leftover .sq-card-wrapper from partial refresh
	 * Only call this when you actually need to reinitialize the card
	 */
	function forceCleanCardContainer() {
		const $container = $( '#payment #card-container' );
		if ( $container.length ) {
			// Check if card instance exists and properly detach it
			if (window.squareCard && typeof window.squareCard.destroy === 'function') {
				try {
					window.squareCard.destroy();
					window.squareCard = null;
					console.log('Destroyed existing card instance');
				} catch (e) {
					console.warn('Error destroying card instance:', e);
				}
			}
			$container.find( '.sq-card-wrapper' ).remove();
			$container.find( '.sq-card-iframe-container' ).remove();
		}
	}

	/**
	 * Remove leftover wallet button elements
	 */
	function forceCleanWalletButtons() {
		// Clean up wallet instances if cleanup function exists
		if (typeof cleanupWalletInstances === 'function') {
			cleanupWalletInstances();
		}

		// Don't empty Google Pay if button already exists
		const googlePayExists = document.querySelector('#gpay-button-online-api-id');
		if (!googlePayExists) {
			jQuery( '#google-pay-button' ).empty();
		}

		// Don't empty Afterpay if button already exists
		const afterpayExists = document.querySelector('.sq-ap__button');
		if (!afterpayExists) {
			jQuery( '#afterpay-button' ).empty();
		}

		// Apple Pay can be safely emptied as it doesn't persist
		jQuery( '#apple-pay-button' ).empty();

		// Also re-allow initWalletPayments() if you use a guard inside it
		// e.g. `walletPaymentsInitialized = false;`
		window.walletPaymentsInitialized = false;
		walletPaymentsInitialized = false;
	}

	/**
	 * Intercept place_order if squaresync_credit is chosen, so we can tokenize.
	 */
	$( document ).on( 'click', '#place_order', function ( e ) {
		const method = $(
			'#payment input[name="payment_method"]:checked'
		).val();
		if ( method !== 'squaresync_credit' || paymentInProgress ) return;

		e.preventDefault();
		paymentInProgress = true;
		$( document.body ).trigger( 'checkout_place_order_squaresync_credit' );
	} );

	/**
	 * Actually tokenize the card, store nonce, then re-submit.
	 */
	$( document.body ).on(
		'checkout_place_order_squaresync_credit',
		async function () {
			// Clear any stale nonces before generating a new one
			clearStoredTokens();
			console.log('Starting payment processing - cleared any stale nonces');

			const success = await processCreditCardPayment(
				payments,
				walletPaymentRequest
			);
			paymentInProgress = false;
			if ( success ) {
				if ( SquareConfig.context === 'account' ) {
					$( '#add_payment_method' ).trigger( 'submit' );
				} else {
					// Handle both checkout and pay-for-order forms
					const $form = $( 'form.checkout, form#order_review' );
					if ( $form.length ) {
						$form.trigger( 'submit' );
					} else {
						console.error( 'Could not find checkout form to submit' );
					}
				}
			} else {
				console.log('Payment processing failed - nonces cleared');
				clearStoredTokens();
			}
		}
	);

	$( document.body ).on( 'wc_payment_method_selected', scheduleSquareInit );

	/**
	 * Show/hide the new card fields vs. saved tokens
	 */
	function toggleCardFields() {
		const token = $(
			'#payment input[name="wc-squaresync_credit-payment-token"]:checked'
		).val();
		if ( token && token !== 'new' ) {
			$( '#payment-form' ).hide();
			$( '.woocommerce-SavedPaymentMethods-saveNew' ).hide();
		} else {
			$( '#payment-form' ).show();
			$( '.woocommerce-SavedPaymentMethods-saveNew' ).show();
		}
	}

	// Debounced triggers from WooCommerce
	$( document.body ).on( 'updated_checkout', function(e, data) {
		// Check if this is a minor update (like coupon application)
		const isMinorUpdate = data && (data.coupon_applied || data.coupon_removed);

		if (!isMinorUpdate) {
			clearSelectorCache();
		}

		// Always schedule init but it will skip if card already exists
		scheduleSquareInit();
	});
	$( document.body ).on(
		'change',
		'#payment input[name="payment_method"]',
		function() {
			// Payment method changed, need full reinit
			clearSelectorCache();
			scheduleSquareInit();
		}
	);

	$( document ).on(
		'click',
		'#wc-squaresync_credit-payment-token-new',
		function ( e ) {
			$( '#payment-form' ).show();
			// Initialize Square when switching to new payment method
			// Only trigger on pay-for-order pages where updated_checkout doesn't fire
			const method = $('#payment input[name="payment_method"]:checked').val();
			const isPayForOrderPage = $('body').hasClass('woocommerce-order-pay');
			if (method === 'squaresync_credit' && isPayForOrderPage) {
				scheduleSquareInit();
			}
		}
	);
	$( document ).on(
		'click',
		'.woocommerce-SavedPaymentMethods-token input',
		function ( e ) {
			$( '#payment-form' ).hide();
		}
	);

	// If user picks "Use a new card," re-check
	// $(document).on('change', '#payment input[name="wc-squaresync_credit-payment-token"]', function () {
	//   toggleCardFields();
	//   const method = $('#payment input[name="payment_method"]:checked').val();
	//   if ($(this).val() === 'new' && method === 'squaresync_credit') {
	//     forceCleanCardContainer()
	//     forceCleanWalletButtons()
	//     scheduleSquareInit();
	//   }
	// });

	// On account page "Add Payment Method", do an init once
	$( document ).ready( function () {
		if ( SquareConfig.context === 'account' ) {
			$( document.body ).trigger( 'wc_payment_method_selected' );
		}

		// On pay-for-order pages, initialize Square if the payment method is already selected
		const isPayForOrderPage = $('body').hasClass('woocommerce-order-pay');
		const isSquareSelected = $('#payment_method_squaresync_credit').is(':checked');
		if ( isPayForOrderPage && isSquareSelected ) {
			scheduleSquareInit();
		}
	} );

	// On checkout_error, clear tokens and fully re-initialize card + wallets
	$( document.body ).on( 'checkout_error', function () {
		try {
			console.log('checkout_error event fired - clearing nonces and reinitializing');
			clearStoredTokens();
			// Clean existing UI/instances to avoid stale nonce or stuck state
			forceCleanCardContainer();
			forceCleanWalletButtons();
			// Re-run initialization to mount fresh instances
			scheduleSquareInit();
			paymentInProgress = false;
		} catch (e) {
			console.warn('Square re-init after checkout_error failed:', e);
		}
	} );

	// Additional handler: Reset on form submission failure (defense-in-depth for customized checkouts)
	// This catches cases where checkout_error might not fire consistently
	let formSubmissionAttempted = false;
	$( document ).on( 'submit', 'form.checkout, form#order_review', function() {
		const method = $( '#payment input[name="payment_method"]:checked' ).val();
		if ( method === 'squaresync_credit' ) {
			formSubmissionAttempted = true;
			console.log('Form submission attempted with Square payment');
		}
	} );

	// Monitor for WooCommerce error notices appearing after form submission
	const observer = new MutationObserver(function(mutations) {
		mutations.forEach(function(mutation) {
			if (mutation.addedNodes.length) {
				mutation.addedNodes.forEach(function(node) {
					// Check if error notices were added to the page
					if (node.nodeType === 1 && (
						$(node).hasClass('woocommerce-error') ||
						$(node).hasClass('woocommerce-NoticeGroup-checkout') ||
						$(node).find('.woocommerce-error').length
					)) {
						const method = $( '#payment input[name="payment_method"]:checked' ).val();
						if (formSubmissionAttempted && method === 'squaresync_credit') {
							console.log('Payment error detected via notice - clearing nonces for retry');
							clearStoredTokens();
							paymentInProgress = false;
							formSubmissionAttempted = false;
							// Card instance should remain for retry, but nonces are cleared
						}
					}
				});
			}
		});
	});

	// Start observing the checkout form area for error notices
	$( document ).ready( function() {
		const checkoutForm = document.querySelector('.woocommerce-checkout, .woocommerce-order-pay');
		if (checkoutForm) {
			observer.observe(checkoutForm, { childList: true, subtree: true });
		}

		// Clear stale nonces when page is shown from browser cache (back button)
		window.addEventListener('pageshow', function(event) {
			if (event.persisted) {
				// Page was loaded from cache (back/forward button)
				console.log('Page shown from cache - clearing any stale payment nonces');
				clearStoredTokens();
				paymentInProgress = false;
				formSubmissionAttempted = false;
			}
		});
	} );

	// Handle coupon-specific events to prevent card destruction
	$( document.body ).on( 'applied_coupon removed_coupon', function(e) {
		console.log('Coupon event detected, preserving card fields');
		// Just update payment request without destroying card
		if (payments && walletPaymentRequest) {
			checkNeedsShipping().then(needsShipping => {
				initPaymentRequest(payments, needsShipping, true).then(updatedRequest => {
					if (updatedRequest) {
						walletPaymentRequest = updatedRequest;
						console.log('Payment request updated for coupon change');
					}
				});
			});
		}
	});
} )( jQuery );
