import { __ } from '@wordpress/i18n';
import { ready } from '../../utilities/ready';
import PersonalizeWP from 'PersonalizeWP';

const pwpProductCollectionBlocks = (function (exports) {
	'use strict';

	let productCollectionBlocks = []; // Track the product collection blocks

	// Simple product cache implementation
	const productCache = new Map();
	const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes in milliseconds
	const MAX_CACHE_SIZE = 50; // Limit cache size to prevent memory issues

	// Cart quantities tracker
	const cartQuantities = new Map();

	// Constants
	const CONSTANTS = {
		ANIMATION_DURATION: 3000,
		ERROR_DURATION: 2000,
		DEFAULT_MAX_PRODUCTS: 8,
		DEFAULT_FALLBACK_MESSAGE: __('Discover our featured products', 'personalizewp'),
		LOADING_TEXT: __('Loading personalized products...', 'personalizewp'),
		ADDING_TEXT: __('Adding...', 'personalizewp'),
		ERROR_TEXT: __('Error', 'personalizewp'),
		IN_CART_TEXT: __('in cart', 'personalizewp'),
		ADD_TO_CART_TEXT: __('Add to cart', 'personalizewp'),
	};

	// Template functions for cleaner HTML generation
	const templates = {
		/**
		 * Generate product item HTML
		 */
		productItem: (product, index, totalProducts, layoutType, buttonConfig) => {
			const productClasses = templates.getProductClasses(product, index, totalProducts, layoutType, buttonConfig.typeClass);
			const saleBadge = templates.saleBadge(product);
			const productImage = templates.productImage(product);
			const ratingHtml = templates.rating(product);
			const buttonHtml = templates.button(product, buttonConfig);
			const productContext = templates.getProductContext(product);

			// For list layout, use vertical layout (image on top, content below)
			if (layoutType === 'list') {
				return `
					<li class="${productClasses}"
						data-wp-interactive="woocommerce/product-collection"
						data-wp-context="${productContext}"
						data-wp-key="product-item-${product.id}">

						<div data-block-name="woocommerce/product-image"
							data-image-sizing="thumbnail"
							data-is-descendent-of-query-loop="true"
							class="wc-block-components-product-image wc-block-grid__product-image wp-block-woocommerce-product-image">
							<a href="${product.permalink}"
								data-wp-on--click="woocommerce/product-collection::actions.viewProduct">
								${saleBadge}
								${productImage}
							</a>
						</div>

						<h3 style="margin-bottom:0.75rem;margin-top:0;"
							class="has-text-align-center wp-block-post-title has-medium-font-size">
							<a data-wp-on--click="woocommerce/product-collection::actions.viewProduct"
								href="${product.permalink}"
								target="_self">${product.name}</a>
						</h3>

						${ratingHtml}

						<div data-block-name="woocommerce/product-price"
							data-font-size="small"
							data-is-descendent-of-query-loop="true"
							data-text-align="center"
							class="wp-block-woocommerce-product-price">
							<div class="wc-block-components-product-price wc-block-grid__product-price has-text-align-center has-font-size has-small-font-size">
								${product.price_html}
							</div>
						</div>

						${buttonHtml}
					</li>
				`;
			}

			// Default grid layout
			return `
				<li class="${productClasses}"
					data-wp-interactive="woocommerce/product-collection"
					data-wp-context="${productContext}"
					data-wp-key="product-item-${product.id}">

					<div data-block-name="woocommerce/product-image"
						data-image-sizing="thumbnail"
						data-is-descendent-of-query-loop="true"
						class="wc-block-components-product-image wc-block-grid__product-image wp-block-woocommerce-product-image">
						<a href="${product.permalink}"
							data-wp-on--click="woocommerce/product-collection::actions.viewProduct">
							${saleBadge}
							${productImage}
						</a>
					</div>

					<h3 style="margin-bottom:0.75rem;margin-top:0;"
						class="has-text-align-center wp-block-post-title has-medium-font-size">
						<a data-wp-on--click="woocommerce/product-collection::actions.viewProduct"
							href="${product.permalink}"
							target="_self">${product.name}</a>
					</h3>

					${ratingHtml}

					<div data-block-name="woocommerce/product-price"
						data-font-size="small"
						data-is-descendent-of-query-loop="true"
						data-text-align="center"
						class="wp-block-woocommerce-product-price">
						<div class="wc-block-components-product-price wc-block-grid__product-price has-text-align-center has-font-size has-small-font-size">
							${product.price_html}
						</div>
					</div>

					${buttonHtml}
				</li>
			`;
		},

		/**
		 * Get product classes
		 */
		getProductClasses: (product, index, totalProducts, layoutType, productTypeClass) => {
			const classes = [
				'wc-block-product',
				`post-${product.id}`,
				'product',
				'type-product',
				'status-publish',
				product.image_url ? 'has-post-thumbnail' : '',
				'instock',
				'shipping-taxable',
				'purchasable',
				productTypeClass
			].filter(Boolean);

			if (layoutType === 'list') classes.push('pwp-list-item');
			if (index === 0) classes.push('first');
			if (index === totalProducts - 1) classes.push('last');

			return classes.join(' ');
		},

		/**
		 * Generate sale badge HTML
		 */
		saleBadge: (product) => {
			const isOnSale = product.price_html && product.price_html.includes('<del');
			if (!isOnSale) return '';

			return `
				<div class="wc-block-components-product-sale-badge wc-block-components-product-sale-badge--align-right wc-block-grid__product-onsale">
					<span aria-hidden="true">${__('Sale', 'personalizewp')}</span>
					<span class="screen-reader-text">${__('Product on sale', 'personalizewp')}</span>
				</div>
			`;
		},

		/**
		 * Generate product image HTML
		 */
		productImage: (product) => {
			const src = product.image_url || '/wp-content/uploads/woocommerce-placeholder-300x300.png';
			const className = product.image_url
				? 'attachment-woocommerce_thumbnail size-woocommerce_thumbnail'
				: 'woocommerce-placeholder wp-post-image';

			return `<img decoding="async" width="300" height="300" src="${src}" class="${className}" alt="${product.name}" data-testid="product-image" style="max-width:none;object-fit:cover;" />`;
		},

		/**
		 * Generate star rating HTML
		 */
		rating: (product) => {
			if (!product.average_rating) return '';

			const fullStars = Math.floor(product.average_rating);
			const emptyStars = 5 - fullStars;

			return `
				<div class="wc-block-components-product-rating">
					<div class="wc-block-components-product-rating__stars" aria-label="${product.average_rating} ${__('out of 5 stars', 'personalizewp')}">
						${'★'.repeat(fullStars)}${'☆'.repeat(emptyStars)}
					</div>
				</div>
			`;
		},

		/**
		 * Generate button HTML
		 */
		button: (product, buttonConfig) => {
			const buttonContext = JSON.stringify({
				quantityToAdd: 1,
				productId: product.id,
				addToCartText: buttonConfig.text,
				tempQuantity: 0,
				animationStatus: "IDLE"
			}).replace(/"/g, '&quot;');

			const buttonClass = `wp-block-button__link wp-element-button wc-block-components-product-button__button ${buttonConfig.className} ${buttonConfig.typeClass.replace('-', '_')} has-font-size has-small-font-size has-text-align-center wc-interactive`;

			if (buttonConfig.isExternal) {
				return `
					<div data-block-name="woocommerce/product-button"
						data-font-size="small"
						data-is-descendent-of-query-loop="true"
						data-text-align="center"
						class="wp-block-button wc-block-components-product-button align-center wp-block-woocommerce-product-button has-small-font-size"
						data-wp-interactive="woocommerce/product-button"
						data-wp-context="${buttonContext}"
						data-wp-init="actions.refreshCartItems">

						<a href="${product.external_url}"
							class="${buttonClass}"
							data-product_id="${product.id}"
							data-product_sku="${product.sku || ''}"
							aria-label="${buttonConfig.text}: &quot;${product.name}&quot;"
							rel="nofollow noopener"
							target="_blank">

							<span data-wp-text="state.addToCartText"
								data-wp-class--wc-block-slide-in="state.slideInAnimation"
								data-wp-class--wc-block-slide-out="state.slideOutAnimation"
								data-wp-on--animationend="actions.handleAnimationEnd"
								data-wp-watch="callbacks.startAnimation"
								data-wp-run="callbacks.syncTempQuantityOnLoad">${buttonConfig.text}</span>
						</a>
					</div>
				`;
			}

			// For variable and grouped products, link to product page
			if (product.type === 'variable' || product.type === 'grouped') {
				return `
					<div data-block-name="woocommerce/product-button"
						data-font-size="small"
						data-is-descendent-of-query-loop="true"
						data-text-align="center"
						class="wp-block-button wc-block-components-product-button align-center wp-block-woocommerce-product-button has-small-font-size">

						<a href="${product.permalink}"
							class="${buttonClass}"
							data-product_id="${product.id}"
							data-product_sku="${product.sku || ''}"
							aria-label="${buttonConfig.text}: &quot;${product.name}&quot;"
							rel="nofollow">

							<span>${buttonConfig.text}</span>
						</a>
					</div>
				`;
			}

			// For simple products, use AJAX add to cart
			return `
				<div data-block-name="woocommerce/product-button"
					data-font-size="small"
					data-is-descendent-of-query-loop="true"
					data-text-align="center"
					class="wp-block-button wc-block-components-product-button align-center wp-block-woocommerce-product-button has-small-font-size pwp-add-to-cart-button"
					data-product-id="${product.id}">

					<button type="button"
						class="${buttonClass}"
						data-product_id="${product.id}"
						data-product_sku="${product.sku || ''}"
						data-quantity="1"
						aria-label="${buttonConfig.text}: &quot;${product.name}&quot;"
						rel="nofollow">

						<span class="pwp-button-text">${buttonConfig.text}</span>
					</button>

					<span class="added_to_cart wc-forward" style="display:none;">
						<a href="/cart/" title="${__('View cart', 'personalizewp')}">${__('View cart', 'personalizewp')}</a>
					</span>
				</div>
			`;
		},

		/**
		 * Get product context for WooCommerce Interactive API
		 */
		getProductContext: (product) => {
			const context = {
				productId: product.id,
				productType: product.type || 'simple',
				productName: product.name,
				isInStock: true,
				isOnSale: product.price_html && product.price_html.includes('<del'),
				isPurchasable: true,
				hasOptions: product.type === 'variable',
				rating: product.average_rating || 0
			};
			return JSON.stringify(context).replace(/"/g, '&quot;');
		}
	};

	class PWPProductCollection extends HTMLElement {

		connectedCallback() {
			// Check if we have a blockId
			if (this.blockId) {
				// Push the element to the productCollectionBlocks array
				productCollectionBlocks.push(this);
			}
		}

		get blockId() {
			return this.getAttribute("block-id");
		}

		get recipe() {
			return this.getAttribute("recipe") || "default";
		}

		get maxProducts() {
			const max = this.getAttribute("max-products");
			return max ? parseInt(max, 10) : CONSTANTS.DEFAULT_MAX_PRODUCTS;
		}

		get fallbackBehavior() {
			return this.getAttribute("fallback-behavior") || "show_message";
		}

		get fallbackMessage() {
			return this.getAttribute("fallback-message") || CONSTANTS.DEFAULT_FALLBACK_MESSAGE;
		}

		get layoutType() {
			return this.getAttribute("layout-type") || "grid";
		}

		get gridColumns() {
			const columns = this.getAttribute("grid-columns");
			return columns ? parseInt(columns, 10) : 3;
		}

		get collectionTitle() {
			return this.getAttribute("collection-title") || "";
		}
	}

	window.customElements.define('pwp-product-collection', PWPProductCollection);

	/**
	 * Get visitor UID from PersonalizeWP
	 */
	function getVisitorUID() {
		const { pwpGet } = window.PersonalizeWP.utils;
		const user = pwpGet('tracked_user', true, 'pwp');

		return user?.id || null;
	}

	/**
	 * Fetch visitor activities using PersonalizeWP's existing REST API
	 */
	async function fetchVisitorActivities(uid, filters = {}) {
		const cacheKey = `activities_${uid}_${JSON.stringify(filters)}`;
		const cached = getCachedData(cacheKey);
		if (cached) {
			return cached;
		}

		try {
			const { callApi } = window.PersonalizeWP.utils;

			const requestBody = { uid: uid };

			// Only add filters if they exist and are not empty
			if (filters && Object.keys(filters).length > 0) {
				requestBody.filters = filters;
			}

			const result = await callApi('v1/visitor-activities', requestBody);

			// PersonalizeWP API returns { success: bool, data: array }
			const activities = result && result.success && result.data ? result.data : [];

			// Cache the result
			setCachedData(cacheKey, activities);

			return activities;
		} catch (error) {
			return [];
		}
	}

	/**
	 * Fetch visitor segments using PersonalizeWP's existing REST API
	 */
	async function fetchVisitorSegments(uid) {
		const cacheKey = `segments_${uid}`;
		const cached = getCachedData(cacheKey);
		if (cached) {
			return cached;
		}

		try {
			const { callApi } = window.PersonalizeWP.utils;

			const result = await callApi('v1/visitor-segments', { uid: uid });

			// PersonalizeWP API returns { success: bool, data: array }
			const segments = result && result.success && result.data ? result.data : [];

			// Cache the result
			setCachedData(cacheKey, segments);

			return segments;
		} catch (error) {
			return [];
		}
	}

	/**
	 * Get cached data
	 */
	function getCachedData(key) {
		const cached = productCache.get(key);
		if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
			return cached.data;
		}
		productCache.delete(key);
		return null;
	}

	/**
	 * Set cached data with size limit
	 */
	function setCachedData(key, data) {
		// Clear old cache entries if we're at the limit
		if (productCache.size >= MAX_CACHE_SIZE) {
			const oldestKey = productCache.keys().next().value;
			productCache.delete(oldestKey);
		}

		productCache.set(key, {
			data: data,
			timestamp: Date.now()
		});
	}

	/**
	 * Get previously viewed products from activities
	 */
	function getPreviouslyViewedProducts(activities, maxProducts) {
		const productIds = [];

		for (const activity of activities) {
			// Look for product view activities (activity_type: 'post')
			const isProductView = activity.activity_type === 'post' && activity.object_type === 'product';

			if (isProductView) {
				const productId = parseInt(activity.object_id);
				if (productId && !productIds.includes(productId)) {
					productIds.push(productId);
					if (productIds.length >= maxProducts) {
						break;
					}
				}
			}
		}

		return productIds;
	}

	/**
	 * Get recommended products based on visitor behavior
	 */
	async function getRecommendedProducts(activities, segments, maxProducts) {
		const viewedProducts = [];
		const purchasedProducts = [];

		// Analyze activities to understand visitor behavior
		for (const activity of activities) {
			if (activity.object_type === 'product') {
				const productId = parseInt(activity.object_id);

				if (activity.activity_type === 'post') {
					viewedProducts.push(productId);
				} else if (activity.activity_type === 'purchase') {
					purchasedProducts.push(productId);
				}
			}
		}

		// Combine viewed and purchased products, prioritizing purchased
		const candidateProducts = [
			...purchasedProducts,
			...viewedProducts.filter(id => !purchasedProducts.includes(id))
		];

		// Remove duplicates and shuffle for variety
		const uniqueProducts = [...new Set(candidateProducts)];
		const shuffled = uniqueProducts.sort(() => 0.5 - Math.random());

		return shuffled.slice(0, maxProducts);
	}

	/**
	 * Fetch product details from WooCommerce
	 */
	async function fetchProductDetails(productIds, recipe) {
		if (!productIds || productIds.length === 0) {
			return [];
		}
		const restURL = window.pwpSettings?.root || '/wp-json/';

		const cacheKey = `products_${productIds.join(',')}_${recipe}`;
		const cached = getCachedData(cacheKey);
		if (cached) {
			return cached;
		}

		try {
			// Use WooCommerce Store API for product details
			const idsParam = productIds.join(',');
			const response = await fetch(`${restURL}wc/store/v1/products?include=${idsParam}&per_page=${productIds.length}`);

			if (!response.ok) {
				throw new Error(`Failed to fetch products: ${response.status}`);
			}

			const products = await response.json();

			// Transform to our expected format
			const transformedProducts = products.map(product => ({
					id: product.id,
					name: product.name,
					permalink: product.permalink,
					excerpt: product.short_description || product.description,
					image_url: product.images && product.images.length > 0 ? product.images[0].src : null,
					price_html: product.price_html,
					average_rating: parseFloat(product.average_rating) || 0,
					rating_count: product.rating_count || 0,
					type: product.type || 'simple',
					external_url: product.external_url || '',
				button_text: product.button_text || '',
				sku: product.sku || ''
			}));

			// Cache the result
			setCachedData(cacheKey, transformedProducts);

			return transformedProducts;
		} catch (error) {
			return [];
		}
	}

	/**
	 * Generate button configuration
	 */
	function getButtonConfig(product) {
		let text = __('Add to cart', 'personalizewp');
		let className = 'add_to_cart_button ajax_add_to_cart';
		let typeClass = 'product-type-simple';
		let isExternal = false;

		if (product.type === 'external') {
			text = product.button_text || __('Buy product', 'personalizewp');
			className = 'product_type_external';
			typeClass = 'product-type-external';
			isExternal = true;
		} else if (product.type === 'variable') {
			text = __('Select options', 'personalizewp');
			className = 'product_type_variable';
			typeClass = 'product-type-variable';
		} else if (product.type === 'grouped') {
			text = __('View products', 'personalizewp');
			className = 'product_type_grouped';
			typeClass = 'product-type-grouped';
		} else if (product.price_html && product.price_html.includes('—')) {
			// Fallback check for variable products if type wasn't detected
			text = __('Select options', 'personalizewp');
			className = 'product_type_variable';
			typeClass = 'product-type-variable';
		}

		return { text, className, typeClass, isExternal };
	}

	/**
	 * Generate HTML for products
	 */
	function generateProductsHTML(products, recipe, layoutType, gridColumns, collectionTitle = '') {
		if (!products || products.length === 0) {
			return '';
		}

		const layoutClass = layoutType === 'list' ? 'pwp-layout-list' : 'pwp-layout-grid';
		const columnsClass = layoutType === 'grid' ? `columns-${gridColumns}` : 'columns-1';

		// Generate product items
		const productItems = products.map((product, index) => {
			const buttonConfig = getButtonConfig(product);
			return templates.productItem(product, index, products.length, layoutType, buttonConfig);
		}).join('');

		// Generate title HTML if provided
		const titleHTML = collectionTitle ? `
			<div class="pwp-collection-title">
				<h2 class="pwp-collection-title__heading">${collectionTitle}</h2>
			</div>
		` : '';

		// Add PersonalizeWP-specific classes alongside WooCommerce classes
		return `
			${titleHTML}
			<div class="pwp-product-collection-block pwp-layout-centered pwp-grid-responsive wp-block-woocommerce-product-collection is-layout-flow wp-block-product-collection-is-layout-flow ${layoutClass}">
				<div class="wc-block-components-notices alignwide"></div>
				<ul class="${columnsClass} wc-block-product-template__responsive wc-block-product-template wp-block-woocommerce-product-template">
					${productItems}
				</ul>
			</div>
		`;
	}

	/**
	 * Process a single product collection block
	 */
	async function processProductCollection(block) {
		const uid = getVisitorUID();

		// If no visitor UID, handle fallback
		if (!uid) {
			return handleFallback(block);
		}

		let productIds = [];

		try {
			switch (block.recipe) {
				case 'previously-viewed':
					const viewActivities = await fetchVisitorActivities(uid, {
						activity_type: 'post',
						object_type: 'product'
					});

					productIds = getPreviouslyViewedProducts(viewActivities, block.maxProducts);
					break;

				case 'products-for-you':
					// Get all activities for recommendation algorithm
					const allActivities = await fetchVisitorActivities(uid);

					// Also fetch visitor segments for enhanced recommendations
					const segments = await fetchVisitorSegments(uid);

					// Use sophisticated recommendation algorithm
					productIds = getRecommendedProducts(allActivities, segments, block.maxProducts);
					break;

				default:
					break;
			}

			// If no personalized products found, handle fallback
			if (!productIds.length) {
				const fallbackResult = handleFallback(block);
				if (fallbackResult instanceof Promise) {
					return await fallbackResult;
				}
				return fallbackResult;
			}

			// Fetch product details
			const products = await fetchProductDetails(productIds, block.recipe);

			// Generate HTML for products with layout support
			const html = generateProductsHTML(products, block.recipe, block.layoutType, block.gridColumns, block.collectionTitle);

			return html;

		} catch (error) {
			const fallbackResult = handleFallback(block);
			if (fallbackResult instanceof Promise) {
				return await fallbackResult;
			}
			return fallbackResult;
		}
	}

	/**
	 * Handle fallback behavior (following PersonalizeWP documentation standards)
	 */
	function handleFallback(block) {
		switch (block.fallbackBehavior) {
			case 'hide_block':
				return '';
			case 'show_message':
				// For show_message, only show the custom message without the title
				return `<div class="pwp-product-collection-message"><p>${block.fallbackMessage}</p></div>`;
			case 'show_all':
				return showDefaultRecommendations(block);
			default:
				// For default case, only show the custom message without the title
				return `<div class="pwp-product-collection-message"><p>${block.fallbackMessage}</p></div>`;
		}
	}

	/**
	 * Show default product recommendations when no segments are found
	 */
	async function showDefaultRecommendations(block) {
		try {
			// Fetch recent products as fallback (following documentation)
			const recentProducts = await fetchFallbackProducts(block.maxProducts);
			if (recentProducts.length > 0) {
				const html = generateProductsHTML(recentProducts, 'recent', block.layoutType, block.gridColumns, block.collectionTitle);
				return html;
			} else {
				// If no featured products, show message without title
				return `<div class="pwp-product-collection-message"><p>${block.fallbackMessage}</p></div>`;
			}
		} catch (error) {
			// On error, show fallback message without title
			return `<div class="pwp-product-collection-message"><p>${block.fallbackMessage}</p></div>`;
		}
	}

	/**
	 * Fetch recent products as fallback
	 */
	async function fetchFallbackProducts(maxProducts = 8) {
		const restURL = window.pwpSettings?.root || '/wp-json/';
		const cacheKey = `recent_products_${maxProducts}`;
		const cached = getCachedData(cacheKey);
		if (cached) {
			return cached;
		}

		try {
			// Use WooCommerce Store API to fetch recent products
			const response = await fetch(`${restURL}wc/store/v1/products?per_page=${maxProducts}&orderby=date&order=desc`);

			if (!response.ok) {
				throw new Error(`Failed to fetch recent products: ${response.status}`);
			}

			const latestProducts = await response.json();

			// Transform to our expected format
			const fallbackProducts = latestProducts.map(product => ({
				id: product.id,
				name: product.name,
				permalink: product.permalink,
				excerpt: product.short_description || product.description,
				image_url: product.images && product.images.length > 0 ? product.images[0].src : null,
				price_html: product.price_html || `$${product.prices.price}`,
				average_rating: parseFloat(product.average_rating) || 0,
				rating_count: product.rating_count || 0,
				type: product.type || 'simple',
				external_url: product.external_url || '',
				button_text: product.button_text || '',
				sku: product.sku || ''
			}));

			// Cache the result
			setCachedData(cacheKey, fallbackProducts);

			return fallbackProducts;
		} catch (error) {
			return [];
		}
	}

	/**
	 * Populate all product collection blocks
	 */
	async function populateProductCollections() {
		if (productCollectionBlocks.length === 0) {
			return;
		}

		// Initialize add to cart functionality once
		initializeAddToCart();

		// Process each block
		for (const block of productCollectionBlocks) {
			try {
				const content = await processProductCollection(block);

				if (content) {
					// Create container for the content
					const wrapper = document.createElement('div');
					wrapper.innerHTML = content;

					// Replace the custom element with the generated content
					block.replaceWith(...wrapper.childNodes);

					// Trigger custom event for this block
					const blockEvent = new CustomEvent('PWP:parseProductCollection', {
						bubbles: true,
						cancelable: true,
						detail: {
							container: block.parentNode,
							type: 'product-collection'
						},
					});
					document.dispatchEvent(blockEvent);
				} else {
					// Hide block case
					block.remove();
				}
			} catch (error) {
				// Show fallback on error
				const fallbackContent = handleFallback(block);
				if (fallbackContent) {
					const wrapper = document.createElement('div');
					wrapper.innerHTML = fallbackContent;
					block.replaceWith(...wrapper.childNodes);
				} else {
					block.remove();
				}
			}
		}

		// Clear the blocks array
		productCollectionBlocks = [];

		// Update button states after all products are loaded
		setTimeout(() => {
			updateButtonStates();
		}, 100);

		// Trigger batch completion event
		const batchEvent = new CustomEvent('PWP:parsedProductCollections', {
			bubbles: true,
			cancelable: true,
			detail: {
				count: productCollectionBlocks.length
			}
		});
		document.dispatchEvent(batchEvent);

		// Re-trigger DOMContentLoaded for other scripts
		document.dispatchEvent(new CustomEvent('DOMContentLoaded'));
	}

	/**
	 * Initialize add to cart functionality
	 */
	function initializeAddToCart() {
		// Initialize cart quantities from WooCommerce session
		initializeCartQuantities();

		// Set up a MutationObserver to watch for new buttons being added
		observeButtonChanges();

		// Add event delegation for add to cart buttons
		document.addEventListener('click', async (e) => {
			const button = e.target.closest('.pwp-add-to-cart-button button');
			if (!button) return;

			e.preventDefault();
			e.stopPropagation();

			// Disable button and show loading state
			button.disabled = true;
			const buttonText = button.querySelector('.pwp-button-text');
			const originalText = buttonText.textContent;
			buttonText.textContent = CONSTANTS.ADDING_TEXT;

			const productId = parseInt(button.getAttribute('data-product_id'));
			const quantity = parseInt(button.getAttribute('data-quantity')) || 1;

			try {
				// Add to cart via AJAX
				const ajaxURL = window.woocommerce_params?.ajax_url || '/wp-admin/admin-ajax.php';
				const response = await fetch(ajaxURL, {
					method: 'POST',
					headers: {
						'Content-Type': 'application/x-www-form-urlencoded',
					},
					body: new URLSearchParams({
						action: 'woocommerce_add_to_cart',
						product_id: productId,
						quantity: quantity,
					})
				});

				const data = await response.text();

				if (response.ok) {
					// Update cart fragments
					await updateCartFragments();

					// Update tracked quantity
					const currentQty = cartQuantities.get(productId) || 0;
					const newQty = currentQty + quantity;
					cartQuantities.set(productId, newQty);

					// Show success state with total quantity in cart
					buttonText.textContent = `${newQty} ${CONSTANTS.IN_CART_TEXT}`;

					// Show view cart link
					const viewCartLink = button.parentElement.querySelector('.added_to_cart');
					if (viewCartLink) {
						viewCartLink.style.display = 'inline-block';
						}

						// Trigger WooCommerce events
					if (typeof jQuery !== 'undefined') {
						// Trigger the event without passing the HTML data which causes the error
						jQuery(document.body).trigger('added_to_cart', [{fragments: {}}, null, jQuery(button)]);
					}

					// Reset button after delay
						setTimeout(() => {
						// Show current quantity or default text
						const qty = cartQuantities.get(productId) || 0;
						buttonText.textContent = qty > 0 ? `${qty} ${CONSTANTS.IN_CART_TEXT}` : CONSTANTS.ADD_TO_CART_TEXT;
						button.disabled = false;
					}, CONSTANTS.ANIMATION_DURATION);
				} else {
					throw new Error('Failed to add to cart');
				}
			} catch (error) {
				buttonText.textContent = CONSTANTS.ERROR_TEXT;

				setTimeout(() => {
					const qty = cartQuantities.get(productId) || 0;
					buttonText.textContent = qty > 0 ? `${qty} ${CONSTANTS.IN_CART_TEXT}` : originalText;
					button.disabled = false;
				}, CONSTANTS.ERROR_DURATION);
			}
		});

		// Handle quantity changes
		document.addEventListener('input', (e) => {
			if (e.target.matches('.pwp-add-to-cart-button input.qty')) {
				const quantity = parseInt(e.target.value) || 1;
				const button = e.target.closest('.pwp-add-to-cart-button').querySelector('button');
				if (button) {
					button.setAttribute('data-quantity', quantity);
				}
			}
		});

		// Listen for cart updates from other sources
		if (typeof jQuery !== 'undefined') {
			jQuery(document.body).on('wc_fragments_refreshed', () => {
				updateButtonStates();
			});

			jQuery(document.body).on('removed_from_cart', () => {
				initializeCartQuantities();
			});
		}
	}

	/**
	 * Initialize cart quantities from WooCommerce
	 */
	async function initializeCartQuantities() {
		try {
			// Try to get cart items from WooCommerce session
			const ajaxURL = window.woocommerce_params?.ajax_url || '/wp-admin/admin-ajax.php';
			const response = await fetch(ajaxURL, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/x-www-form-urlencoded',
				},
				body: new URLSearchParams({
					action: 'woocommerce_get_refreshed_fragments'
				})
			});

			const data = await response.json();

			if (data && data.fragments) {
				// Clear existing quantities
				cartQuantities.clear();

				// Parse cart quantities from mini cart HTML
				parseCartQuantitiesFromFragments(data.fragments);
			}

			// Update all button states
			updateButtonStates();
		} catch (error) {
			// Fallback: try to parse from existing mini cart on page
			parseCartQuantitiesFromDOM();
			updateButtonStates();
		}
	}

	/**
	 * Parse cart quantities from WooCommerce fragments
	 */
	function parseCartQuantitiesFromFragments(fragments) {
		// Look for mini cart content
		const miniCartSelectors = [
			'div.widget_shopping_cart_content',
			'.widget_shopping_cart_content',
			'.woocommerce-mini-cart',
			'ul.woocommerce-mini-cart'
		];

		for (const selector of miniCartSelectors) {
			if (fragments[selector]) {
				parseCartQuantitiesFromHTML(fragments[selector]);
				break;
			}
		}
	}

	/**
	 * Parse cart quantities from DOM (fallback)
	 */
	function parseCartQuantitiesFromDOM() {
		const miniCartSelectors = [
			'div.widget_shopping_cart_content',
			'.widget_shopping_cart_content',
			'.woocommerce-mini-cart',
			'ul.woocommerce-mini-cart'
		];

		for (const selector of miniCartSelectors) {
			const miniCart = document.querySelector(selector);
			if (miniCart) {
				parseCartQuantitiesFromHTML(miniCart.outerHTML);
				break;
			}
		}
	}

	/**
	 * Parse cart quantities from HTML string
	 */
	function parseCartQuantitiesFromHTML(html) {
		// Create a temporary div to parse the HTML
		const temp = document.createElement('div');
		temp.innerHTML = html;

		// Look for cart items with data attributes or links
		const cartItems = temp.querySelectorAll('.woocommerce-mini-cart-item, .mini_cart_item');

		cartItems.forEach(item => {
			// Try to get product ID from remove button
			const removeButton = item.querySelector('.remove_from_cart_button, .remove');
			let productId = null;

			if (removeButton) {
				productId = removeButton.getAttribute('data-product_id');
			}

			// If no product ID from remove button, try to extract from product link
			if (!productId) {
				const productLink = item.querySelector('a[href*="/product/"]');
				if (productLink) {
					const href = productLink.getAttribute('href');
					const matches = href.match(/product\/([^\/]+)/);
					if (matches) {
						// This would need product slug to ID conversion, skip for now
						return;
					}
				}
			}

			if (productId) {
				productId = parseInt(productId);

				// Extract quantity from the quantity span
				const quantitySpan = item.querySelector('.quantity');
				if (quantitySpan) {
					const quantityText = quantitySpan.textContent || quantitySpan.innerText;
					const quantityMatch = quantityText.match(/(\d+)\s*×/);
					if (quantityMatch) {
						const quantity = parseInt(quantityMatch[1]);
						cartQuantities.set(productId, quantity);
					}
				}
			}
		});
	}

	/**
	 * Update all add to cart button states
	 */
	function updateButtonStates() {
		document.querySelectorAll('.pwp-add-to-cart-button button').forEach(button => {
			const productId = parseInt(button.getAttribute('data-product_id'));
			const buttonText = button.querySelector('.pwp-button-text');

			if (buttonText && productId) {
				const qty = cartQuantities.get(productId) || 0;
				if (qty > 0) {
					buttonText.textContent = `${qty} ${CONSTANTS.IN_CART_TEXT}`;

					// Show view cart link
					const viewCartLink = button.parentElement.querySelector('.added_to_cart');
					if (viewCartLink) {
						viewCartLink.style.display = 'inline-block';
					}
				} else if (!button.disabled) {
					buttonText.textContent = CONSTANTS.ADD_TO_CART_TEXT;

					// Hide view cart link
					const viewCartLink = button.parentElement.querySelector('.added_to_cart');
					if (viewCartLink) {
						viewCartLink.style.display = 'none';
					}
				}
			}
		});
	}

	/**
	 * Update cart fragments
	 */
	async function updateCartFragments() {
		try {
			const ajaxURL = window.woocommerce_params?.ajax_url || '/wp-admin/admin-ajax.php';
			const response = await fetch(ajaxURL, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/x-www-form-urlencoded',
				},
				body: new URLSearchParams({
					action: 'woocommerce_get_refreshed_fragments'
				})
			});

			const data = await response.json();

			if (data && data.fragments) {
				// Update cart fragments
				Object.keys(data.fragments).forEach(selector => {
					const elements = document.querySelectorAll(selector);
					elements.forEach(element => {
						element.outerHTML = data.fragments[selector];
					});
				});

				// Parse updated cart quantities
				parseCartQuantitiesFromFragments(data.fragments);

				// Update cart hash if available
				if (data.cart_hash) {
					if (typeof sessionStorage !== 'undefined') {
						sessionStorage.setItem('wc_cart_hash', data.cart_hash);
					}
				}

				// Trigger fragment refresh event
				if (typeof jQuery !== 'undefined') {
					jQuery(document.body).trigger('wc_fragments_refreshed');
				}
			}
		} catch (error) {
		}
	}

	/**
	 * Observe button changes to update states when new buttons are added
	 */
	function observeButtonChanges() {
		// Create a MutationObserver to watch for new add to cart buttons
		const observer = new MutationObserver((mutations) => {
			let shouldUpdate = false;

			mutations.forEach((mutation) => {
				if (mutation.type === 'childList') {
					mutation.addedNodes.forEach((node) => {
						if (node.nodeType === Node.ELEMENT_NODE) {
							// Check if the added node contains add to cart buttons
							if (node.querySelector && node.querySelector('.pwp-add-to-cart-button button')) {
								shouldUpdate = true;
							}
							// Or if the node itself is an add to cart button
							if (node.matches && node.matches('.pwp-add-to-cart-button button')) {
								shouldUpdate = true;
							}
						}
					});
				}
			});

			if (shouldUpdate) {
				// Delay the update slightly to ensure DOM is fully updated
				setTimeout(() => {
					updateButtonStates();
				}, 50);
			}
		});

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

	/**
	 * Called automatically by PersonalizeWP after module has been initiated.
	 */
	function moduleReady() {
		populateProductCollections();
	}

	/**
	 * Called automatically once PersonalizeWP is available for loading this module.
	 */
	function readyInit() {
		// Double check
		if ( window.PersonalizeWP ) {
			PersonalizeWP.module('pwp-product-collection', this);
		}
	}

	// Export the public functions of Product Collection Blocks
	exports.ready = moduleReady;
	exports.readyInit = readyInit;

	return exports;
})({});

// Check and delay until PersonalizeWP object available.
ready(pwpProductCollectionBlocks);
