
(function ($) {
	'use strict';

	$(function () {
		var $form = $('form.cart').first();
		var $initialWrap = $form.find('.nudgesells-upsell-wrap').first();

		if (!$initialWrap.length) {
			return;
		}

		var hostId = $initialWrap.data('product-id');
		var isVariableHost = $initialWrap.data('is-variable-host') == 1;
		var needsFetch = $initialWrap.data('needs-fetch') == 1;

		var currentVariation = null;
		var previewTimer = null;
		var qtyRefreshTimer = null;
		var fetchToken = 0;

		function $wrap() {
			return $form.find('.nudgesells-upsell-wrap');
		}

		function getHostQty() {
			var val = parseInt($form.find('input.qty').val(), 10);
			return val > 0 ? val : 1;
		}

		var hasFetchedOnce = ! needsFetch;

		var lastRenderedHtml = null;

		function refreshWidget(variationId) {
			var token = ++fetchToken;
			var isInitial = !hasFetchedOnce;
			hasFetchedOnce = true;
			$.post(NudgeSells_Public_Vars.render_widget_url, {
				nonce: NudgeSells_Public_Vars.nonce,
				host_id: hostId,
				host_variation_id: variationId || 0,
				host_qty: getHostQty(),
				initial: isInitial ? 1 : 0
			}).done(function (response) {
				if (token !== fetchToken) {
					return;
				}
				var html = (response && response.success && response.data && response.data.html) ? response.data.html : '';
				if (!html) {
					var hadQtyFilter = $wrap().data('has-qty-filter') == 1;
					html = '<div class="nudgesells-upsell-wrap nudgesells-upsell-wrap--empty" data-product-id="' + hostId + '" data-is-variable-host="' + (isVariableHost ? '1' : '0') + '" data-has-qty-filter="' + (hadQtyFilter ? '1' : '0') + '"></div>';
				}

				if (html === lastRenderedHtml) {
					return;
				}
				lastRenderedHtml = html;

				$wrap().replaceWith(html);
				$(document).trigger('nudgesells_widget_refreshed');
			});
		}

		if (needsFetch) {
			refreshWidget(0);
		}

		if (isVariableHost && $form.hasClass('variations_form')) {
			$form.on('found_variation', function (event, variation) {
				currentVariation = variation;
				refreshWidget(variation.variation_id);
				schedulePreview();
			});
			$form.on('reset_data hide_variation', function () {
				currentVariation = null;
				refreshWidget(0);
				schedulePreview();
			});
		}

		$form.on('change input', 'input.qty', function () {
			if ($wrap().data('has-qty-filter') != 1) {
				return;
			}
			clearTimeout(qtyRefreshTimer);
			qtyRefreshTimer = setTimeout(function () {
				refreshWidget(currentVariation ? currentVariation.variation_id : 0);
			}, 300);
		});

		function isAllowQty($row) {
			return $row.data('allow-qty') == 1;
		}

		function isRowSelected($row) {
			if (isAllowQty($row)) {
				return (parseInt($row.find('.nudgesells-addon-qty').val(), 10) || 0) > 0;
			}
			return $row.find('.nudgesells-addon-toggle').is(':checked');
		}

		function rowQty($row) {
			if (isAllowQty($row)) {
				return Math.max(0, parseInt($row.find('.nudgesells-addon-qty').val(), 10) || 0);
			}
			return 1;
		}

		function updateRowActiveState($row) {
			$row.toggleClass('nudgesells-addon-row--active', isRowSelected($row));
		}

		function updateAllRowActiveStates() {
			$wrap().find('.nudgesells-addon-row').each(function () {
				updateRowActiveState($(this));
			});
		}

		function getSelectedAddons() {
			var addons = [];
			$wrap().find('.nudgesells-addon-row').each(function () {
				var $row = $(this);
				if (!isRowSelected($row)) {
					return;
				}
				var isVariable = $row.data('is-variable') == 1;
				var variationId = 0;
				if (isVariable) {
					variationId = parseInt($row.find('.nudgesells-addon-variation-id').val(), 10) || 0;
					if (!variationId) {
						return;
					}
				}
				addons.push({
					product_id: $row.data('product-id'),
					variation_id: variationId,
					qty: rowQty($row)
				});
			});
			return addons;
		}

		function updateProgressPills() {
			var addons = getSelectedAddons();
			var selectedCount = addons.length;
			var totalQty = 0;
			addons.forEach(function (addon) {
				totalQty += addon.qty;
			});

			$wrap().find('.nudgesells-bundle-pills .nudgesells-pill').each(function (i) {
				setPillActive($(this), i < selectedCount);
			});

			$wrap().find('.nudgesells-tier-pills .nudgesells-pill').each(function () {
				var minQty = parseInt($(this).data('min-qty'), 10) || 0;
				setPillActive($(this), totalQty >= minQty);
			});

			$wrap().find('.nudgesells-bundle-progress-bar').each(function () {
				var total = parseInt($(this).data('total'), 10) || 0;
				var pct = total > 0 ? Math.min(100, (selectedCount / total) * 100) : 0;
				$(this).find('.nudgesells-progress-bar-fill').css('width', pct + '%');
			});

			$wrap().find('.nudgesells-tier-progress-bar').each(function () {
				var thresholds = $(this).data('thresholds') || [];
				var reached = 0;
				thresholds.forEach(function (minQty) {
					if (totalQty >= minQty) {
						reached++;
					}
				});
				var pct = thresholds.length > 0 ? Math.min(100, (reached / thresholds.length) * 100) : 0;
				$(this).find('.nudgesells-progress-bar-fill').css('width', pct + '%');
			});
		}

		function setPillActive($pill, shouldBeActive) {
			var wasActive = $pill.hasClass('nudgesells-pill--active');
			$pill.toggleClass('nudgesells-pill--active', shouldBeActive);
			if (shouldBeActive && !wasActive) {

				$pill.addClass('nudgesells-pill--just-reached');
				setTimeout(function () {
					$pill.removeClass('nudgesells-pill--just-reached');
				}, 300);
			}
		}

		function rowValid($row) {
			var isVariable = $row.data('is-variable') == 1;
			if (!isVariable) {
				return true;
			}
			return !!parseInt($row.find('.nudgesells-addon-variation-id').val(), 10);
		}

		function formatMoney(amount) {

			return amount.toFixed(2);
		}

		function getSelectedUpgrade() {
			var $checked = $wrap().find('input[name="nudgesells_upgrade_choice"]:checked');
			var upgradeId = parseInt($checked.val(), 10) || 0;
			if (!upgradeId) {
				return { id: 0, variationId: 0 };
			}
			var $option = $checked.closest('.nudgesells-upgrade-option');
			var isVariable = $option.data('is-variable') == 1;
			var variationId = isVariable ? (parseInt($option.find('.nudgesells-upgrade-variation-id').val(), 10) || 0) : 0;
			return { id: upgradeId, variationId: variationId };
		}

		// Keeps the hidden `nudgesells_selection` field in sync so it's
		// current whenever anything submits form.cart -- unlike the price
		// preview below, this runs synchronously, not debounced.
		function syncSelectionField() {
			var upgrade = getSelectedUpgrade();
			var payload = {
				host_id: hostId,
				upgrade_id: upgrade.id,
				upgrade_variation_id: upgrade.variationId,
				addons: getSelectedAddons()
			};
			$wrap().find('.nudgesells-selection-field').val(JSON.stringify(payload));
		}

		function schedulePreview() {
			syncSelectionField();
			updateProgressPills();
			clearTimeout(previewTimer);
			previewTimer = setTimeout(runPreview, 200);
		}

		function runPreview() {
			var addons = getSelectedAddons();
			var upgrade = getSelectedUpgrade();
			var $discountMessage = $wrap().find('.nudgesells-discount-message');
			var $summary = $wrap().find('.nudgesells-summary');

			if (!$summary.length && !$discountMessage.length) {
				return;
			}

			$.post(NudgeSells_Public_Vars.price_preview_url, {
				nonce: NudgeSells_Public_Vars.nonce,
				host_id: hostId,
				host_qty: getHostQty(),
				host_variation_id: currentVariation ? currentVariation.variation_id : 0,
				upgrade_id: upgrade.id,
				upgrade_variation_id: upgrade.variationId,
				addons: JSON.stringify(addons)
			}).done(function (response) {
				if (!response || !response.success) {
					return;
				}
				var data = response.data;
				var hasSelection = addons.length > 0 || !!upgrade.id;

				if (data.progress_note_html) {
					$discountMessage.html(data.progress_note_html).show()
						.toggleClass('nudgesells-discount-message--reached', !!data.discount_reached);
				} else {
					$discountMessage.hide().empty().removeClass('nudgesells-discount-message--reached');
				}

				if (!hasSelection) {
					$summary.hide();
					return;
				}
				$summary.show();

				$summary.find('.nudgesells-summary-savings').html(data.savings_note_html || '');

				var totalHtml = '';
				if (data.total_saved > 0) {
					totalHtml += '<del class="nudgesells-summary-total-original">' + data.total_original_display + '</del> ';
				}
				totalHtml += '<span class="nudgesells-summary-total-final">' + data.total_display + '</span>';
				$summary.find('.nudgesells-summary-total').html(totalHtml);
			});
		}

		function findMatchingVariation(variations, selectedAttrs) {
			for (var i = 0; i < variations.length; i++) {
				var variation = variations[i];
				var isMatch = true;
				for (var key in selectedAttrs) {
					if (!Object.prototype.hasOwnProperty.call(selectedAttrs, key)) {
						continue;
					}
					var variationValue = variation.attributes[key];
					if (variationValue && variationValue !== selectedAttrs[key]) {
						isMatch = false;
						break;
					}
				}
				if (isMatch) {
					return variation;
				}
			}
			return null;
		}

		function updateVariationState($container, attributeSelector, hiddenIdSelector, priceSelector) {
			var variations = $container.data('variations') || [];
			var $selects = $container.find(attributeSelector);
			var selectedAttrs = {};
			var allChosen = true;

			$selects.each(function () {
				var name = $(this).data('attribute_name') || $(this).attr('name');
				var val = $(this).val();
				selectedAttrs[name] = val;
				if (!val) {
					allChosen = false;
				}
			});

			var $hiddenId = $container.find(hiddenIdSelector);
			var $price = priceSelector ? $container.find(priceSelector) : null;
			var $thumb = $container.find('.nudgesells-addon-thumb').first();

			if (!allChosen) {
				$hiddenId.val('');
				if ($price) {
					$price.empty();
				}
				return;
			}

			var match = findMatchingVariation(variations, selectedAttrs);
			if (match) {
				$hiddenId.val(match.variation_id);
				if ($price) {
					var savingsLabel = $container.data('savings-label');
					var html = '<span class="nudgesells-addon-price-discounted">' + match.price_display_discounted + '</span>';
					if (match.price_discounted < match.price_original) {
						html += ' <del class="nudgesells-addon-price-original">' + match.price_display_original + '</del>';
					}
					if (savingsLabel) {
						html += ' <span class="nudgesells-savings-badge">' + savingsLabel + '</span>';
					}
					$price.html(html);
				}
				if ($thumb.length && match.image) {
					$thumb.attr('src', match.image);
				}
			} else {
				$hiddenId.val('');
				if ($price) {
					$price.empty();
				}
			}
		}

		function updateUpgradeVariationState($option) {
			updateVariationState($option, '.nudgesells-upgrade-attribute', '.nudgesells-upgrade-variation-id', null);

			var variations = $option.data('variations') || [];
			var selectedAttrs = {};
			var allChosen = true;
			$option.find('.nudgesells-upgrade-attribute').each(function () {
				var name = $(this).data('attribute_name') || $(this).attr('name');
				var val = $(this).val();
				selectedAttrs[name] = val;
				if (!val) {
					allChosen = false;
				}
			});
			if (allChosen) {
				var match = findMatchingVariation(variations, selectedAttrs);
				if (match) {
					var savingsLabel = $option.data('savings-label');
					var html = match.price_display_discounted;
					if (savingsLabel) {
						html += ' <span class="nudgesells-savings-badge">' + savingsLabel + '</span>';
					}
					$option.find('.nudgesells-upgrade-price').html(html);
				}
			}
		}

		function updateAddonVariationState($row) {
			updateVariationState($row, '.nudgesells-addon-attribute', '.nudgesells-addon-variation-id', '.nudgesells-addon-price');
		}

		$form.on('change', '.nudgesells-addon-toggle', function () {
			var $row = $(this).closest('.nudgesells-addon-row');
			$row.find('.nudgesells-addon-attribute').prop('disabled', !isRowSelected($row));
			updateRowActiveState($row);
			schedulePreview();
		});

		$form.on('change input', '.nudgesells-addon-qty', function () {
			var $row = $(this).closest('.nudgesells-addon-row');
			if (parseInt($(this).val(), 10) < 0) {
				$(this).val(0);
			}
			$row.find('.nudgesells-addon-attribute').prop('disabled', !isRowSelected($row));
			updateRowActiveState($row);
			schedulePreview();
		});

		$form.on('click', '.nudgesells-quick-view', function (e) {
			var $link = $(this);
			var detail = {
				productId: parseInt($link.data('product_id'), 10) || 0,
				permalink: $link.attr('href')
			};
			var nativeEvent = new CustomEvent('nudgesells_open_quick_view', { detail: detail, cancelable: true });
			var notCancelled = document.dispatchEvent(nativeEvent);
			if (!notCancelled) {
				e.preventDefault();
			}
		});

		$form.on('click', '.nudgesells-qty-plus, .nudgesells-qty-minus', function () {
			var $btn = $(this);
			var $input = $btn.siblings('.nudgesells-addon-qty');
			var current = parseInt($input.val(), 10) || 0;
			var next = $btn.hasClass('nudgesells-qty-plus') ? current + 1 : Math.max(0, current - 1);
			$input.val(next).trigger('change');
		});

		$form.on('change', '.nudgesells-addon-attribute', function () {
			var $row = $(this).closest('.nudgesells-addon-row');
			updateAddonVariationState($row);
			schedulePreview();
		});

		$form.on('change', '.nudgesells-upgrade-attribute', function () {
			updateUpgradeVariationState($(this).closest('.nudgesells-upgrade-option'));
			schedulePreview();
		});

		$form.on('change', 'input[name="nudgesells_upgrade_choice"]', function () {
			$wrap().find('.nudgesells-upgrade-option').removeClass('nudgesells-selected');
			$(this).closest('.nudgesells-upgrade-option').addClass('nudgesells-selected');
			schedulePreview();
		});

		function initRowStates() {
			$wrap().find('.nudgesells-addon-row').each(function () {
				var $row = $(this);
				$row.find('.nudgesells-addon-attribute').prop('disabled', !isRowSelected($row));
			});
			updateAllRowActiveStates();
		}
		initRowStates();
		$(document).on('nudgesells_widget_refreshed', initRowStates);

		var countdownIntervals = [];

		function initCountdowns() {

			countdownIntervals.forEach(function (intervalId) {
				clearInterval(intervalId);
			});
			countdownIntervals = [];

			$wrap().find('.nudgesells-countdown-pill').each(function () {
				var $pill = $(this);
				var endTimestamp = parseInt($pill.data('end-timestamp'), 10) || 0;
				var format = $pill.data('format') || 'hms';

				if (!endTimestamp) {
					$pill.hide();
					return;
				}

				var intervalId = setInterval(tick, 1000);
				countdownIntervals.push(intervalId);
				tick();

				function tick() {
					var remaining = endTimestamp - Math.floor(Date.now() / 1000);

					if (remaining <= 0) {
						clearInterval(intervalId);
						$pill.hide();

						refreshWidget(currentVariation ? currentVariation.variation_id : 0);
						return;
					}

					var pad = function (n) {
						return (n < 10 ? '0' : '') + n;
					};

					var days = Math.floor(remaining / 86400);
					var totalHours = Math.floor(remaining / 3600);
					var hoursOfDay = Math.floor((remaining % 86400) / 3600);
					var minutes = Math.floor((remaining % 3600) / 60);
					var seconds = remaining % 60;

					var text = format
						.replace('{d}', days)
						.replace('{H}', pad(totalHours))
						.replace('{h}', pad(hoursOfDay))
						.replace('{mm}', pad(minutes))
						.replace('{ss}', pad(seconds));
					$pill.find('.nudgesells-countdown-time').text(text);
				}
			});
		}
		initCountdowns();
		$(document).on('nudgesells_widget_refreshed', initCountdowns);

		schedulePreview();
		$(document).on('nudgesells_widget_refreshed', schedulePreview);

		function resetSelections() {
			$wrap().find('.nudgesells-addon-toggle').prop('checked', false);
			$wrap().find('.nudgesells-addon-qty').val(0);
			$wrap().find('input[name="nudgesells_upgrade_choice"]').prop('checked', false);
			$wrap().find('input[name="nudgesells_upgrade_choice"][value=""]').prop('checked', true);
			$wrap().find('.nudgesells-upgrade-option').removeClass('nudgesells-selected');
			initRowStates();
			schedulePreview();
		}
		$(document.body).on('added_to_cart', resetSelections);

		if (!$form.length) {
			return;
		}

		$form.on('submit', function (e) {
			var addons = getSelectedAddons();
			var $checkedUpgrade = $wrap().find('input[name="nudgesells_upgrade_choice"]:checked');
			var upgradeId = parseInt($checkedUpgrade.val(), 10) || 0;
			var $upgradeOption = upgradeId ? $checkedUpgrade.closest('.nudgesells-upgrade-option') : null;
			var upgradeIsVariable = $upgradeOption && $upgradeOption.data('is-variable') == 1;
			var upgradeVariationId = upgradeIsVariable ? (parseInt($upgradeOption.find('.nudgesells-upgrade-variation-id').val(), 10) || 0) : 0;

			var invalid = false;
			$wrap().find('.nudgesells-addon-row').each(function () {
				var $row = $(this);
				if (isRowSelected($row) && !rowValid($row)) {
					invalid = true;
					$row.addClass('nudgesells-row-error');
				}
			});
			if (upgradeIsVariable && !upgradeVariationId) {
				invalid = true;
				$upgradeOption.addClass('nudgesells-row-error');
			}
			if (invalid) {
				e.preventDefault();
				alert(NudgeSells_Public_Vars.i18n.select_option);
				return false;
			}

			if (!addons.length && !upgradeId) {
				return true;
			}

			if (isVariableHost && !upgradeId && !currentVariation) {
				e.preventDefault();
				alert(NudgeSells_Public_Vars.i18n.select_option);
				return false;
			}

			e.preventDefault();

			var hostQty = parseInt($form.find('input.qty').val(), 10) || 1;
			var hostVariationId = (isVariableHost && currentVariation) ? currentVariation.variation_id : 0;
			var hostVariationAttributes = {};
			if (isVariableHost) {
				$form.find('[name^="attribute_"]').each(function () {
					hostVariationAttributes[$(this).attr('name')] = $(this).val();
				});
			}
			var upgradeVariationAttributes = {};
			if (upgradeIsVariable) {
				$upgradeOption.find('.nudgesells-upgrade-attribute').each(function () {
					var attrName = $(this).data('attribute_name') || $(this).attr('name');
					upgradeVariationAttributes[attrName] = $(this).val();
				});
			}
			var $button = $form.find('.single_add_to_cart_button');
			$button.addClass('loading').prop('disabled', true);

			$.post(NudgeSells_Public_Vars.add_to_cart_url, {
				nonce: NudgeSells_Public_Vars.nonce,
				host_id: hostId,
				host_qty: hostQty,
				host_variation_id: hostVariationId,
				host_variation_attributes: JSON.stringify(hostVariationAttributes),
				upgrade_id: upgradeId,
				upgrade_variation_id: upgradeVariationId,
				upgrade_variation_attributes: JSON.stringify(upgradeVariationAttributes),
				addons: JSON.stringify(addons)
			}).done(function (response) {
				if (response && response.success) {
					$(document.body).trigger('wc_fragment_refresh');
					window.location = response.data.cart_url;
				} else {
					alert((response && response.data && response.data.message) || NudgeSells_Public_Vars.i18n.add_to_cart_error);
				}
			}).fail(function () {
				alert(NudgeSells_Public_Vars.i18n.add_to_cart_error);
			}).always(function () {
				$button.removeClass('loading').prop('disabled', false);
			});
		});
	});
})(jQuery);
