/**
 * Gift Wrapping for WooCommerce — Cart & Checkout Blocks integration (front end).
 *
 * Renders an order-level gift-wrapping control into the block cart/checkout
 * order summary via the ExperimentalOrderMeta slot. Reads live state from the
 * Store API cart "extensions" payload and pushes changes back with
 * extensionCartUpdate, which triggers WooCommerce to recalculate fees/totals.
 *
 * Written against the global wp.* / wc.* runtime — no build step required.
 *
 * Note: ExperimentalOrderMeta / extensionCartUpdate live in a code-split chunk
 * of @woocommerce/blocks-checkout that loads with the cart/checkout block, so
 * we resolve them lazily at render time rather than at script load.
 */
( function ( wp ) {
	'use strict';

	if ( ! wp || ! wp.element || ! wp.plugins || ! wp.data || ! wp.i18n ) {
		return;
	}

	var el = wp.element.createElement;
	var useState = wp.element.useState;
	var useEffect = wp.element.useEffect;
	var useRef = wp.element.useRef;
	var registerPlugin = wp.plugins.registerPlugin;
	var useSelect = wp.data.useSelect;
	var __ = wp.i18n.__;

	var NAMESPACE = 'cart-gift-wrapping';
	var cfg = ( window.wc && window.wc.wcSettings && window.wc.wcSettings.getSetting )
		? window.wc.wcSettings.getSetting( NAMESPACE + '_data', {} )
		: {};

	/**
	 * Resolve the blocks-checkout API at call time (it loads in a split chunk).
	 *
	 * @return {Object|null}
	 */
	function getCheckoutApi() {
		return ( window.wc && window.wc.blocksCheckout ) ? window.wc.blocksCheckout : null;
	}

	/**
	 * Read this plugin's slice of the Store API cart "extensions" data.
	 *
	 * @return {Object} { enabled, message, available, fee_html }
	 */
	function useWrapState() {
		return useSelect( function ( select ) {
			var store = select( 'wc/store/cart' );
			if ( ! store || ! store.getCartData ) {
				return {};
			}
			var data = store.getCartData();
			if ( data && data.extensions && data.extensions[ NAMESPACE ] ) {
				return data.extensions[ NAMESPACE ];
			}
			return {};
		}, [] );
	}

	/**
	 * Pending-update chain: extensionCartUpdate calls must not overlap. Two
	 * in-flight updates race — the earlier response can arrive last and
	 * resurrect the earlier choice (e.g. clicking "No gift wrapping" right
	 * after picking a design silently loses the click). Chaining makes each
	 * update wait for the previous one to settle, so the last click always
	 * wins on both the server and in the store.
	 */
	var updateChain = Promise.resolve();

	/**
	 * Push the current state to the server. WooCommerce recalculates the cart
	 * (and our fee) when this resolves.
	 *
	 * @param {boolean} enabled Whether wrapping is on.
	 * @param {string}  message Gift message.
	 */
	function pushUpdate( enabled, message, option ) {
		var payload = {
			namespace: NAMESPACE,
			data: {
				enabled: !! enabled,
				message: message || '',
				option: option || ''
			}
		};
		updateChain = updateChain.then( function () {
			var api = getCheckoutApi();
			if ( ! api || ! api.extensionCartUpdate ) {
				return;
			}
			return api.extensionCartUpdate( payload );
		} ).catch( function () {
			// Keep the chain alive after a failed update; the store still
			// reflects the server's last accepted state.
		} );
	}

	/**
	 * Optional info-tooltip icon (mirrors the classic-cart markup so the same
	 * CSS drives the black box / white text on hover/focus).
	 *
	 * @return {Object|null}
	 */
	function tipNode() {
		if ( ! cfg.enableTooltip || ! cfg.tooltipText ) {
			return null;
		}
		return el(
			'span',
			{
				className: 'cgwfw-tip',
				tabIndex: 0,
				role: 'img',
				'aria-label': cfg.tooltipText,
				'data-cgwfw-tip': cfg.tooltipText
			},
			'?'
		);
	}

	/**
	 * The gift-box icon circle (matches the flat-fee card).
	 *
	 * @return {Object}
	 */
	function giftIcon() {
		return el(
			'span',
			{ className: 'cgwfw-card-icon', 'aria-hidden': 'true' },
			el(
				'svg',
				{ viewBox: '0 0 24 24', width: '24', height: '24', fill: 'none', stroke: 'currentColor', strokeWidth: '1.6', strokeLinecap: 'round', strokeLinejoin: 'round' },
				el( 'polyline', { points: '20 12 20 22 4 22 4 12' } ),
				el( 'rect', { x: '2', y: '7', width: '20', height: '5' } ),
				el( 'line', { x1: '12', y1: '22', x2: '12', y2: '7' } ),
				el( 'path', { d: 'M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z' } ),
				el( 'path', { d: 'M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z' } )
			)
		);
	}

	/**
	 * Optional gift-message textarea.
	 */
	function MessageField( props ) {
		if ( ! cfg.enableMessage || ! props.visible ) {
			return null;
		}
		var attrs = {
			className: 'cgwfw-message',
			rows: 2,
			value: props.value,
			onChange: function ( e ) {
				props.onChange( e.target.value );
			},
			onBlur: function () {
				props.onCommit();
			}
		};
		if ( cfg.messageLimit > 0 ) {
			attrs.maxLength = cfg.messageLimit;
		}
		return el(
			'div',
			{ className: 'cgwfw-message-wrap' },
			el(
				'label',
				{ className: 'cgwfw-message-label' },
				cfg.messageLabel || __( 'Gift message (optional)', 'tinyplugs-gift-wrapping' ),
				el( 'textarea', attrs )
			)
		);
	}

	/**
	 * The gift-wrapping control. Card or checkbox style per the admin setting.
	 */
	function GiftWrap() {
		var state = useWrapState();
		var available = !! state.available;
		var enabled = !! state.enabled;
		var selected = state.option || '';
		var feeHtml = state.fee_html || '';

		var msgState = useState( '' );
		var message = msgState[ 0 ];
		var setMessage = msgState[ 1 ];

		// Keep the local textarea in sync with the server value unless the
		// user is mid-edit (tracked with a focus/dirty ref).
		var dirty = useRef( false );
		useEffect( function () {
			if ( ! dirty.current ) {
				setMessage( state.message || '' );
			}
		}, [ state.message ] );

		// Dropdown open/close state (used in design mode).
		var openState = useState( false );
		var open = openState[ 0 ];
		var setOpen = openState[ 1 ];
		var ddRef = useRef( null );
		useEffect( function () {
			function onDoc( e ) {
				if ( ddRef.current && ! ddRef.current.contains( e.target ) ) {
					setOpen( false );
				}
			}
			document.addEventListener( 'mousedown', onDoc );
			return function () {
				document.removeEventListener( 'mousedown', onDoc );
			};
		}, [] );

		if ( ! available ) {
			return null;
		}

		var onMessageChange = function ( val ) {
			dirty.current = true;
			setMessage( val );
		};
		var commitMessage = function () {
			dirty.current = false;
			if ( enabled ) {
				pushUpdate( true, message, selected );
			}
		};
		var toggle = function ( next ) {
			pushUpdate( next, next ? message : '', '' );
		};

		// ---- Design dropdown (multi-design mode, Pro) ------------------------
		

		var feeNode = feeHtml
			? el( 'span', { className: 'cgwfw-card-price', dangerouslySetInnerHTML: { __html: feeHtml } } )
			: null;

		// ---- Checkbox style -------------------------------------------------
		if ( 'card' !== cfg.style ) {
			return el(
				'div',
				{ className: 'cgwfw-wrap cgwfw-order cgwfw-blocks' + ( enabled ? ' is-wrapped' : '' ) },
				el(
					'label',
					{ className: 'cgwfw-order-toggle' },
					el( 'input', {
						type: 'checkbox',
						className: 'cgwfw-order-check',
						checked: enabled,
						onChange: function ( e ) {
							toggle( e.target.checked );
						}
					} ),
					el( 'span', null, cfg.orderLabel || __( 'Add gift wrapping to my order', 'tinyplugs-gift-wrapping' ) ),
					feeHtml ? el( 'span', { className: 'cgwfw-btn-fee', dangerouslySetInnerHTML: { __html: '(' + feeHtml + ')' } } ) : null
				),
				tipNode(),
				el( MessageField, {
					visible: enabled,
					value: message,
					onChange: onMessageChange,
					onCommit: commitMessage
				} )
			);
		}

		// ---- Card style -----------------------------------------------------
		var btnLabel = enabled
			? ( cfg.addedLabel || __( 'Added', 'tinyplugs-gift-wrapping' ) )
			: ( cfg.addLabel || __( 'Add', 'tinyplugs-gift-wrapping' ) );

		return el(
			'div',
			{ className: 'cgwfw-wrap cgwfw-card cgwfw-order cgwfw-blocks' + ( enabled ? ' is-wrapped' : '' ) },
			el(
				'div',
				{ className: 'cgwfw-card-main' },
				el(
					'span',
					{ className: 'cgwfw-card-icon', 'aria-hidden': 'true' },
					el(
						'svg',
						{
							viewBox: '0 0 24 24',
							width: '32',
							height: '32',
							fill: 'none',
							stroke: 'currentColor',
							strokeWidth: '1.6',
							strokeLinecap: 'round',
							strokeLinejoin: 'round'
						},
						el( 'polyline', { points: '20 12 20 22 4 22 4 12' } ),
						el( 'rect', { x: '2', y: '7', width: '20', height: '5' } ),
						el( 'line', { x1: '12', y1: '22', x2: '12', y2: '7' } ),
						el( 'path', { d: 'M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z' } ),
						el( 'path', { d: 'M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z' } )
					)
				),
				el(
					'div',
					{ className: 'cgwfw-card-body' },
					el( 'div', { className: 'cgwfw-card-title' }, cfg.orderLabel || __( 'Add gift wrapping to my order', 'tinyplugs-gift-wrapping' ), tipNode() ),
					cfg.subtitle ? el( 'div', { className: 'cgwfw-card-sub' }, cfg.subtitle ) : null,
					feeNode
				),
				el(
					'button',
					{
						type: 'button',
						className: 'cgwfw-btn cgwfw-card-btn' + ( enabled ? ' is-wrapped' : '' ),
						'aria-pressed': enabled ? 'true' : 'false',
						onClick: function () {
							toggle( ! enabled );
						}
					},
					el( 'span', { className: 'cgwfw-btn-label' }, btnLabel )
				)
			),
			el( MessageField, {
				visible: enabled,
				value: message,
				onChange: onMessageChange,
				onCommit: commitMessage
			} )
		);
	}

	/**
	 * Render into the order-summary slot, resolving the slot component lazily.
	 */
	function render() {
		// The block cart/checkout only offers the order-level option, so it is
		// shown in per-order mode only. Per-item wrapping is a classic-cart
		// feature (the block cart has no per-line-item control slot).
		if ( 'per_order' !== cfg.mode ) {
			return null;
		}
		// Honour the "show on" setting. The ExperimentalOrderMeta slot renders in
		// both the cart and checkout blocks, so distinguish them by the page body
		// class (the Cart block lives on the cart page, the Checkout block on the
		// checkout page).
		var showOn = cfg.showOn || 'both';
		if ( 'both' !== showOn && document.body ) {
			var onCheckout = document.body.classList.contains( 'woocommerce-checkout' );
			var onCart = document.body.classList.contains( 'woocommerce-cart' );
			if ( 'checkout' === showOn && ! onCheckout ) {
				return null;
			}
			if ( 'cart' === showOn && ( onCheckout || ! onCart ) ) {
				return null;
			}
		}
		var api = getCheckoutApi();
		if ( ! api || ! api.ExperimentalOrderMeta ) {
			return null;
		}
		return el( api.ExperimentalOrderMeta, null, el( GiftWrap ) );
	}

	registerPlugin( 'cgwfw-gift-wrapping', {
		render: render,
		scope: 'woocommerce-checkout'
	} );
} )( window.wp );
