/* Tinyplugs Gift Wrapping for WooCommerce – Cart & Checkout — front-end behaviour (no full reload) */
( function ( $ ) {
	'use strict';

	var debounceTimers = {};

	// The Cart & Checkout Blocks render their own React-driven controls (inside
	// a .cgwfw-blocks wrapper) that reuse these CSS classes. cgwfw-blocks.js
	// owns those; touching their DOM from here desyncs React (dead dropdowns,
	// stuck lightboxes) and fires bogus AJAX toggles, so every classic handler
	// must ignore them. React can unmount the clicked control mid-dispatch
	// (picking a design closes the panel), so by the time this delegated
	// handler runs the node may be detached and its .cgwfw-blocks ancestor
	// gone with it — a node no longer in the document is treated as
	// blocks-owned too (classic markup stays attached during its handlers).
	function inBlocks( el ) {
		return ! document.documentElement.contains( el ) || $( el ).closest( '.cgwfw-blocks' ).length > 0;
	}

	function send( $wrap, wrap, message, $btn, option ) {
		var key = $wrap.data( 'key' );

		// No key means no classic wrap context (e.g. a stray call for a
		// blocks-rendered control) — posting would only earn a server
		// rejection and a pointless recovery reload.
		if ( ! key ) {
			return;
		}

		if ( $btn ) {
			$btn.addClass( 'cgwfw-loading' );
		}

		// The controls update optimistically before this request. If the server
		// rejects it (success:false) or the request fails (expired session/nonce,
		// network), the UI no longer matches reality — reload so the page
		// re-renders the true wrap state, fee and a fresh nonce.
		function recover() {
			window.location.reload();
		}

		$.post(
			cgwfwData.ajaxUrl,
			{
				action: 'cgwfw_toggle',
				nonce: cgwfwData.nonce,
				key: key,
				wrap: wrap ? 'true' : 'false',
				message: message || '',
				option: option || ''
			},
			function ( response ) {
				if ( $btn ) {
					$btn.removeClass( 'cgwfw-loading' );
				}
				if ( response && response.success && response.data.fragments ) {
					$.each( response.data.fragments, function ( selector, html ) {
						$( selector ).replaceWith( html );
					} );
					// Cart page: refresh totals. Checkout page: let WooCommerce
					// re-fetch the order review so the fee updates there too.
					$( document.body ).trigger( 'updated_cart_totals' );
					$( document.body ).trigger( 'update_checkout' );
				} else {
					recover();
				}
			}
		).fail( function () {
			if ( $btn ) {
				$btn.removeClass( 'cgwfw-loading' );
			}
			recover();
		} );
	}

	// Per-item button toggle.
	$( document ).on( 'click', '.cgwfw-btn', function ( e ) {
		if ( inBlocks( this ) ) {
			return;
		}
		e.preventDefault();
		var $btn = $( this );
		var $wrap = $btn.closest( '.cgwfw-wrap' );
		var nowWrapped = ! $btn.hasClass( 'is-wrapped' );

		$btn.toggleClass( 'is-wrapped', nowWrapped );
		$wrap.toggleClass( 'is-wrapped', nowWrapped );
		$btn.attr( 'aria-pressed', nowWrapped ? 'true' : 'false' );
		// Prefer per-button labels (data-*), fall back to the localized defaults.
		var label = $btn.data( 'label' ) || cgwfwData.label;
		var labelAdded = $btn.data( 'labelAdded' ) || cgwfwData.labelAdded;
		$btn.find( '.cgwfw-btn-label' ).text(
			nowWrapped ? labelAdded : label
		);

		var $msgWrap = $wrap.find( '.cgwfw-message-wrap' );
		if ( nowWrapped ) {
			$msgWrap.show();
		} else {
			$msgWrap.hide();
		}

		var message = $wrap.find( '.cgwfw-message' ).val();
		send( $wrap, nowWrapped, message, $btn );
	} );

	

	// Checkbox-style toggles: per-order checkbox and per-item switch box.
	$( document ).on( 'change', '.cgwfw-order-check, .cgwfw-switch-check', function () {
		if ( inBlocks( this ) ) {
			return;
		}
		var $check = $( this );
		var $wrap = $check.closest( '.cgwfw-wrap' );
		var nowWrapped = $check.is( ':checked' );
		var $msgWrap = $wrap.find( '.cgwfw-message-wrap' );

		$wrap.toggleClass( 'is-wrapped', nowWrapped );

		if ( nowWrapped ) {
			$msgWrap.show();
		} else {
			$msgWrap.hide();
		}

		var message = $wrap.find( '.cgwfw-message' ).val();
		send( $wrap, nowWrapped, message );
	} );

	// Debounced save when typing a gift message (only if already wrapped).
	$( document ).on( 'input', '.cgwfw-message', function () {
		if ( inBlocks( this ) ) {
			return;
		}
		var $field = $( this );
		var $wrap = $field.closest( '.cgwfw-wrap' );
		var key = $wrap.data( 'key' );
		var isWrapped =
			$wrap.find( '.cgwfw-btn' ).hasClass( 'is-wrapped' ) ||
			$wrap.find( '.cgwfw-order-check' ).is( ':checked' ) ||
			$wrap.hasClass( 'is-wrapped' );

		if ( ! isWrapped ) {
			return;
		}

		var option = $wrap.find( '.cgwfw-dd-option.is-selected, .cgwfw-lb-option.is-selected' ).data( 'option' ) || '';

		clearTimeout( debounceTimers[ key ] );
		debounceTimers[ key ] = setTimeout( function () {
			send( $wrap, true, $field.val(), null, String( option ) );
		}, 600 );
	} );
} )( jQuery );
