/**
 * Carticy Checkout Shield - Client-side protection script.
 *
 * Implements the double-submit cookie pattern for bot detection.
 * This script generates a token, sets it as a cookie, and ensures
 * it's submitted with checkout requests via hidden field or header.
 *
 * @package Carticy\CheckoutShield
 */
(function() {
	'use strict';

	// Get configuration from inline script.
	var config = window.carticyCheckoutShieldConfig || {
		cookieName: 'ccs_proof',
		fieldName: 'ccs_proof',
		headerName: 'X-CCS-Proof'
	};

	/**
	 * Generate a cryptographically random token.
	 * Uses crypto.getRandomValues for security.
	 *
	 * @return {string} 32-character hex token.
	 */
	function generateToken() {
		var array = new Uint8Array(16);
		crypto.getRandomValues(array);
		return Array.from(array, function(byte) {
			return byte.toString(16).padStart(2, '0');
		}).join('');
	}

	/**
	 * Set a cookie with the given name and value.
	 *
	 * @param {string} name  Cookie name.
	 * @param {string} value Cookie value.
	 */
	function setCookie(name, value) {
		var secure = location.protocol === 'https:' ? '; Secure' : '';
		// SameSite=Lax allows cross-site top-level GET navigations (PayPal returns).
		document.cookie = name + '=' + value + '; path=/; SameSite=Lax' + secure;
	}

	/**
	 * Inject hidden field into checkout form.
	 *
	 * @param {string} token The token value.
	 */
	function injectHiddenField(token) {
		// Multiple selectors for different checkout form structures.
		var selectors = [
			'form.checkout',
			'form.woocommerce-checkout',
			'form#checkout',
			'.wc-block-checkout form'
		];

		selectors.forEach(function(selector) {
			var forms = document.querySelectorAll(selector);
			forms.forEach(function(form) {
				// Check if field already exists.
				if (form.querySelector('input[name="' + config.fieldName + '"]')) {
					return;
				}

				var field = document.createElement('input');
				field.type = 'hidden';
				field.name = config.fieldName;
				field.value = token;
				form.appendChild(field);
			});
		});
	}

	/**
	 * Set up MutationObserver to handle dynamically loaded forms.
	 *
	 * @param {string} token The token value.
	 */
	function observeForForms(token) {
		if (typeof MutationObserver === 'undefined') {
			return;
		}

		var observer = new MutationObserver(function(mutations) {
			mutations.forEach(function() {
				injectHiddenField(token);
			});
		});

		observer.observe(document.body, {
			childList: true,
			subtree: true
		});
	}

	/**
	 * Set up wp.apiFetch middleware for Block Checkout.
	 *
	 * @param {string} token The token value.
	 */
	function setupApiFetchMiddleware(token) {
		// Check if wp.apiFetch is available.
		if (typeof wp === 'undefined' || !wp.apiFetch) {
			return;
		}

		wp.apiFetch.use(function(options, next) {
			// Only add header for Store API requests.
			if (options.path && options.path.indexOf('/wc/store') !== -1) {
				options.headers = options.headers || {};
				options.headers[config.headerName] = token;
			}
			return next(options);
		});
	}

	/**
	 * Initialize the checkout shield.
	 */
	function init() {
		// Generate token.
		var token = generateToken();

		// Set cookie.
		setCookie(config.cookieName, token);

		// Inject hidden field into existing forms.
		injectHiddenField(token);

		// Set up observer for dynamically loaded forms.
		observeForForms(token);

		// Set up wp.apiFetch middleware for Block Checkout.
		setupApiFetchMiddleware(token);

		// Re-inject on popular AJAX events.
		document.addEventListener('updated_checkout', function() {
			injectHiddenField(token);
		});

		// Handle jQuery trigger if available.
		if (typeof jQuery !== 'undefined') {
			jQuery(document.body).on('updated_checkout', function() {
				injectHiddenField(token);
			});
		}
	}

	// Initialize when DOM is ready.
	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', init);
	} else {
		init();
	}
})();
