/* global ShoptimizerLoadMore */
document.addEventListener( 'DOMContentLoaded', function () {
	// Consolidate multiple product grids into one (scoped to .site-main only)
	var grids = document.querySelectorAll( '.site-main .products' );
	if ( grids.length > 1 ) {
		var mainGrid = grids[0];
		for ( var i = 1; i < grids.length; i++ ) {
			var products = grids[i].querySelectorAll( '.product' );
			products.forEach( function( product ) {
				mainGrid.appendChild( product );
			} );
			grids[i].remove();
		}
	}

	var button = document.getElementById( 'shoptimizer-load-more-btn' );
	var spinner = document.querySelector( '.site-main .load-more-spinner' );
	var grid = document.querySelector( '.site-main .products' );
	var statusText = document.querySelector( '.site-main .viewed-count' );
	var statusWrap = document.querySelector( '.site-main .load-more-status' );
	var progress = document.querySelector('.site-main .load-more-progress');
	var progressBar = document.querySelector('.site-main .load-more-progress-bar');

	if ( ! grid || ! ShoptimizerLoadMore ) {
		return;
	}

	var currentPage = parseInt( ShoptimizerLoadMore.current_page, 10 );
	var maxPages = parseInt( ShoptimizerLoadMore.max_pages, 10 );
	var queryVars = ShoptimizerLoadMore.query_vars;
	var orderBy = ShoptimizerLoadMore.orderby;
	var resultText = ShoptimizerLoadMore.result_text;
	var resultTotal = parseInt( ShoptimizerLoadMore.result_total, 10 );
	var resultLimit = parseInt( ShoptimizerLoadMore.result_limit, 10 );
	var firstPage = parseInt( ShoptimizerLoadMore.first_page, 10 );
	var loading = false;
	var retryCount = 0;
	var maxRetries = 3;
	var currentRequest = null;

	updateViewedCount();
	updateResultCount();

	if ( button ) {
		grid.setAttribute( 'aria-busy', 'false' );
		grid.setAttribute( 'aria-live', 'polite' );
		button.addEventListener( 'click', function () {
			if ( loading ) {
				return;
			}
			if ( currentPage >= maxPages ) {
				return;
			}
			if ( retryCount >= maxRetries ) {
				return;
			}
			loading = true;
			spinner.style.display = 'inline';
			button.style.display = 'none';
			loadNextPage();
		} );
	}

	function loadNextPage() {
		currentPage++;

		var formData = new FormData();
		formData.append( 'action', 'shoptimizer_load_more' );
		formData.append( 'nonce', ShoptimizerLoadMore.nonce );
		formData.append( 'page', currentPage );
		formData.append( 'query', queryVars );
		formData.append( 'orderby', orderBy );
		formData.append( 'limit', resultLimit );

		grid.setAttribute( 'aria-busy', 'true' );

		// Create AbortController for race condition prevention
		if ( currentRequest ) {
			currentRequest.abort();
		}
		var controller = new AbortController();
		currentRequest = controller;

		fetch( ShoptimizerLoadMore.ajax_url, {
			method: 'POST',
			credentials: 'same-origin',
			body: formData,
			signal: controller.signal
		} )
		.then( function ( response ) {
			// Validate HTTP response status
			if ( ! response.ok ) {
				throw new Error( 'HTTP ' + response.status );
			}
			return response.text();
		} )
		.then( function ( html ) {
			var temp = document.createElement( 'div' );
			temp.innerHTML = html;

			var products = temp.querySelectorAll( '.product' );

			// Handle empty product response
			if ( products.length === 0 ) {
				// No products returned, just hide the button
				hideLoadMoreUI();
				grid.setAttribute( 'aria-busy', 'false' );
				loading = false;
				spinner.style.display = 'none';
				currentRequest = null;
				return;
			}

			var firstNewProduct = null;
			for ( var i = 0; i < products.length; i++ ) {
				if ( i === 0 ) {
					firstNewProduct = products[ i ];
				}
				grid.appendChild( products[ i ] );
			}
			grid.setAttribute( 'aria-busy', 'false' );

			updateViewedCount();
			focusFirstNewProduct( firstNewProduct );

			spinner.style.display = 'none';
			loading = false;
			retryCount = 0; // Reset retry count on success
			currentRequest = null;

			if ( currentPage < maxPages ) {
				button.style.display = 'inline';
			} else {
				hideLoadMoreUI();
			}
			var pageURL = getPageURLByFormat( currentPage );
			if ( pageURL ) {
				pageURL = setFpageParam( pageURL, firstPage );
				history.replaceState( null, '', pageURL );
			}

			updateResultCount();
		} )
		.catch( function ( error ) {
			// Comprehensive error handling
			console.error( 'Load More Error:', error );

			// Don't show error for aborted requests
			if ( error.name === 'AbortError' ) {
				return;
			}

			grid.setAttribute( 'aria-busy', 'false' );
			spinner.style.display = 'none';
			loading = false;
			currentPage--; // Rollback page increment
			currentRequest = null;

			retryCount++;

			if ( retryCount < maxRetries ) {
				// Allow retry
				button.style.display = 'inline';
				showErrorMessage( ShoptimizerLoadMore.i18n.error_message );
			} else {
				// Max retries reached, disable button
				hideLoadMoreUI();
				showErrorMessage( ShoptimizerLoadMore.i18n.error_message );
			}
		} );
	}

	function showErrorMessage( message ) {
		// Create error message element if it doesn't exist
		var errorEl = document.querySelector( '.shoptimizer-load-more-error' );
		if ( ! errorEl ) {
			errorEl = document.createElement( 'p' );
			errorEl.className = 'shoptimizer-load-more-error';
			errorEl.style.cssText = 'color: #d63638; margin: 1em 0; text-align: center;';
			errorEl.setAttribute( 'role', 'alert' );
			errorEl.setAttribute( 'aria-live', 'assertive' );

			var wrapper = document.querySelector( '.shoptimizer-load-more-wrapper' );
			if ( wrapper ) {
				wrapper.appendChild( errorEl );
			}
		}
		errorEl.textContent = message;
		errorEl.style.display = 'block';

		// Auto-hide error after 5 seconds
		setTimeout( function() {
			if ( errorEl ) {
				errorEl.style.display = 'none';
			}
		}, 5000 );
	}

	function hideLoadMoreUI() {
		if ( button && button.parentNode ) {
			button.parentNode.removeChild( button );
		}
		if ( statusWrap && statusWrap.parentNode ) {
			statusWrap.parentNode.removeChild( statusWrap );
		}
		if ( progress && progress.parentNode ) {
			progress.parentNode.removeChild( progress );
		}
	}

	function updateViewedCount() {
		var count = grid.querySelectorAll( '.site-main .products .product:not(.cg-grid-feature)' ).length;
		var viewed = Math.min( count, resultTotal );
		if ( statusText ) {
			statusText.textContent = viewed;
			statusWrap.style.visibility = 'visible';
		}
		if ( progressBar ) {
			var percent = ( viewed / resultTotal ) * 100;
			progressBar.style.width = percent + '%';
			progress.setAttribute( 'aria-valuenow', viewed );
		}
	}

	function updateResultCount() {
		var firstValue = ( resultLimit * firstPage ) - resultLimit + 1;
		var lastValue  = Math.min( resultTotal, resultLimit * currentPage );
		var pageText   = resultText.replace( '{FROM}', firstValue ).replace( '{TO}', lastValue );
		var pageEl = document.querySelector( '.site-main .woocommerce-result-count' );
		if ( pageEl ) {
			pageEl.setAttribute( 'aria-live', 'polite' );
			pageEl.textContent = pageText;
			pageEl.style.visibility = 'visible';
		}
	}

	function focusFirstNewProduct( product ) {
		if ( ! product ) {
			return;
		}
		var link = product.querySelector( 'a' );
		if ( link ) {
			link.setAttribute( 'tabindex', '-1' );
			link.focus();
			link.addEventListener( 'blur', function () {
				link.removeAttribute( 'tabindex' );
			}, { once: true } );
		}
	}

	function getNextPageUrl() {
		var pagination = document.querySelector( '.woocommerce-pagination' );
		if ( ! pagination ) {
			return null;
		}

		var nextLink = pagination.querySelector( 'a.next, a.page-numbers.next' );
		if ( ! nextLink ) {
			return null;
		}

		return nextLink.getAttribute( 'href' );
	}

	function getPageURLByFormat( pageNum ) {
		var url = getNextPageUrl();
		if ( ! url ) {
			return null;
		}

		var pageMatch = url.match( /\/page\/(\d+)/ );
		if ( pageMatch ) {
			return url.replace( /\/page\/\d+/, '/page/' + pageNum );
		}

		if ( url.indexOf( 'paged=' ) !== -1 ) {
			return url.replace( /paged=(\d+)/, function( match, p1 ) {
				return 'paged=' + pageNum;
			});
		}

		if ( url.indexOf( 'page=' ) !== -1 ) {
			return url.replace( /page=(\d+)/, function( match, p1 ) {
				return 'page=' + pageNum;
			});
		}

		return null;
	}

	function setFpageParam( urlString, value ) {
		var url = new URL( urlString, window.location.origin );
		url.searchParams.set( 'fpage', value );
		return url.toString();
	}
} );
