/* =============================================================================
 * Storzen — Sticky Add to Cart (frontend)
 * Shows the bar on scroll past the configured trigger, handles AJAX add to
 * cart (via WC's own endpoint) + Buy Now (Storzen endpoint, redirects to
 * checkout), with quantity controls and accessible state changes.
 *
 * Depends on: jQuery (already shipped with WP)
 * ========================================================================== */
(function ($) {
	'use strict';

	if (typeof szStickyAtc === 'undefined') { return; }

	var SAC = {

		$bar:        null,
		productId:   0,
		productType: 'simple',
		nonce:       '',
		trigger:     500,
		ticking:     false,

		init: function () {
			this.$bar = $('.sz-sac');
			if (!this.$bar.length) { return; }

			this.productId   = parseInt(this.$bar.data('product-id'), 10) || 0;
			this.productType = this.$bar.data('product-type') || 'simple';
			this.nonce       = this.$bar.data('nonce') || '';
			this.trigger     = parseInt(this.$bar.data('trigger-offset'), 10) || 500;

			this.bindScroll();
			this.bindQty();
			this.bindButtons();

			// Pro features (each guards on the presence of its DOM element).
			this.bindCountdown();
			this.bindShipProgress();
			this.bindAbTestLabel();
			this.bindRecentToggle();
		},

		/* ───── Scroll trigger (rAF-throttled) ───── */
		bindScroll: function () {
			var self = this;
			window.addEventListener('scroll', function () {
				if (!self.ticking) {
					window.requestAnimationFrame(function () {
						self.handleScroll();
						self.ticking = false;
					});
					self.ticking = true;
				}
			}, { passive: true });

			// Evaluate once on load — handles page refreshes mid-scroll.
			this.handleScroll();
		},

		handleScroll: function () {
			var scrolled = window.scrollY || window.pageYOffset || 0;
			var el       = this.$bar[0];
			if (scrolled >= this.trigger) {
				el.classList.add('is-visible');
				el.setAttribute('aria-hidden', 'false');
			} else {
				el.classList.remove('is-visible');
				el.setAttribute('aria-hidden', 'true');
			}
		},

		/* ───── Quantity controls ───── */
		bindQty: function () {
			$(document).on('click', '.sz-sac__qty-btn', function () {
				var $input = $(this).closest('.sz-sac__qty').find('.sz-sac__qty-input');
				var val    = parseInt($input.val(), 10) || 1;
				var action = $(this).data('action');
				var min    = parseInt($input.attr('min'), 10) || 1;
				var max    = parseInt($input.attr('max'), 10) || 9999;

				if ('inc' === action) { val = Math.min(val + 1, max); }
				if ('dec' === action) { val = Math.max(val - 1, min); }
				$input.val(val);
			});

			$(document).on('change', '.sz-sac__qty-input', function () {
				var $this = $(this);
				var min   = parseInt($this.attr('min'), 10) || 1;
				var max   = parseInt($this.attr('max'), 10) || 9999;
				var val   = parseInt($this.val(), 10) || min;
				$this.val(Math.min(Math.max(val, min), max));
			});
		},

		/* ───── Button actions ───── */
		bindButtons: function () {
			var self = this;

			// Variable products — scroll back to the variation form.
			$(document).on('click', '.sz-sac__btn--scroll', function (e) {
				e.preventDefault();
				var target  = $(this).data('target') || '.variations_form';
				var $target = $(target);
				if ($target.length) {
					$('html, body').animate({ scrollTop: $target.offset().top - 100 }, 300);
				}
			});

			// Add to cart.
			$(document).on('click', '.sz-sac__btn--atc', function (e) {
				e.preventDefault();
				self.doAddToCart(false);
			});

			// Buy now.
			$(document).on('click', '.sz-sac__btn--buy', function (e) {
				e.preventDefault();
				self.doAddToCart(true);
			});
		},

		/* ───── Core add to cart / buy now ───── */
		doAddToCart: function (buyNow) {
			var self          = this;
			var $btn          = buyNow ? $('.sz-sac__btn--buy') : $('.sz-sac__btn--atc');
			var quantity      = parseInt($('.sz-sac__qty-input').val(), 10) || 1;
			var $label        = $btn.find('.sz-sac__btn-label');
			var originalLabel = $label.text();

			$btn.addClass('is-loading').prop('disabled', true);

			if (buyNow) {
				// Buy Now — Storzen endpoint adds to cart, returns checkout URL.
				$label.text(szStickyAtc.i18n.goingTo);

				$.post(szStickyAtc.ajaxUrl, {
					action:     'storzen_buy_now',
					product_id: self.productId,
					quantity:   quantity,
					nonce:      self.nonce
				})
					.done(function (res) {
						if (res && res.success && res.data && res.data.redirect) {
							window.location.href = res.data.redirect;
						} else {
							var msg = (res && res.data && res.data.message) || szStickyAtc.i18n.error;
							$btn.removeClass('is-loading').prop('disabled', false);
							$label.text(originalLabel);
							SAC.showError(msg);
						}
					})
					.fail(function () {
						$btn.removeClass('is-loading').prop('disabled', false);
						$label.text(originalLabel);
						SAC.showError(szStickyAtc.i18n.error);
					});

			} else {
				// Standard ATC — uses WooCommerce's built-in AJAX endpoint.
				// This is the same endpoint WC uses for the loop "Add to cart"
				// button, so it goes through WC's own validation & fragments.
				$label.text(szStickyAtc.i18n.adding);

				$.post(szStickyAtc.ajaxUrl, {
					action:     'woocommerce_add_to_cart',
					product_id: self.productId,
					quantity:   quantity
				})
					.done(function (res) {
						// WC returns either an error string (rare) or a fragments object.
						if (res && res.error) {
							$btn.removeClass('is-loading').prop('disabled', false);
							$label.text(originalLabel);
							SAC.showError(szStickyAtc.i18n.error);
							return;
						}

						if (res && res.fragments) {
							$.each(res.fragments, function (key, val) {
								$(key).replaceWith(val);
							});
							$(document.body).trigger('added_to_cart', [res.fragments, res.cart_hash || '']);
						}

						$btn.removeClass('is-loading').addClass('is-success').prop('disabled', false);
						$label.text(szStickyAtc.i18n.added);

						setTimeout(function () {
							$btn.removeClass('is-success');
							$label.text(originalLabel);
						}, 2000);
					})
					.fail(function () {
						$btn.removeClass('is-loading').prop('disabled', false);
						$label.text(originalLabel);
						SAC.showError(szStickyAtc.i18n.error);
					});
			}
		},

		/* ───── Countdown timer (Pro) ───── */
		bindCountdown: function () {
			var $cd = $('.sz-sac__countdown');
			if (!$cd.length) { return; }

			var endTs = parseInt($cd.data('end'), 10) || 0;
			if (!endTs) { return; }

			var $time = $cd.find('.sz-sac__countdown-time');
			var I = szStickyAtc.i18n;

			function tick() {
				var now  = Math.floor(Date.now() / 1000);
				var diff = endTs - now;
				if (diff <= 0) {
					$cd.addClass('is-expired');
					$time.text('00:00:00');
					return false;
				}
				var d = Math.floor(diff / 86400);
				var h = Math.floor((diff % 86400) / 3600);
				var m = Math.floor((diff % 3600) / 60);
				var s = diff % 60;

				var parts = [];
				if (d > 0) { parts.push(d + I.days); }
				parts.push(pad(h) + I.hours);
				parts.push(pad(m) + I.mins);
				parts.push(pad(s) + I.secs);

				// Last hour — flag for the urgent style.
				$cd.toggleClass('is-urgent', diff < 3600);

				$time.text(parts.join(' '));
				return true;
			}

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

			if (tick() !== false) {
				setInterval(tick, 1000);
			}
		},

		/* ───── Free-shipping progress bar (Pro) ───── */
		bindShipProgress: function () {
			var $prog = $('.sz-sac__ship-progress');
			if (!$prog.length) { return; }

			var threshold = parseFloat($prog.data('threshold')) || 0;
			if (threshold <= 0) { return; }

			var current   = parseFloat(szStickyAtc.cartTotal) || 0;
			var $fill     = $prog.find('.sz-sac__ship-fill');
			var $track    = $prog.find('.sz-sac__ship-track');
			var $text     = $prog.find('.sz-sac__ship-text');
			var I         = szStickyAtc.i18n;
			var currency  = szStickyAtc.currencySym || '';

			function render() {
				var pct = Math.min(100, Math.max(0, (current / threshold) * 100));
				$fill.css('width', pct.toFixed(1) + '%');
				$track.attr('aria-valuenow', Math.round(pct));

				if (current >= threshold) {
					$prog.addClass('is-reached');
					$text.text(I.shipReached);
				} else {
					$prog.removeClass('is-reached');
					var remaining = (threshold - current).toFixed(2);
					$text.text(I.shipMore.replace('%s', currency + remaining));
				}
			}

			render();

			// When WC fires added_to_cart, update our tracked total. WC's response
			// doesn't include a subtotal directly, so we re-fetch via cart fragments.
			$(document.body).on('added_to_cart', function () {
				// Pull the freshest subtotal from the WC cart fragment if present.
				var $frag = $('.woocommerce-mini-cart__total .amount, .cart-subtotal .amount').last();
				if ($frag.length) {
					var raw  = $frag.text().replace(/[^\d.,-]/g, '').replace(',', '.');
					var val  = parseFloat(raw);
					if (!isNaN(val)) { current = val; }
				} else {
					// Best-effort fallback: bump by the product's price * quantity.
					var qty   = parseInt($('.sz-sac__qty-input').val(), 10) || 1;
					var price = parseFloat($('.sz-sac__price .amount').first().text().replace(/[^\d.,-]/g, '').replace(',', '.')) || 0;
					current  += price * qty;
				}
				render();
			});
		},

		/* ───── A/B test button label (Pro) ───── */
		bindAbTestLabel: function () {
			if (!szStickyAtc.abTestEnabled) { return; }

			var altLabel = this.$bar.data('ab-alt-label');
			if (!altLabel) { return; }

			var $btn   = $('.sz-sac__btn--atc .sz-sac__btn-label');
			if (!$btn.length) { return; }

			// Persist the variant choice for the session so a refresh doesn't
			// re-roll the experiment and confuse the user (or the analytics).
			var KEY     = 'sz_sac_ab_' + (this.productId || 0);
			var variant = '';
			try { variant = window.sessionStorage.getItem(KEY) || ''; } catch (e) {}

			if (!variant) {
				variant = (Math.random() < 0.5) ? 'A' : 'B';
				try { window.sessionStorage.setItem(KEY, variant); } catch (e) {}
			}

			if (variant === 'B') {
				$btn.text(altLabel);
				this.$bar.attr('data-ab-active', 'B');
			} else {
				this.$bar.attr('data-ab-active', 'A');
			}

			// Emit an event analytics can hook into when the customer clicks.
			$(document).on('click', '.sz-sac__btn--atc, .sz-sac__btn--buy', function () {
				$(document.body).trigger('storzen:sac_ab_click', [{
					productId: SAC.productId,
					variant:   variant,
					label:     $btn.text()
				}]);
			});
		},

		/* ───── Recently viewed strip toggle ───── */
		bindRecentToggle: function () {
			$(document).on('click', '.sz-sac__recent-toggle', function () {
				var $btn  = $(this);
				var $list = $('#' + $btn.attr('aria-controls'));
				var open  = $btn.attr('aria-expanded') === 'true';
				$btn.attr('aria-expanded', open ? 'false' : 'true');
				if (open) {
					$list.attr('hidden', 'hidden');
				} else {
					$list.removeAttr('hidden');
				}
			});
		},

		/* ───── Toast-style error ───── */
		showError: function (message) {
			$('.sz-sac-error').remove();
			var $err = $('<div class="sz-sac-error" role="alert"></div>').text(message);
			$('body').append($err);
			setTimeout(function () {
				$err.fadeOut(300, function () { $(this).remove(); });
			}, 3000);
		}
	};

	$(function () { SAC.init(); });

	// Public namespace (debugging).
	window.StorzenStickyAtc = SAC;

})(jQuery);
