/**
 * Elementor split checkout widgets — form binding + submit fix.
 *
 * Problems this file solves:
 *
 * 1) SCRIPT NOT LOADING: When the checkout page uses Elementor widgets instead of
 *    the [woocommerce_checkout] shortcode, WooCommerce never enqueues wc-checkout.js,
 *    so wc_checkout_form never exists and no submit handler is bound.
 *    Fixed in PHP (class-storzen-init.php :: enqueue_checkout_scripts).
 *
 * 2) NOVALIDATE MISSING: form#szp-checkout lacks novalidate, so browser HTML5
 *    validation silently blocks submit on empty required fields.
 *
 * 3) ORPHAN FIELDS: Elementor wraps each widget in a container div. The browser
 *    auto-closes <form> at the end of the first container, so #order_review / #payment
 *    (nonce, payment_method, terms) are outside form#szp-checkout. WC serialize()
 *    misses them — the server rejects the POST silently.
 *    Fixed via HTML5 form="" attribute on those controls.
 *
 * 4) WC HANDLERS ON WRONG FORM: checkout.js binds to $('form.checkout').first() at
 *    DOMContentLoaded. If Elementor renders the form late the handlers miss it.
 *    Fixed by migrating wc_checkout_form.$checkout_form to form#szp-checkout.
 */
( function ( $ ) {
	'use strict';

	var WCP_FORM_ID    = 'szp-checkout';
	var patchedGetForm = false;

	// ── Helpers ───────────────────────────────────────────────────────────────

	function wcpEnsureNovalidate() {
		var formEl = document.getElementById( WCP_FORM_ID );
		if ( formEl && ! formEl.getAttribute( 'novalidate' ) ) {
			formEl.setAttribute( 'novalidate', 'novalidate' );
		}
	}

	function wcpAssociateOrphanCheckoutFields() {
		var formEl = document.getElementById( WCP_FORM_ID );
		if ( ! formEl ) {
			return;
		}
		$( '#order_review, #payment' )
			.find( 'input, select, textarea, button' )
			.each( function () {
				if ( $.contains( formEl, this ) ) {
					return;
				}
				if ( ! this.getAttribute( 'form' ) ) {
					this.setAttribute( 'form', WCP_FORM_ID );
				}
			} );
	}

	function wcpPatchCustomPlaceOrderGetForm( $wcp ) {
		if (
			patchedGetForm ||
			typeof wc === 'undefined' ||
			! wc.customPlaceOrderButton ||
			typeof wc.customPlaceOrderButton.__getForm !== 'function'
		) {
			return;
		}
		var original = wc.customPlaceOrderButton.__getForm;
		wc.customPlaceOrderButton.__getForm = function () {
			if ( $( '#' + WCP_FORM_ID ).length ) {
				return $( '#' + WCP_FORM_ID ).first();
			}
			return original.call( this );
		};
		patchedGetForm = true;
	}

	// ── WC checkout form handler migration ────────────────────────────────────

	function wcpOffWcCheckoutFormHandlers( $form ) {
		if ( ! $form || ! $form.length ) { return; }
		$form.off( 'click',   'input[name="payment_method"]', wc_checkout_form.payment_method_selected );
		$form.off( 'submit',  wc_checkout_form.submit );
		$form.off( 'input validate change focusout', '.input-text, select, input:checkbox', wc_checkout_form.validate_field );
		$form.off( 'update',  wc_checkout_form.trigger_update_checkout );
		$form.off( 'change',  'select.shipping_method, input[name^="shipping_method"], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type="radio"], .update_totals_on_change input[type="checkbox"]', wc_checkout_form.trigger_update_checkout );
		$form.off( 'change',  '.address-field select', wc_checkout_form.input_changed );
		$form.off( 'change',  '.address-field input.input-text, .update_totals_on_change input.input-text', wc_checkout_form.maybe_input_changed );
		$form.off( 'keydown', '.address-field input.input-text, .update_totals_on_change input.input-text', wc_checkout_form.queue_update_checkout );
		$form.off( 'blur',    '#billing_address_1, #shipping_address_1', wc_checkout_form.address_field_blur );
		$form.off( 'change',  '#ship-to-different-address input', wc_checkout_form.ship_to_different_address );
	}

	function wcpOnWcCheckoutFormHandlers( $form ) {
		$form.attr( 'novalidate', 'novalidate' );
		$form.on( 'click',   'input[name="payment_method"]', wc_checkout_form.payment_method_selected );
		$form.on( 'submit',  wc_checkout_form.submit );
		$form.on( 'input validate change focusout', '.input-text, select, input:checkbox', wc_checkout_form.validate_field );
		$form.on( 'update',  wc_checkout_form.trigger_update_checkout );
		$form.on( 'change',  'select.shipping_method, input[name^="shipping_method"], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type="radio"], .update_totals_on_change input[type="checkbox"]', wc_checkout_form.trigger_update_checkout );
		$form.on( 'change',  '.address-field select', wc_checkout_form.input_changed );
		$form.on( 'change',  '.address-field input.input-text, .update_totals_on_change input.input-text', wc_checkout_form.maybe_input_changed );
		$form.on( 'keydown', '.address-field input.input-text, .update_totals_on_change input.input-text', wc_checkout_form.queue_update_checkout );
		$form.on( 'blur',    '#billing_address_1, #shipping_address_1', wc_checkout_form.address_field_blur );
		$form.on( 'change',  '#ship-to-different-address input', wc_checkout_form.ship_to_different_address );
		$form.find( '#ship-to-different-address input' ).trigger( 'change' );
		if ( typeof wc_checkout_form.init_payment_methods === 'function' ) {
			wc_checkout_form.init_payment_methods();
		}
		// Additional handler: sync billing to shipping when billing address changes
		// and user is not shipping to a different address
		$form.on( 'change blur', 'input[id^="billing_"], select[id^="billing_"]', function() {
			wcpSyncBillingToShipping();
		} );
	}

	function wcpRepairCheckoutFormHandlers() {
		wcpEnsureNovalidate();

		if ( typeof wc_checkout_form === 'undefined' || typeof wc_checkout_params === 'undefined' ) {
			return; // AJAX fallback handles submit in this case
		}
		if ( $( document.body ).hasClass( 'woocommerce-order-pay' ) ) {
			return;
		}

		var $wcp    = $( '#' + WCP_FORM_ID );
		var $target = $wcp.length ? $wcp : $( 'form.checkout' );
		if ( ! $target.length ) { return; }

		if ( $wcp.length ) { wcpPatchCustomPlaceOrderGetForm( $wcp ); }

		var $current = wc_checkout_form.$checkout_form;
		if ( $current && $current.length && $current[ 0 ] === $target[ 0 ] ) {
			return; // already correct
		}

		if ( $current && $current.length ) { wcpOffWcCheckoutFormHandlers( $current ); }
		wc_checkout_form.$checkout_form = $target;
		wc_checkout_form.$order_review  = $( '#order_review' );
		wcpOnWcCheckoutFormHandlers( $target );
	}

	// ── AJAX submit fallback ──────────────────────────────────────────────────
	// Used when wc_checkout_form is unavailable.

	var wcpFallbackBound = false;

	function wcpMaybeFallbackSubmit() {
		if ( typeof wc_checkout_form !== 'undefined' ) {
			if ( wcpFallbackBound ) {
				$( '#' + WCP_FORM_ID ).off( 'submit.wcpFallback' );
				wcpFallbackBound = false;
			}
			return;
		}

		var $form = $( '#' + WCP_FORM_ID );
		if ( ! $form.length || wcpFallbackBound ) { return; }

		wcpFallbackBound = true;

		$form.on( 'submit.wcpFallback', function ( e ) {
			e.preventDefault();
			e.stopPropagation();

			// Hand off to WC if it appeared by now.
			if ( typeof wc_checkout_form !== 'undefined' && typeof wc_checkout_form.submit === 'function' ) {
				$form.off( 'submit.wcpFallback' );
				wcpFallbackBound = false;
				wcpRepairCheckoutFormHandlers();
				$form.trigger( 'submit' );
				return;
			}

			if ( $form.is( '.processing' ) ) { return; }

			if ( typeof $.fn.block !== 'undefined' ) {
				$form.addClass( 'processing' ).block( { message: null, overlayCSS: { background: '#fff', opacity: 0.6 } } );
			}

			// Serialize form fields plus any orphaned fields with form="szp-checkout".
			var formData = $form.serialize();
			$( '[form="' + WCP_FORM_ID + '"]' ).each( function () {
				if ( ! $.contains( $form[ 0 ], this ) ) {
					var name = $( this ).attr( 'name' );
					var val  = $( this ).val();
					if ( name && val !== undefined ) {
						formData += '&' + encodeURIComponent( name ) + '=' + encodeURIComponent( val );
					}
				}
			} );

			var ajaxUrl = ( typeof wc_checkout_params !== 'undefined' && wc_checkout_params.checkout_url )
				? wc_checkout_params.checkout_url
				: $form.attr( 'action' );

			$.ajax( {
				type:    'POST',
				url:     ajaxUrl,
				data:    formData,
				success: function ( result ) {
					if ( typeof $.fn.unblock !== 'undefined' ) {
						$form.removeClass( 'processing' ).unblock();
					}
					try {
						if ( typeof result === 'string' ) { result = JSON.parse( result ); }
					} catch ( ex ) {
						$( document.body ).trigger( 'checkout_error', [ result ] );
						return;
					}
					if ( result.result === 'success' ) {
						window.location.href = result.redirect;
					} else if ( result.result === 'failure' ) {
						$( document.body ).trigger( 'checkout_error', [ result.messages ] );
						if ( result.messages ) {
							var $notices = $( '.woocommerce-notices-wrapper, .woocommerce-error' ).first();
							if ( ! $notices.length ) { $notices = $form; }
							$notices.prepend( result.messages );
							$( 'html, body' ).animate( { scrollTop: $notices.offset().top - 100 }, 400 );
						}
						if ( result.refresh ) { $( document.body ).trigger( 'update_checkout' ); }
					}
				},
				error: function () {
					if ( typeof $.fn.unblock !== 'undefined' ) {
						$form.removeClass( 'processing' ).unblock();
					}
					$( document.body ).trigger( 'checkout_error' );
				}
			} );
		} );
	}

	// ── Checkout coupon toggle (capture phase) ───────────────────────────────
	// WooCommerce binds a.showcoupon on document.body in the bubble phase. Elementor
	// themes or script order can prevent that handler from running or double-toggle.
	// One capture listener runs first, toggles #woocommerce-checkout-form-coupon, and
	// stops other handlers so the field reliably opens.

	var wcpCouponToggleCaptureBound = false;

	function wcpCheckoutCouponClickCapture( e ) {
		var t = e.target;
		if ( t && t.nodeType !== 1 && t.parentElement ) {
			t = t.parentElement;
		}
		if ( ! t || ! t.closest ) {
			return;
		}
		var a = t.closest( 'a.showcoupon' );
		if ( ! a || ! a.closest( '.woocommerce-form-coupon-toggle' ) ) {
			return;
		}
		var couponForm = document.getElementById( 'woocommerce-checkout-form-coupon' );
		if ( ! couponForm || ! couponForm.classList.contains( 'checkout_coupon' ) ) {
			return;
		}
		e.preventDefault();
		e.stopImmediatePropagation();
		e.stopPropagation();

		var $couponForm = $( couponForm );
		$couponForm.slideToggle( 400, function () {
			var visible = $couponForm.is( ':visible' );
			a.setAttribute( 'aria-expanded', visible ? 'true' : 'false' );
			if ( visible ) {
				$couponForm.find( ':input:visible:eq(0)' ).trigger( 'focus' );
			}
		} );
	}

	function wcpBindCheckoutCouponToggle() {
		if ( wcpCouponToggleCaptureBound ) {
			return;
		}
		// PHP widget printed an inline capture handler (e.g. Elementor preview where wc-checkout did not load).
		if ( typeof window.__szpCouponInlineBound !== 'undefined' && window.__szpCouponInlineBound ) {
			wcpCouponToggleCaptureBound = true;
			return;
		}
		if ( ! document.getElementById( 'woocommerce-checkout-form-coupon' ) ) {
			return;
		}
		wcpCouponToggleCaptureBound = true;
		document.addEventListener( 'click', wcpCheckoutCouponClickCapture, true );
	}

	// ── Main ──────────────────────────────────────────────────────────────────

	// ── Force initial shipping calculation ───────────────────────────────────
	// When checkout form loads with Elementor widgets, trigger update_checkout to
	// ensure shipping methods are calculated based on the entered billing address.

	var wcpInitialUpdateTriggered = false;

	function wcpSyncBillingToShipping() {
		// When "ship to different address" is not checked, ensure shipping fields
		// are populated with billing values so WooCommerce can calculate shipping.
		var $shipToDifferent = $( '#ship-to-different-address input' );
		if ( ! $shipToDifferent.length || ! $shipToDifferent.is( ':checked' ) ) {
			var billingFields = [
				'first_name', 'last_name', 'company', 'country', 
				'address_1', 'address_2', 'city', 'state', 'postcode'
			];
			$.each( billingFields, function( index, field ) {
				var $billing = $( '#billing_' + field );
				var $shipping = $( '#shipping_' + field );
				if ( $billing.length && $shipping.length && $billing.val() ) {
					if ( $shipping.val() !== $billing.val() ) {
						$shipping.val( $billing.val() ).trigger( 'change' );
					}
				}
			} );
		}
	}

	function wcpTriggerInitialCheckoutUpdate() {
		if ( wcpInitialUpdateTriggered ) {
			return;
		}
		if ( typeof wc_checkout_form === 'undefined' || ! wc_checkout_form.$checkout_form ) {
			return;
		}
		var $form = $( '#' + WCP_FORM_ID );
		if ( ! $form.length ) {
			return;
		}
		// Sync billing address to shipping address if not shipping to different address
		wcpSyncBillingToShipping();
		
		// Check if billing address fields have values (indicating a returning customer or saved address)
		var hasBillingAddress = $( '#billing_address_1' ).val() || $( '#billing_country' ).val();
		if ( hasBillingAddress ) {
			wcpInitialUpdateTriggered = true;
			// Small delay to ensure all fields are synced before triggering update
			setTimeout( function() {
				$( document.body ).trigger( 'update_checkout' );
			}, 200 );
		}
	}

	function wcpRunElementorCheckoutFixes() {
		wcpAssociateOrphanCheckoutFields();
		wcpRepairCheckoutFormHandlers();
		wcpMaybeFallbackSubmit();
		wcpBindCheckoutCouponToggle();
		wcpTriggerInitialCheckoutUpdate();
	}

	$( wcpRunElementorCheckoutFixes );
	$( window ).on( 'load', wcpRunElementorCheckoutFixes );
	setTimeout( wcpRunElementorCheckoutFixes, 100 );
	setTimeout( wcpRunElementorCheckoutFixes, 400 );
	setTimeout( wcpRunElementorCheckoutFixes, 1000 );
	setTimeout( wcpRunElementorCheckoutFixes, 2500 );

	$( document.body ).on( 'updated_checkout', function () {
		wcpAssociateOrphanCheckoutFields();
		wcpRepairCheckoutFormHandlers();
		wcpMaybeFallbackSubmit();
		wcpBindCheckoutCouponToggle();
		wcpEnsureNovalidate();
	} );

} )( jQuery );
