/* global cartcueAdmin, jQuery */
(function (w, $) {
	if (!$ || !w.cartcueAdmin) {
		return;
	}

	w.apSetFreq = function (m, c, el) {
		document.querySelectorAll('.ap-freq-pill').forEach(function (o) {
			o.classList.remove('is-selected');
		});
		if (el) {
			el.classList.add('is-selected');
		}
		var mr = document.getElementById('ap-max-runs');
		var cd = document.getElementById('ap-cooldown-days');
		if (mr) {
			mr.value = m;
		}
		if (cd) {
			cd.value = c;
		}
	};

	w.apGetCooldown = function () {
		var el = document.getElementById('ap-cooldown-val');
		return el && el.value ? el.value : 30;
	};

	function formatDelayWait() {
		var timingType = $('#ap-timing-type').val() || 'immediate';
		if ('delay' !== timingType) {
			return null;
		}
		var delayVal = $('#ap-delay-value').val();
		var delayUnit = $('#ap-delay-unit').val() || 'hours';
		var n = parseInt(delayVal, 10);
		if (!n && n !== 0) {
			n = 1;
		}
		var cfg = w.cartcueAdmin;
		var editor = cfg.editor || {};
		var tu = cfg.timingUnits || {};
		var ts = editor.timing_singular || {};
		var wv = editor.wait_verb || 'wait';
		var unitWord = (n === 1 && ts[delayUnit]) ? ts[delayUnit] : (tu[delayUnit] || delayUnit);
		return wv + ' ' + n + ' ' + unitWord;
	}

	function setStorySegmentText($el, text) {
		if (!$el || !$el.length) {
			return;
		}
		var $inner = $el.find('.ap-story-card__text');
		if ($inner.length) {
			$inner.text(text);
		} else {
			$el.text(text);
		}
	}

	function getStorySegmentText($el) {
		if (!$el || !$el.length) {
			return '';
		}
		var $inner = $el.find('.ap-story-card__text');
		return $inner.length ? $inner.text() : $el.text();
	}

	function syncThenSegment(actions) {
		function normalizeActionLabel(slug, fallback) {
			if (slug === 'send_email') {
				return 'send email';
			}
			if (slug === 'send_sms') {
				return 'send SMS';
			}
			if (slug === 'send_whatsapp') {
				return 'send WhatsApp';
			}
			return fallback;
		}
		function actionStoryLabel(slug, fallback, $card) {
			var base = normalizeActionLabel(slug, fallback);
			function getActionFieldDisplay(key) {
				var actionDef = actions && actions[slug] ? actions[slug] : null;
				var fieldDef = null;
				var currentValue = '';
				var currentLabel = '';
				if ($card && $card.length) {
					var $select = $card.find('select[name$="[settings][' + key + ']"]');
					if ($select.length) {
						currentValue = String($select.val() || '');
						currentLabel = $.trim($select.find('option:selected').text() || '');
					} else {
						currentValue = String($card.find('[name$="[settings][' + key + ']"]').val() || '');
					}
				}
				if (actionDef && Array.isArray(actionDef.fields)) {
					for (var i = 0; i < actionDef.fields.length; i++) {
						if (actionDef.fields[i] && actionDef.fields[i].key === key) {
							fieldDef = actionDef.fields[i];
							break;
						}
					}
				}
				if (!currentValue && fieldDef && fieldDef.default !== undefined && fieldDef.default !== null) {
					currentValue = String(fieldDef.default);
				}
				if (currentLabel) {
					return currentLabel;
				}
				if (fieldDef && fieldDef.options && currentValue) {
					if (Array.isArray(fieldDef.options) && fieldDef.options[currentValue] !== undefined) {
						return String(fieldDef.options[currentValue]);
					}
					if (fieldDef.options[currentValue] !== undefined) {
						return String(fieldDef.options[currentValue]);
					}
					if (key === 'new_status') {
						if (fieldDef.options['wc-' + currentValue] !== undefined) {
							return String(fieldDef.options['wc-' + currentValue]);
						}
						if (currentValue.indexOf('wc-') === 0) {
							var stripped = currentValue.replace(/^wc-/, '');
							if (fieldDef.options[stripped] !== undefined) {
								return String(fieldDef.options[stripped]);
							}
						}
					}
				}
				return currentValue || '';
			}
			if (slug === 'change_customer_role') {
				var roleLabel = $.trim(getActionFieldDisplay('new_role'));
				return roleLabel ? (base + ' to ' + roleLabel.toLowerCase()) : base;
			}
			if (slug === 'change_order_status') {
				var statusLabel = $.trim(getActionFieldDisplay('new_status'));
				return statusLabel ? (base + ' to ' + statusLabel.toLowerCase()) : base;
			}
			return base;
		}
		var $then = $('#ss-then');
		if (!$then.length) {
			return;
		}
		var nSeq = $('#ap-sequence-builder .ap-sequence-step').length;
		var editor = (w.cartcueAdmin && w.cartcueAdmin.editor) || {};
		if (nSeq > 0) {
			var parts = [];
			$('#ap-sequence-builder .ap-sequence-step').each(function () {
				var idx = String($(this).find('.ap-seq-action').val());
				var slug = '';
				var $selectedCard = $();
				$('#ap-actions-list .ap-action-card').each(function () {
					if (String($(this).data('index')) === idx) {
						$selectedCard = $(this);
						slug = $(this).find('.ap-action-type').val();
						return false;
					}
				});
				var label = slug && actions[slug] ? actions[slug].label.toLowerCase() : '\u2026';
				parts.push(actionStoryLabel(slug, label, $selectedCard));
			});
			var prefix = (editor.story_timed || '') + ' ';
			setStorySegmentText($then, prefix + parts.join(' \u2192 '));
			$then.addClass('ap-story-segment--filled').removeClass('ap-story-segment--muted');
			return;
		}
		var actionNames = [];
		$('#ap-actions-list .ap-action-card').each(function () {
			var $card = $(this);
			var $type = $card.find('.ap-action-type');
			if (!$type.length) {
				return;
			}
			var v = $type.val();
			if (v && actions[v]) {
				actionNames.push(actionStoryLabel(v, actions[v].label.toLowerCase(), $card));
			}
		});
		if (actionNames.length) {
			setStorySegmentText($then, actionNames.join(' + '));
			$then.addClass('ap-story-segment--filled').removeClass('ap-story-segment--muted');
		} else {
			setStorySegmentText($then, 'do something');
			$then.removeClass('ap-story-segment--filled').addClass('ap-story-segment--muted');
		}
	}

	function syncStep4Sub() {
		var ed = (w.cartcueAdmin && w.cartcueAdmin.editor) || {};
		var n = $('#ap-sequence-builder .ap-sequence-step').length;
		var $sub = $('#ap-step-4-sub');
		if ($sub.length) {
			$sub.text(n > 0 ? (ed.step4_sequence || '') : (ed.step4_simple || ''));
		}
		$('#ap-play-form').toggleClass('ap-mode-sequence', n > 0);
		$('#ap-play-form').attr('data-is-sequence', n > 0 ? 'true' : 'false');
		$('#ap-timing-sequence-wrap').toggleClass('is-expanded', n > 0);
		$('#ap-step-4-actions').toggleClass('ap-step-panel--library-mode', n > 0);
	}

	w.apCartCuePlayUx = {
		formatDelayWait: formatDelayWait,
		setStorySegmentText: setStorySegmentText,
		getStorySegmentText: getStorySegmentText,
		syncThen: function (actions) {
			syncThenSegment(actions || {});
		},
		syncStep4: syncStep4Sub,
		refresh: function () {
			var timingType = $('#ap-timing-type').val() || 'immediate';
			var $wait = $('#ss-wait');
			if ('delay' === timingType && $('#ap-delay-value').val()) {
				var ph = formatDelayWait();
				if (ph) {
					setStorySegmentText($wait, ph);
					$wait.addClass('ap-story-segment--filled').removeClass('ap-story-segment--muted');
				}
			}
			syncStep4Sub();
			syncThenSegment(w.cartcueAdmin.actions || {});
		}
	};
})(window, jQuery);

(function ($) {
	'use strict';

	var cfg      = window.cartcueAdmin || {};
	var triggers = cfg.triggers || {};
	var actions  = cfg.actions  || {};
	var rules    = cfg.rules    || {};

	function setStorySegmentText($el, text) {
		if (window.apCartCuePlayUx && typeof window.apCartCuePlayUx.setStorySegmentText === 'function') {
			window.apCartCuePlayUx.setStorySegmentText($el, text);
			return;
		}
		if (!$el || !$el.length) {
			return;
		}
		var $inner = $el.find('.ap-story-card__text');
		if ($inner.length) {
			$inner.text(text);
		} else {
			$el.text(text);
		}
	}

	function storyRefresh() {
		if (typeof window.apUpdateStory === 'function') {
			window.apUpdateStory();
		}
	}

	function setCollapseState($body, $btn, shouldOpen) {
		if (!$body.length || !$btn.length) {
			return;
		}
		$body.toggleClass('is-open', shouldOpen);
		$btn.attr('aria-expanded', String(shouldOpen));
		var openLabel = $btn.data('openLabel') || 'Hide';
		var closedLabel = $btn.data('closedLabel') || 'Show';
		$btn.text(shouldOpen ? openLabel : closedLabel);
	}

	function setEditorMode() {
		var $form = $('#ap-play-form');
		if (!$form.length) {
			return;
		}
		var hasConditionsData = $('#ap-rules-list .ap-rule-row').length > 0;
		var hasSequenceData = $('#ap-sequence-builder .ap-sequence-step').length > 0;
		setCollapseState($('#ap-conditions-body'), $('#ap-conditions-toggle'), hasConditionsData);
		setCollapseState($('#ap-advanced-settings-body'), $('#ap-advanced-settings-toggle'), false);
		if ($('#ap-sequence-body').length) {
			$('#ap-timing-sequence-wrap').toggleClass('is-expanded', hasSequenceData);
			$('#ap-sequence-body').toggleClass('is-open', hasSequenceData);
		}
	}

	function syncSetupChecklist() {
		var $list = $('#ap-setup-checklist');
		if (!$list.length) {
			return;
		}
		var hasName = $.trim($('#ap-play-name').val() || '').length > 0;
		var hasTrigger = !!$('input[name="trigger_slug"]:checked').val();
		var hasAction = false;
		$('.ap-action-type').each(function () {
			if ($(this).val()) {
				hasAction = true;
				return false;
			}
		});
		$list.find('[data-check="name"]').toggleClass('is-done', hasName);
		$list.find('[data-check="trigger"]').toggleClass('is-done', hasTrigger);
		$list.find('[data-check="action"]').toggleClass('is-done', hasAction);
	}

	window.apSyncSetupChecklist = syncSetupChecklist;

	function fetchPickerOptions(source, term, selected) {
		if (!source || !cfg.nonces || !cfg.nonces.search_picker) {
			return $.Deferred().resolve([]).promise();
		}
		return $.post(cfg.ajaxUrl || ajaxurl, {
			action: 'cartcue_search_picker',
			nonce: cfg.nonces.search_picker,
			source: source,
			term: term || '',
			selected: Array.isArray(selected) ? selected.join(',') : ''
		}).then(function (res) {
			return (res && res.success && res.data && Array.isArray(res.data.items)) ? res.data.items : [];
		}, function () {
			return [];
		});
	}

	function upsertTokenValue(current, token) {
		var parts = (current || '').split(',').map(function (s) { return $.trim(s); }).filter(Boolean);
		if (parts.indexOf(token) === -1) {
			parts.push(token);
		}
		return parts.join(', ');
	}

	function attachAsyncPicker($input) {
		if (!$input || !$input.length || $input.data('asyncBound')) {
			return;
		}
		var source = String($input.data('asyncSource') || '');
		var isMultiple = String($input.data('asyncMultiple') || '0') === '1';
		if (!source) {
			return;
		}
		var showPickedLabels = source === 'products' || source === 'coupons';
		var labelMap = {};

		$input.data('asyncBound', true);
		var $menu = $('<div class="ap-async-menu" hidden></div>');
		var $picked = $('<div class="ap-async-picked" hidden></div>');
		$input.after($picked);
		$input.after($menu);

		var debounce = null;
		function selectedTokens() {
			if (isMultiple) {
				return String($input.val() || '').split(',').map(function (s) { return $.trim(s); }).filter(Boolean);
			}
			var single = $.trim(String($input.val() || ''));
			return single ? [single] : [];
		}

		function renderPicked() {
			if (!showPickedLabels) {
				return;
			}
			var tokens = selectedTokens();
			$picked.empty();
			if (!tokens.length) {
				$picked.prop('hidden', true);
				return;
			}
			tokens.forEach(function (token) {
				var label = labelMap[token] || token;
				$picked.append($('<span class="ap-async-picked__item"></span>').text(label));
			});
			$picked.prop('hidden', false);
		}

		function renderMenu(items) {
			$menu.empty();
			if (!items || !items.length) {
				$menu.prop('hidden', true);
				return;
			}
			items.forEach(function (item) {
				var label = item.label || item.value || '';
				var value = item.value || '';
				labelMap[value] = label;
				var $btn = $('<button type="button" class="ap-async-menu__item"></button>');
				$btn.attr('data-value', value).text(label);
				$menu.append($btn);
			});
			$menu.prop('hidden', false);
			renderPicked();
		}

		function runSearch() {
			var term = String($input.val() || '');
			if (isMultiple) {
				var chunks = term.split(',');
				term = $.trim(chunks[chunks.length - 1] || '');
			}
			fetchPickerOptions(source, term).then(renderMenu);
		}

		$input.on('input focus', function () {
			clearTimeout(debounce);
			debounce = setTimeout(runSearch, 180);
		});

		$menu.on('click', '.ap-async-menu__item', function () {
			var value = String($(this).data('value') || '');
			if (!value) {
				return;
			}
			if (isMultiple) {
				$input.val(upsertTokenValue($input.val(), value));
			} else {
				$input.val(value);
			}
			$input.trigger('change');
			$menu.prop('hidden', true);
			renderPicked();
		});

		$input.on('change blur', renderPicked);

		$(document).on('click', function (e) {
			if (e.target === $input[0] || $.contains($menu[0], e.target)) {
				return;
			}
			$menu.prop('hidden', true);
		});

		if (showPickedLabels) {
			var current = selectedTokens();
			if (current.length) {
				fetchPickerOptions(source, '', current).then(function (items) {
					(items || []).forEach(function (item) {
						if (item && item.value) {
							labelMap[item.value] = item.label || item.value;
						}
					});
					renderPicked();
				});
			} else {
				renderPicked();
			}
		}
	}

	function initAsyncPickers($scope) {
		var $root = $scope && $scope.length ? $scope : $(document);
		$root.find('.ap-async-input').each(function () {
			attachAsyncPicker($(this));
		});
	}

	function scrollToStorySection(selector) {
		if (!selector) {
			return;
		}
		if ($('#ap-play-form').hasClass('ap-guided-mode')) {
			var stepMap = {
				'#ap-section-if': 'trigger',
				'#ap-section-then-wait': 'timing',
				'#ap-section-do': 'action',
				'#ap-conditions-body': 'review',
			};
			var step = stepMap[selector];
			if (step) {
				var $item = $('.ap-guided-stepper__item[data-guided-step="' + step + '"]');
				if ($item.length) {
					$item.trigger('click');
				}
				return;
			}
		}
		var $target = $(selector).first();
		if (!$target.length) {
			return;
		}
		var y = $target.offset().top - 110;
		$('html, body').animate({ scrollTop: y }, 220);
		$target.addClass('is-focus-target');
		window.setTimeout(function () {
			$target.removeClass('is-focus-target');
		}, 600);
	}

	// -------------------------------------------------------------------------
	// Trigger selection (free Pro teasers + ghost upgrade gate)
	// -------------------------------------------------------------------------

	function syncGhostTriggerUI(slug) {
		var $gate = $('#ap-ghost-gate');
		if (!$gate.length) {
			return;
		}
		var triggerCfg = (window.cartcueAdmin && window.cartcueAdmin.triggers) || {};
		var cfgTrigger = slug && triggerCfg[slug] ? triggerCfg[slug] : null;
		var isGhost = cfgTrigger && cfgTrigger.is_ghost;
		if (isGhost) {
			$gate.show().html(cfgTrigger.upgrade_html || '');
			$('#ap-trigger-settings').hide();
			$('#ap-ghost-save-hint').show();
			$('#ap-play-form button[type="submit"]').prop('disabled', true);
		} else {
			$gate.hide();
			$('#ap-trigger-settings').show();
			$('#ap-ghost-save-hint').hide();
			$('#ap-play-form button[type="submit"]').prop('disabled', false);
			if (typeof syncTriggerSettings === 'function') {
				syncTriggerSettings();
			}
		}
	}

	$(document).on('click', '.ap-trigger-card.is-pro', function (e) {
		if ($(this).find('input.ap-trigger-radio').length) {
			return;
		}
		e.preventDefault();
		$('.ap-trigger-card').removeClass('is-selected');
		$(this).addClass('is-selected');
		syncGhostTriggerUI($(this).data('trigger-slug') || '');
		syncSetupChecklist();
	});

	$(document).on('change', 'input[name="trigger_slug"]', function () {
		$('.ap-trigger-card').removeClass('is-selected');
		$(this).closest('.ap-trigger-card').addClass('is-selected');
		syncGhostTriggerUI($(this).val() || '');
		syncSetupChecklist();
	});

	// -------------------------------------------------------------------------
	// Timing pills
	// -------------------------------------------------------------------------
	function syncTimingPillA11y() {
		$('.ap-timing-pill').attr('aria-pressed', 'false');
		$('.ap-timing-pill.is-selected').attr('aria-pressed', 'true');
	}

	$(document).on('click', '.ap-timing-pill', function () {
		if (!$('#ap-timing-type').data('auto-selecting')) {
			$('#ap-timing-type').data('user-modified', true);
		} else {
			$('#ap-timing-type').data('user-modified', true);
		}
		$('.ap-timing-pill').find('.ap-timing-recommended').remove();

		var isCustomToggle = $(this).hasClass('ap-timing-pill--custom-toggle');

		if (isCustomToggle) {
			$('.ap-timing-pill').not('.ap-timing-pill--custom-toggle').removeClass('is-selected');
			$(this).addClass('is-selected');
			syncTimingPillA11y();
			$('#ap-timing-custom-panel').addClass('is-open');
			storyRefresh();
			return;
		}

		$('.ap-timing-pill').removeClass('is-selected');
		$(this).addClass('is-selected');
		syncTimingPillA11y();
		var inCustomPanel = $(this).closest('#ap-timing-custom-panel').length > 0;
		if (inCustomPanel) {
			$('#ap-timing-custom-panel').addClass('is-open');
		} else {
			$('#ap-timing-custom-panel').removeClass('is-open');
		}

		var type  = $(this).data('type');
		var value = $(this).data('value');
		var unit  = $(this).data('unit');

		$('#ap-timing-type').val(type);
		if (type === 'schedule_time') {
			$('#ap-schedule-time-row').show();
		} else {
			$('#ap-schedule-time-row').hide();
		}
		$('#ap-delay-value').val(value);
		$('#ap-delay-unit').val(unit);
		storyRefresh();
	});

	$('#ap-custom-timing-btn').on('click', function () {
		if (!$('#ap-timing-type').data('auto-selecting')) {
			$('#ap-timing-type').data('user-modified', true);
		}
		$('.ap-timing-pill').find('.ap-timing-recommended').remove();

		var val  = parseInt($('#ap-custom-val').val(), 10)  || 1;
		var unit = $('#ap-custom-unit').val() || 'hours';
		$('.ap-timing-pill').not('.ap-timing-pill--custom-toggle').removeClass('is-selected');
		$('.ap-timing-pill--custom-toggle').addClass('is-selected');
		syncTimingPillA11y();
		$('#ap-timing-custom-panel').addClass('is-open');
		$('#ap-schedule-time-row').hide();
		$('#ap-timing-type').val('delay');
		$('#ap-delay-value').val(val);
		$('#ap-delay-unit').val(unit);
		storyRefresh();
	});

	$(document).on('change', '#ap-schedule-time', function () {
		storyRefresh();
	});

	// -------------------------------------------------------------------------
	// Conditions toggle
	// -------------------------------------------------------------------------

	$('#ap-conditions-toggle').on('click', function () {
		var $body = $('#ap-conditions-body');
		setCollapseState($body, $(this), !$body.hasClass('is-open'));
	});

	$('#ap-advanced-settings-toggle').on('click', function () {
		var $body = $('#ap-advanced-settings-body');
		setCollapseState($body, $(this), !$body.hasClass('is-open'));
	});


	$(document).on('click', '.ap-story-segment--clickable', function () {
		var step = $(this).data('guidedStep');
		if (step && $('#ap-play-form').hasClass('ap-guided-mode')) {
			var $item = $('.ap-guided-stepper__item[data-guided-step="' + step + '"]');
			if ($item.length) {
				$item.trigger('click');
				return;
			}
		}
		scrollToStorySection($(this).data('scrollTarget'));
	});

	// -------------------------------------------------------------------------
	// Rules (conditions)
	// -------------------------------------------------------------------------

	var ruleIndex = $('#ap-rules-list .ap-rule-row').length;

	$('#ap-add-rule').on('click', function () {
		var idx  = ruleIndex++;
		var $row = buildRuleRow(idx);
		$('#ap-rules-list .ap-rules-empty').remove();
		$('#ap-rules-list').append($row);
	});

	$(document).on('click', '.ap-remove-rule', function () {
		$(this).closest('.ap-rule-row').remove();
		if (typeof window.apSyncRulesEmpty === 'function') {
			window.apSyncRulesEmpty();
		}
	});

	$(document).on('change', '.ap-rule-slug', function () {
		var $row = $(this).closest('.ap-rule-row');
		var idx  = $row.data('index');
		var slug = $(this).val();
		rebuildRuleControls($row, idx, slug);
	});

	function buildRuleRow(idx) {
		var $row  = $('<div class="ap-rule-row ap-rule-row--sentence"></div>').data('index', idx);
		$row.append($('<span class="ap-rule-prefix"></span>').text((cfg.editor && cfg.editor.rule_prefix) || 'Customer'));
		var $slug = $('<select class="ap-select ap-rule-slug"></select>').attr('name', 'rules[' + idx + '][slug]');
		$slug.append($('<option value="">— Choose a filter —</option>'));
		$.each(rules, function (slug, rule) {
			$slug.append($('<option></option>').val(slug).text(rule.label));
		});
		var $del = $('<button type="button" class="ap-icon-btn ap-remove-rule">✕</button>');
		$row.append($slug, $del);
		return $row;
	}

	function rebuildRuleControls($row, idx, slug) {
		$row.find('.ap-rule-op, .ap-rule-val').remove();
		if (!slug || !rules[slug]) { return; }

		var rule = rules[slug];
		var $del = $row.find('.ap-remove-rule');

		// Operator select.
		var $op = $('<select class="ap-select ap-rule-op"></select>').attr('name', 'rules[' + idx + '][operator]');
		$.each(rule.operators || {}, function (k, l) { $op.append($('<option></option>').val(k).text(l)); });
		$op.insertBefore($del);

		// Value field.
		if ('hidden' !== rule.value_type) {
			if ('select' === rule.value_type) {
				var $sel = $('<select class="ap-select ap-rule-val"></select>').attr('name', 'rules[' + idx + '][value]');
				$.each(rule.value_options || {}, function (k, l) { $sel.append($('<option></option>').val(k).text(l)); });
				$sel.insertBefore($del);
			} else if ('async_select' === rule.value_type) {
				var $ain = $('<input class="ap-input ap-rule-val ap-async-input">').attr({
					type: 'text',
					name: 'rules[' + idx + '][value]',
					placeholder: rule.placeholder || ''
				});
				if (rule.value_source) {
					$ain.attr('data-async-source', rule.value_source);
				}
				$ain.attr('data-async-multiple', rule.value_multiple ? '1' : '0');
				$ain.insertBefore($del);
				attachAsyncPicker($ain);
			} else {
				var itype = rule.value_type === 'number' ? 'number' : 'text';
				$('<input class="ap-input ap-rule-val">').attr({ type: itype, name: 'rules[' + idx + '][value]' }).insertBefore($del);
			}
		}
	}

	// -------------------------------------------------------------------------
	// Actions
	// -------------------------------------------------------------------------

	var actionIndex = $('#ap-actions-list .ap-action-card').length;

	$('#ap-add-action').on('click', function () {
		var $card = buildActionCard(actionIndex++);
		$('#ap-actions-list').append($card);
		storyRefresh();
		syncPreviewBtn();
		syncSetupChecklist();
	});

	$(document).on('click', '.ap-remove-action', function () {
		if (!window.confirm('Remove this action and its content?')) {
			return;
		}
		$(this).closest('.ap-action-card').remove();
		storyRefresh();
		syncPreviewBtn();
		syncSetupChecklist();
	});

	$(document).on('change', '.ap-action-type', function () {
		var $card = $(this).closest('.ap-action-card');
		var idx   = $card.data('index');
		var slug  = $(this).val();
		if (!$card.find('.ap-action-fields').length) {
			$card.append($('<div class="ap-action-fields"></div>'));
		}
		renderActionFields($card, idx, slug);
		storyRefresh();
		syncPreviewBtn();
		syncSetupChecklist();
	});
	$(document).on('change', '#ap-actions-list .ap-action-fields select', function () {
		storyRefresh();
	});

	function syncPreviewBtn() {
		var hasEmail = false;
		$('.ap-action-type').each(function () {
			if ($(this).val() === 'send_email') {
				hasEmail = true;
			}
		});
		var $btn = $('.ap-preview-btn');
		if (!$btn.length) {
			return;
		}
		$btn.toggle(hasEmail);
	}

	function buildActionCard(idx) {
		if (typeof window.apBuildActionCardOverride === 'function') {
			return window.apBuildActionCardOverride(idx);
		}
		var $card = $('<div class="ap-action-card"></div>').data('index', idx);
		var $hdr  = $('<div class="ap-action-card__header"></div>');
		var $type = $('<select class="ap-select ap-action-type"></select>').attr('name', 'actions[' + idx + '][type]');
		$type.append($('<option value="">— Choose an action —</option>'));
		$.each(actions, function (slug, action) {
			$type.append($('<option></option>').val(slug).text(action.label));
		});
		var $del = $('<button type="button" class="ap-icon-btn ap-remove-action">✕</button>');
		$hdr.append($type, $del);
		$card.append($hdr, $('<div class="ap-action-fields"></div>'));
		return $card;
	}

	function buildSubjectTagsControls(idx, fieldKey) {
		fieldKey = fieldKey || 'subject';
		var quickTags = cfg.quickTags || {
			'{{customer.first_name}}': 'First name',
			'{{customer.last_name}}': 'Last name',
			'{{customer.email}}': 'Email',
			'{{order.number}}': 'Order number',
			'{{order.total}}': 'Order total',
			'{{cart.total}}': 'Cart total',
			'{{cart.recover_url}}': 'Recovery link',
			'{{coupon.code}}': 'Coupon code',
			'{{shop.name}}': 'Shop name'
		};
		var editor = cfg.editor || {};
		var tagsLabel = editor.tags_btn || '{ } Tags';
		var tagsTitle = editor.tags_title || 'Insert a magic tag';
		var seeAllLabel = editor.tags_see_all || 'See all tags';

		var $btn = $('<button type="button" class="ap-tags-btn"></button>')
			.attr('data-field-key', fieldKey)
			.attr('title', tagsTitle)
			.append($('<i class="ti ti-braces" aria-hidden="true"></i>'))
			.append(document.createTextNode(' ' + tagsLabel));

		var $popover = $('<div class="ap-tags-popover"></div>')
			.attr('id', 'ap-tags-popover-' + idx + '-' + fieldKey)
			.prop('hidden', true);

		$.each(quickTags, function (tag, label) {
			$popover.append(
				$('<button type="button" class="ap-tag-insert-btn"></button>')
					.attr('data-tag', tag)
					.append($('<code></code>').text(tag))
					.append($('<span></span>').text(label))
			);
		});
		$popover.append(
			$('<button type="button" class="ap-tags-see-all"></button>')
				.attr('data-open-tags-panel', '')
				.text(seeAllLabel)
		);

		return { $btn: $btn, $popover: $popover };
	}
	window.apBuildSubjectTagsControls = buildSubjectTagsControls;

	function renderActionFields($card, idx, slug) {
		var $fields = $card.find('.ap-action-fields');
		var cardEl = $card.get(0);
		if (cardEl) {
			delete cardEl.dataset.builderMounted;
		}
		$card.removeAttr('data-email-enhanced');
		$fields.empty();
		if (!slug || !actions[slug]) { return; }

		(actions[slug].fields || []).forEach(function (f) {
			if (f.type === 'hidden') {
				$fields.append(
					$('<input type="hidden">')
						.attr('name', 'actions[' + idx + '][settings][' + f.key + ']')
						.val(f.default || '')
				);
				return;
			}

			var $row   = $('<div class="ap-field-row"></div>');
			var $label = $('<label class="ap-field-label"></label>').text(f.label);
			var name   = 'actions[' + idx + '][settings][' + f.key + ']';
			var $ctrl;

			if (f.type === 'textarea') {
				$ctrl = $('<textarea class="ap-textarea"></textarea>').attr({ name: name, rows: f.rows || 5, placeholder: f.placeholder || '' }).val(f.default || '');
			} else if (f.type === 'select') {
				$ctrl = $('<select class="ap-select"></select>').attr('name', name);
				$.each(f.options || {}, function (k, l) { $ctrl.append($('<option></option>').val(k).text(l)); });
				$ctrl.val(f.default || '');
			} else {
				$ctrl = $('<input class="ap-input">').attr({ type: f.type || 'text', name: name, placeholder: f.placeholder || '' }).val(f.default || '');
				if (f.async_source) {
					$ctrl.addClass('ap-async-input')
						.attr('data-async-source', f.async_source)
						.attr('data-async-multiple', f.async_multiple ? '1' : '0');
				}
			}
			$row.append($label, $ctrl);
			if (f.description) {
				$row.append($('<p class="ap-field-hint"></p>').text(f.description));
			}
			if (f.key === 'subject') {
				var tags = buildSubjectTagsControls(idx, f.key);
				$row.append(tags.$btn, tags.$popover);
				if (!$row.find('.ap-field-hint').length) {
					$row.append('<p class="ap-field-hint">Keep it short and personal. Example: “Hey {{customer.first_name|there}}, your cart is waiting”.</p>');
				}
			}
			$fields.append($row);
			if ($ctrl.hasClass('ap-async-input')) {
				attachAsyncPicker($ctrl);
			}
		});

		if (!cfg.isPro && actions[slug].pro_feature_labels && actions[slug].pro_feature_labels.length) {
			if (slug === 'create_coupon') {
				var $upsell = $('<div class="ap-action-pro-upsell"></div>');
				$upsell.append($('<p class="ap-action-pro-upsell__title"></p>').text('Need unique codes per customer?'));
				var $list = $('<ul class="ap-action-pro-upsell__list"></ul>');
				actions[slug].pro_feature_labels.forEach(function (label) {
					$list.append($('<li></li>').text(label));
				});
				$upsell.append($list);
				$fields.append($upsell);
			} else {
				actions[slug].pro_feature_labels.forEach(function (label) {
					var $row = $('<div class="ap-field-row ap-field-row--locked"></div>');
					$row.append(
						$('<label class="ap-field-label"></label>').text(label),
						$('<div class="ap-pro-lock"><i class="ti ti-lock" aria-hidden="true"></i> Pro</div>')
					);
					$fields.append($row);
				});
			}
		}

		$fields.append(buildActionConditionFields(idx));

	}
	window.renderActionFields = renderActionFields;

	function buildActionConditionFields(idx, condition) {
		var cfgCondition = condition || {};
		var enabled = !!cfgCondition.enabled;
		var field = cfgCondition.field || 'order_total';
		var operator = cfgCondition.operator || 'gt';
		var value = cfgCondition.value || '';
		var fieldName = 'actions[' + idx + '][condition][field]';
		var operatorName = 'actions[' + idx + '][condition][operator]';
		var valueName = 'actions[' + idx + '][condition][value]';
		var enabledName = 'actions[' + idx + '][condition][enabled]';
		var $wrap = $('<div class="ap-action-condition" data-condition-row></div>');
		if (enabled) {
			$wrap.addClass('is-open');
		}

		var $toggle = $('<label class="ap-checkbox-label"></label>')
			.append(
				$('<input type="checkbox" class="ap-action-cond-enabled">')
					.attr('name', enabledName)
					.attr('value', '1')
					.prop('checked', enabled)
			)
			.append(document.createTextNode(' Run this action only when a condition matches'));

		var $body = $('<div class="ap-action-condition__body"></div>');
		var $field = $('<select class="ap-select ap-action-cond-field"></select>').attr('name', fieldName);
		[
			['order_total', 'Order total'],
			['order_currency', 'Order currency'],
			['customer_email', 'Customer email'],
			['customer_total_spent', 'Customer total spent']
		].forEach(function (entry) {
			$field.append($('<option></option>').val(entry[0]).text(entry[1]));
		});
		$field.val(field);

		var $operator = $('<select class="ap-select ap-action-cond-operator"></select>').attr('name', operatorName);
		[
			['gt', 'is greater than'],
			['gte', 'is greater than or equal to'],
			['lt', 'is less than'],
			['lte', 'is less than or equal to'],
			['equals', 'equals'],
			['not_equals', 'does not equal'],
			['contains', 'contains']
		].forEach(function (entry) {
			$operator.append($('<option></option>').val(entry[0]).text(entry[1]));
		});
		$operator.val(operator);

		var $value = $('<input type="text" class="ap-input ap-action-cond-value">')
			.attr('name', valueName)
			.attr('placeholder', 'Value')
			.val(value);

		$body.append($field, $operator, $value);
		$wrap.append($toggle, $body);
		return $wrap;
	}

	// -------------------------------------------------------------------------
	// Variable token click-to-copy
	// -------------------------------------------------------------------------

	$(document).on('click', '.ap-var-item', function () {
		var token = $(this).data('token');
		if (!token) { return; }
		if (navigator.clipboard) {
			navigator.clipboard.writeText(token).then(function () {
				var $el = $('.ap-var-item[data-token="' + token + '"]');
				$el.css('background', '#534AB7');
				$el.find('.ap-var-desc').css('color', '#fff');
				setTimeout(function () {
					$el.css('background', '');
					$el.find('.ap-var-desc').css('color', '');
				}, 800);
			});
		}
	});

	// -------------------------------------------------------------------------
	// Init
	// -------------------------------------------------------------------------

	syncPreviewBtn();
	storyRefresh();
	setEditorMode();
	initAsyncPickers($(document));

}(jQuery));

// ============================================================
// v1.3+ additions (noConflict: $ only exists inside this IIFE)
// ============================================================
(function ($) {
	'use strict';

	var cfg = window.cartcueAdmin || {};
	var triggers = cfg.triggers || {};
	var actions = cfg.actions || {};

	function setStorySegmentText($el, text) {
		if (window.apCartCuePlayUx && typeof window.apCartCuePlayUx.setStorySegmentText === 'function') {
			window.apCartCuePlayUx.setStorySegmentText($el, text);
			return;
		}
		if (!$el || !$el.length) {
			return;
		}
		var $inner = $el.find('.ap-story-card__text');
		if ($inner.length) {
			$inner.text(text);
		} else {
			$el.text(text);
		}
	}

	function syncSetupChecklist() {
		if (typeof window.apSyncSetupChecklist === 'function') {
			window.apSyncSetupChecklist();
		}
	}

	function renderTimingTimeline() {
		var $timeline = $('#ap-timing-timeline');
		if (!$timeline.length) {
			return;
		}

		var timingType = $('#ap-timing-type').val() || 'immediate';
		var delayVal   = parseInt($('#ap-delay-value').val(), 10) || 0;
		var delayUnit  = $('#ap-delay-unit').val() || 'hours';
		var parts      = [];

		parts.push('<span class="ap-tl-node ap-tl-node--trigger">Trigger</span>');

		if (timingType === 'delay' && delayVal > 0) {
			parts.push('<span class="ap-tl-sep">→</span>');
			parts.push('<span class="ap-tl-node ap-tl-node--wait">wait ' + delayVal + ' ' + delayUnit + '</span>');
		}
		parts.push('<span class="ap-tl-sep">→</span>');
		parts.push('<span class="ap-tl-node ap-tl-node--action">Email 1</span>');

		$('#ap-sequence-builder .ap-sequence-step').each(function (i) {
			var d = parseInt($(this).find('.ap-seq-delay').val(), 10) || 0;
			var u = $(this).find('.ap-seq-unit').val() || 'days';
			if (d > 0) {
				parts.push('<span class="ap-tl-sep">→</span>');
				parts.push('<span class="ap-tl-node ap-tl-node--wait">wait ' + d + ' ' + u + '</span>');
			}
			parts.push('<span class="ap-tl-sep">→</span>');
			parts.push('<span class="ap-tl-node ap-tl-node--action">Email ' + (i + 2) + '</span>');
		});

		var html =
			'<div class="ap-tl-label">Your send schedule:</div>' +
			'<div class="ap-tl-track">' + parts.join('') + '</div>';
		$timeline.html(html).show();
		$('#ap-review-timeline').html(html).show();
	}
	window.renderTimingTimeline = renderTimingTimeline;

	// ---- Story bar: natural-language sentences from triggers_config ----
	function updateStory() {
		var $form = $('#ap-play-form');
		if ( ! $form.length ) { return; }

		var triggerSlug = $('input[name="trigger_slug"]:checked').val() || '';
		var triggerCfg  = triggerSlug && triggers[triggerSlug] ? triggers[triggerSlug] : null;
		var sentence    = triggerCfg ? triggerCfg.sentence : '';

		var timingType  = $('#ap-timing-type').val() || 'immediate';
		var delayVal    = $('#ap-delay-value').val() || '';
		var delayUnit   = $('#ap-delay-unit').val()  || '';

		var $when = $('#ss-when');
		if (sentence) {
			setStorySegmentText($when, sentence);
			$when.addClass('ap-story-segment--filled').removeClass('ap-story-segment--muted');
		} else {
			setStorySegmentText($when, 'something happens');
			$when.removeClass('ap-story-segment--filled').addClass('ap-story-segment--muted');
		}

		var $wait = $('#ss-wait');
		if ('delay' === timingType && delayVal) {
			var dphrase = window.apCartCuePlayUx && window.apCartCuePlayUx.formatDelayWait();
			setStorySegmentText($wait, dphrase || ('wait ' + delayVal + ' ' + delayUnit));
			$wait.addClass('ap-story-segment--filled').removeClass('ap-story-segment--muted');
		} else if ('schedule_time' === timingType) {
			var tmg = $('#ap-schedule-time').val() || '09:00';
			setStorySegmentText($wait, 'at ' + tmg + ' (store time)');
			$wait.addClass('ap-story-segment--filled').removeClass('ap-story-segment--muted');
		} else {
			setStorySegmentText($wait, 'immediately');
			$wait.removeClass('ap-story-segment--filled').addClass('ap-story-segment--muted');
		}

		if (window.apCartCuePlayUx) {
			window.apCartCuePlayUx.syncThen(actions);
			window.apCartCuePlayUx.syncStep4();
		}
		renderTimingTimeline();
	}
	window.apUpdateStory = updateStory;

	var debouncedStoryRefresh = debounce(updateStory, 300);
	$(document).on(
		'change keyup',
		'#ap-play-form .ap-name-input, #ap-play-form select, #ap-play-form input:not([type="hidden"]), #ap-play-form textarea',
		debouncedStoryRefresh
	);

	function ensureDraftToast() {
		var $toast = $('#ap-draft-toast');
		if (!$toast.length) {
			$toast = $('<div id="ap-draft-toast" class="ap-draft-toast" role="status" aria-live="polite" hidden></div>');
			$('body').append($toast);
		}
		return $toast;
	}

	function showDraftToast(message) {
		var $toast = ensureDraftToast();
		$toast.text(message).prop('hidden', false).addClass('is-visible');
		window.clearTimeout(showDraftToast._timer);
		showDraftToast._timer = window.setTimeout(function () {
			$toast.removeClass('is-visible');
			window.setTimeout(function () {
				$toast.prop('hidden', true);
			}, 200);
		}, 2200);
	}

	function initDraftAutosave() {
		var $form = $('#ap-play-form');
		if (!$form.length || String($form.data('isNew')) !== '1') {
			return;
		}
		var draftKey = 'cartcue_play_draft_' + String($form.data('automationType') || 'event');
		var draftLabel = (cfg.editor && cfg.editor.draft_saved) || 'Draft saved';

		window.setInterval(function () {
			var triggerSlug = $('input[name="trigger_slug"]:checked').val() || '';
			var draft = {
				name: $.trim($('#ap-play-name').val() || ''),
				trigger_slug: triggerSlug,
				timing_type: $('#ap-timing-type').val() || 'immediate',
				saved_at: Date.now()
			};
			try {
				window.localStorage.setItem(draftKey, JSON.stringify(draft));
				showDraftToast(draftLabel);
			} catch (err) {
				// Ignore quota / privacy mode errors.
			}
		}, 8000);
	}

	function applyDefaultEditorMode() {
		var $form = $('#ap-play-form');
		if (!$form.length) {
			return;
		}
		var defaultMode = cfg.defaultMode || 'guided';
		if ('guided' === defaultMode && !$form.hasClass('ap-editor-layout-advanced')) {
			$form.attr('data-editor-layout', 'guided');
		}
	}

	function syncTriggerSettings() {
		var slug = $('input[name="trigger_slug"]:checked').val() || '';
		$('#ap-trigger-settings').show();
		$('.ap-tsettings-group').removeClass('is-visible');
		$('.ap-tsettings-group[data-trigger="' + slug + '"]').addClass('is-visible');
	}

	function syncRulesEmptyState() {
		var $list = $('#ap-rules-list');
		if (!$list.length) {
			return;
		}
		var ed = cfg.editor || {};
		var hint = ed.rules_empty || 'No audience filters — this play runs for everyone.';
		if ($list.find('.ap-rule-row').length) {
			$list.find('.ap-rules-empty').remove();
		} else if (!$list.find('.ap-rules-empty').length) {
			$list.prepend('<p class="ap-rules-empty">' + $('<span>').text(hint).html() + '</p>');
		}
	}

	function debounce(fn, wait) {
		var timer = null;
		return function () {
			var ctx = this;
			var args = arguments;
			window.clearTimeout(timer);
			timer = window.setTimeout(function () {
				fn.apply(ctx, args);
			}, wait);
		};
	}

	function getTriggerSlug() {
		return $('input[name="trigger_slug"]:checked').val() || $('[name="trigger_slug"]').val() || '';
	}

	function collectRulesFromDom() {
		var collected = [];
		$('#ap-rules-list .ap-rule-row').each(function () {
			var $row = $(this);
			var slug = $row.find('.ap-rule-slug').val();
			if (!slug) {
				return;
			}
			collected.push({
				slug: slug,
				operator: $row.find('.ap-rule-op').val() || 'equals',
				value: $row.find('.ap-rule-val').val() || ''
			});
		});
		return collected;
	}

	function fetchAudiencePreview() {
		if (!cfg.nonces || !cfg.nonces.preview_audience) {
			return;
		}
		var $counter = $('#cartcue-audience-count');
		if (!$counter.length || !$('#ap-play-form').length) {
			return;
		}
		var triggerSlug = getTriggerSlug();
		if (!triggerSlug) {
			$counter.text('');
			return;
		}

		$counter.text('Counting…');
		$.post(cfg.ajaxUrl || ajaxurl, {
			action: 'cartcue_preview_audience',
			nonce: cfg.nonces.preview_audience,
			trigger_slug: triggerSlug,
			rules: JSON.stringify(collectRulesFromDom())
		}).done(function (res) {
			if (!res || !res.success || !res.data) {
				$counter.text('Could not count.');
				return;
			}
			var data = res.data;
			var count = parseInt(data.count, 10) || 0;
			var scanned = parseInt(data.scanned, 10) || 0;
			var msg = count.toLocaleString() + ' customers match';
			if (count > 0) {
				msg += ' your current audience filters.';
			}
			if (scanned >= 5000) {
				msg += ' (sample of first 5,000 records)';
			}
			$counter.text(msg);
		}).fail(function () {
			$counter.text('Could not count.');
		});
	}

	var debouncedAudiencePreview = debounce(fetchAudiencePreview, 600);

	function setPlayName(value, fromUser) {
		var $canonical = $('#ap-play-name');
		$canonical.val(value);
		if (fromUser) {
			$canonical.data('autofilled', false);
		}
		$('#ap-play-name-review').val(value);
	}

	$(document).on('change', 'input[name="trigger_slug"]', function () {
		(function autoFillName() {
			var triggerNames = {
				cart_abandoned:           'Abandoned Cart Recovery',
				checkout_started:         'Checkout Reminder',
				order_paid:               'Post-Purchase Thank You',
				customer_created:         'New Customer Welcome',
				customer_win_back:        'Win-Back Lapsed Customers',
				customer_never_purchased: 'Never-Purchased Nudge',
				order_status_changed:     'Order Status Update',
				payment_failed:           'Payment Failed Recovery',
				new_review:               'Review Request'
			};
			var $nameInput = $('#ap-play-name');
			var slug       = $('input[name="trigger_slug"]:checked').val() || '';
			var suggestion = triggerNames[slug] || '';
			var current    = $.trim($nameInput.val() || '');
			var wasAuto    = $nameInput.data('autofilled') === true;

			if (suggestion && (current === '' || wasAuto)) {
				$nameInput.val(suggestion).data('autofilled', true);
				setPlayName(suggestion, false);
				syncSetupChecklist();
			}
		})();

		(function autoSelectTiming() {
			var timingDefaults = {
				cart_abandoned:           { type: 'delay', value: 1,  unit: 'hours'   },
				payment_failed:           { type: 'delay', value: 30, unit: 'minutes' },
				new_review:               { type: 'delay', value: 1,  unit: 'days'    },
				customer_win_back:        { type: 'delay', value: 7,  unit: 'days'    },
				customer_created:         { type: 'immediate' },
				order_paid:               { type: 'immediate' },
				order_status_changed:     { type: 'immediate' }
			};
			var slug = $('input[name="trigger_slug"]:checked').val() || '';
			var def  = timingDefaults[slug];
			if (!def || $('#ap-timing-type').data('user-modified')) {
				return;
			}

			$('#ap-timing-type').data('auto-selecting', true);
			if (def.type === 'immediate') {
				$('.ap-timing-pill[data-type="immediate"]').first().trigger('click');
			} else {
				var $match = $('.ap-timing-pill[data-value="' + def.value + '"][data-unit="' + def.unit + '"]');
				if ($match.length) {
					$match.first().trigger('click');
				}
			}
			$('#ap-timing-type').data('auto-selecting', false);

			$('.ap-timing-pill').find('.ap-timing-recommended').remove();
			$('.ap-timing-pill.is-selected').append(
				'<span class="ap-timing-recommended" ' +
				'style="font-size:10px;margin-left:5px;opacity:0.7;font-weight:500">recommended</span>'
			);
		})();

		syncTriggerSettings();
		updateStory();
		fetchAudiencePreview();
		syncSetupChecklist();
	});

	window.apSyncRulesEmpty = syncRulesEmptyState;

	$(document).on('click', '.ap-freq-pill', function () {
		var maxRuns = $(this).data('maxRuns');
		var cooldown = $(this).data('cooldown');
		if (cooldown === 'custom') {
			cooldown = window.apGetCooldown ? window.apGetCooldown() : 30;
		}
		if (window.apSetFreq) {
			window.apSetFreq(maxRuns, cooldown, this);
		}
	});

	$(document).on('change', '#ap-cooldown-val', function () {
		var $opt = $(this).closest('.ap-freq-pill');
		if ($opt.length && window.apSetFreq) {
			window.apSetFreq(0, $(this).val(), $opt[0]);
		}
	});

	$(function () {
		$('.ap-story-segment--clickable').each(function () {
			if (!this.hasAttribute('tabindex')) {
				$(this).attr('tabindex', '0');
			}
		});
		if (typeof syncTimingPillA11y === 'function') {
			syncTimingPillA11y();
		} else {
			$('.ap-timing-pill').attr('aria-pressed', 'false');
			$('.ap-timing-pill.is-selected').attr('aria-pressed', 'true');
		}

		$(document).on('keydown', '.ap-story-segment--clickable', function (e) {
			if (e.key !== 'Enter' && e.key !== ' ') {
				return;
			}
			e.preventDefault();
			scrollToStorySection($(this).data('scrollTarget'));
		});

		syncTriggerSettings();
		updateStory();
		syncRulesEmptyState();
		fetchAudiencePreview();
		syncSetupChecklist();
		applyDefaultEditorMode();
		initDraftAutosave();
	});

	$(document).on('change input', '#ap-rules-list .ap-rule-row select, #ap-rules-list .ap-rule-row input', debouncedAudiencePreview);
	$(document).on('click', '#ap-add-rule, .ap-remove-rule', debouncedAudiencePreview);
	$(document).on('change', '.ap-action-cond-enabled', function () {
		var $row = $(this).closest('[data-condition-row]');
		$row.toggleClass('is-open', $(this).is(':checked'));
	});
	$(document).on('input', '#ap-play-name', function () {
		setPlayName($(this).val(), true);
		syncSetupChecklist();
	});

	$(document).on('input', '#ap-play-name-review', function () {
		setPlayName($(this).val(), true);
		syncSetupChecklist();
	});

	// ---- Email template preset (send_email action) -------------------
	$(document).on('change', 'select[name$="[email_preset]"]', function () {
		var previousValue = $(this).data('lastValue') || '';
		var presetKey = $(this).val();
		var presets   = (cfg.emailPresets || {});
		var preset    = presets[presetKey];
		if (!preset || !presetKey) {
			$(this).data('lastValue', presetKey || '');
			return;
		}
		var presetLabel = $(this).find('option:selected').text() || 'selected';
		if (!window.confirm('Replace your current email with "' + presetLabel + '" template? This cannot be undone.')) {
			$(this).val(previousValue);
			return;
		}
		var $card = $(this).closest('.ap-action-card');
		var bodyMode = $card.find('input[name$="[body_mode]"]').val();
		$card.find('[name$="[subject]"]').val(preset.subject || '');
		if (bodyMode !== 'builder') {
			$card.find('[name$="[body]"]').val(preset.body || '');
		}
		$(this).data('lastValue', presetKey);
	});

	$(document).on('change', 'select[name$="[template]"]', function () {
		var preset = String($(this).val() || 'custom');
		var $card = $(this).closest('.ap-action-card');
		if (!$card.length || preset === 'custom') {
			return;
		}
		var presetUrls = {
			zapier: 'https://hooks.zapier.com/hooks/catch/123456/example',
			make: 'https://hook.make.com/your-webhook-id',
			n8n: 'https://your-n8n-domain/webhook/cartcue',
			google_sheets: 'https://script.google.com/macros/s/your-script-id/exec',
			slack: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXX'
		};
		var knownUrls = Object.keys(presetUrls).map(function (key) { return presetUrls[key]; });
		var $url = $card.find('input[name$="[settings][url]"]');
		var current = String($url.val() || '').trim();
		if (!current || knownUrls.indexOf(current) !== -1) {
			$url.val(presetUrls[preset] || current);
		}
		var $method = $card.find('select[name$="[settings][method]"]');
		if ($method.length) {
			$method.val('POST');
		}
	});

	// ---- Test Play button ------------------------------------------
	function showTestToast(message) {
		var $toast = $('#ap-test-toast');
		if (!$toast.length || !message) {
			return;
		}
		$toast.text(message).prop('hidden', false).addClass('ap-test-toast--visible');
	}

	function persistTestResult(playId, message) {
		try {
			sessionStorage.setItem('cartcue_last_test', JSON.stringify({
				playId: playId,
				message: message,
				at: Date.now()
			}));
		} catch (e) {
			// Ignore storage errors.
		}
	}

	function restoreTestToast() {
		var $toast = $('#ap-test-toast');
		if (!$toast.length) {
			return;
		}
		try {
			var raw = sessionStorage.getItem('cartcue_last_test');
			if (!raw) {
				return;
			}
			var data = JSON.parse(raw);
			if (!data || !data.message || !data.at) {
				return;
			}
			if (Date.now() - data.at > 86400000) {
				sessionStorage.removeItem('cartcue_last_test');
				return;
			}
			var currentPlayId = parseInt($('#ap-test-btn').data('play'), 10) || 0;
			if (currentPlayId && data.playId && currentPlayId !== data.playId) {
				return;
			}
			showTestToast(data.message);
		} catch (e) {
			// Ignore parse errors.
		}
	}

	$(function () {
		restoreTestToast();
	});

	$(document).on('click', '#ap-test-btn', function () {
		var $btn   = $(this);
		var playId = parseInt($btn.data('play'), 10) || 0;
		var $res   = $('#ap-test-result');

		$btn.find('.ap-test-idle').hide();
		$btn.find('.ap-test-loading').show();
		$btn.prop('disabled', true);
		$res.hide();

		var testTo = $('#ap-test-to').val() || (cartcueAdmin && cartcueAdmin.adminEmail) || '';
		var payload = {
			action:  'cartcue_test_play',
			nonce:   cartcueAdmin.nonces.test_play,
			play_id: playId,
			test_to: testTo
		};

		if (!playId) {
			payload.trigger_slug = $('input[name="trigger_slug"]:checked').val() || '';
			payload.actions = JSON.stringify(apCollectInlineActions());
		}

		$.post(
			(window.cartcueAdmin && cartcueAdmin.ajaxUrl) || ajaxurl,
			payload,
			function (response) {
				$btn.find('.ap-test-idle').show();
				$btn.find('.ap-test-loading').hide();
				$btn.prop('disabled', false);

				if (response.success) {
					var msg = '✓ ' + response.data;
					$res.removeClass('ap-test-result--error')
					    .addClass('ap-test-result ap-test-result--success')
					    .text(msg)
					    .show();
					showTestToast(response.data);
					persistTestResult(playId, response.data);
				} else {
					$res.removeClass('ap-test-result--success')
					    .addClass('ap-test-result ap-test-result--error')
					    .text('✕ ' + response.data)
					    .show();
				}
			}
		);
	});

	// -------------------------------------------------------------------------
	// Multi-step sequence builder (play editor)
	// -------------------------------------------------------------------------
	var $root = $('#ap-sequence-builder');
	if ($root.length) {
	var actMap = cfg.actions || {};

	var sequenceSteps = $.isArray(window.apSequenceInitial) ? window.apSequenceInitial.slice() : [];
	if (!cfg.canUseBranching) {
		sequenceSteps = sequenceSteps.filter(function (step) {
			return step && step.step_type !== 'branch';
		});
	}

	function firstActionIndex() {
		var v = null;
		$('#ap-actions-list .ap-action-card').each(function () {
			var idx = $(this).data('index');
			if (idx === undefined || idx === null) {
				return;
			}
			if (v === null) {
				v = idx;
			}
		});
		return v !== null ? String(v) : '0';
	}

	function readStepsFromDOM() {
		var next = [];
		$('#ap-sequence-builder .ap-sequence-step').each(function () {
			var $row = $(this);
			if ($row.hasClass('ap-sequence-step--branch')) {
				next.push({
					step_type: 'branch',
					delay: parseInt($row.find('.ap-seq-delay').val(), 10) || 0,
					delay_unit: $row.find('.ap-seq-unit').val() || 'hours',
					rules: [{
						slug: $row.find('.ap-seq-branch-rule').val() || 'email_opened',
						operator: $row.find('.ap-seq-branch-op').val() || 'is',
						value: $row.find('.ap-seq-branch-val').val() || ''
					}],
					next_if_true: parseInt($row.find('.ap-seq-branch-true').val(), 10) || 0,
					next_if_false: parseInt($row.find('.ap-seq-branch-false').val(), 10) || 0
				});
				return;
			}
			next.push({
				step_type: 'action',
				action_index: $row.find('.ap-seq-action').val() || firstActionIndex(),
				delay: parseInt($row.find('.ap-seq-delay').val(), 10) || 0,
				delay_unit: $row.find('.ap-seq-unit').val() || 'hours'
			});
		});
		sequenceSteps = next;
	}

	function actionOptionsMarkup(selectedIdx) {
		var html = '';
		$('#ap-actions-list .ap-action-card').each(function () {
			var idx = $(this).data('index');
			if (idx === undefined || idx === null) {
				return;
			}
			var slug = $(this).find('.ap-action-type').val();
			var label = slug && actMap[slug] ? actMap[slug].label : (slug || '—');
			var $card = $('#ap-actions-list .ap-action-card[data-index="' + idx + '"]');
			var subject = $card.find('[name$="[subject]"]').val() || '';
			if (subject) {
				label += ' — ' + subject;
			}
			var sel = String(idx) === String(selectedIdx) ? ' selected' : '';
			html += '<option value="' + idx + '"' + sel + '>' + $('<span>').text(label).html() + '</option>';
		});
		return html;
	}

	var seqTxt = (cfg.seqStrings || {});

	function renderSequenceBuilder() {
		var $c = $('#ap-sequence-builder');
		$c.empty();
		if (!sequenceSteps.length) {
			$c.append('<p class="ap-step-sub ap-seq-empty">' + (seqTxt.emptyHint || '') + '</p>');
			if (window.apCartCuePlayUx) {
				window.apCartCuePlayUx.refresh();
			}
			return;
		}
		var thenRun = seqTxt.thenRun || 'Then run';
		var waitLbl = seqTxt.waitLabel || 'Wait';
		var rmLbl = seqTxt.removeStep || '';
		sequenceSteps.forEach(function (step, i) {
			var delay = step.delay != null ? step.delay : 1;
			var unit = step.delay_unit || 'hours';
			if (step.step_type === 'branch') {
				var rule = (step.rules && step.rules[0]) || { slug: 'email_opened', operator: 'is', value: '' };
				var branchRules = cfg.branchRules || [];
				var ruleOpts = '';
				branchRules.forEach(function (br) {
					ruleOpts += '<option value="' + br.slug + '"' + (br.slug === rule.slug ? ' selected' : '') + '>' + $('<span>').text(br.label).html() + '</option>';
				});
				var opOpts = '';
				branchRules.forEach(function (br) {
					if (br.slug !== rule.slug) { return; }
					Object.keys(br.operators || {}).forEach(function (opKey) {
						opOpts += '<option value="' + opKey + '"' + (opKey === rule.operator ? ' selected' : '') + '>' + $('<span>').text(br.operators[opKey]).html() + '</option>';
					});
				});
				var $row = $(
					'<div class="ap-sequence-step ap-sequence-step--branch" data-seq-index="' + i + '">' +
						'<div class="ap-seq-step__body">' +
							'<div class="ap-seq-line ap-seq-line--action">' +
								'<span class="ap-seq-badge">' + stepWord + ' ' + (i + 1) + '</span>' +
								'<span class="ap-seq-muted">' + $('<span>').text(seqTxt.branchLabel || 'If / Else').html() + '</span>' +
							'</div>' +
							'<div class="ap-seq-line">' +
								'<select class="ap-select ap-seq-branch-rule" name="sequence[' + i + '][rules][0][slug]">' + ruleOpts + '</select>' +
								'<select class="ap-select ap-seq-branch-op" name="sequence[' + i + '][rules][0][operator]">' + opOpts + '</select>' +
								'<input type="text" class="ap-input ap-seq-branch-val" name="sequence[' + i + '][rules][0][value]" value="' + $('<span>').text(rule.value || '').html() + '" placeholder="">' +
							'</div>' +
							'<div class="ap-seq-line ap-seq-line--wait">' +
								'<span class="ap-seq-muted">' + $('<span>').text(waitLbl).html() + '</span>' +
								'<input type="number" class="ap-input ap-input--tiny ap-seq-delay" name="sequence[' + i + '][delay]" min="0" value="' + delay + '">' +
								'<select class="ap-select ap-seq-unit" name="sequence[' + i + '][delay_unit]">' +
									'<option value="minutes">' + ((cfg.timingUnits || {}).minutes || 'minutes') + '</option>' +
									'<option value="hours">' + ((cfg.timingUnits || {}).hours || 'hours') + '</option>' +
									'<option value="days">' + ((cfg.timingUnits || {}).days || 'days') + '</option>' +
								'</select>' +
							'</div>' +
							'<div class="ap-seq-line">' +
								'<span class="ap-seq-muted">' + $('<span>').text(seqTxt.branchIf || 'If true → step').html() + '</span>' +
								'<input type="number" class="ap-input ap-input--tiny ap-seq-branch-true" name="sequence[' + i + '][next_if_true]" min="0" value="' + (step.next_if_true != null ? step.next_if_true : i + 1) + '">' +
								'<span class="ap-seq-muted">' + $('<span>').text(seqTxt.branchElse || 'Else → step').html() + '</span>' +
								'<input type="number" class="ap-input ap-input--tiny ap-seq-branch-false" name="sequence[' + i + '][next_if_false]" min="0" value="' + (step.next_if_false != null ? step.next_if_false : i + 2) + '">' +
								'<input type="hidden" name="sequence[' + i + '][step_type]" value="branch">' +
								'<button type="button" class="ap-icon-btn ap-remove-sequence-step">✕</button>' +
							'</div>' +
						'</div>' +
					'</div>'
				);
				$row.find('.ap-seq-unit').val(unit);
				$c.append($row);
				return;
			}
			var ai = step.action_index != null ? String(step.action_index) : firstActionIndex();
			var opts = actionOptionsMarkup(ai);
			if (!opts) {
				opts = '<option value="0">— ' + (seqTxt.needsAction || '') + ' —</option>';
			}
			var stepWord = seqTxt.step || 'Step';
			var $row = $(
				'<div class="ap-sequence-step" data-seq-index="' + i + '">' +
					'<div class="ap-seq-step__body">' +
						'<div class="ap-seq-line ap-seq-line--action">' +
							'<span class="ap-seq-badge">' + stepWord + ' ' + (i + 1) + '</span>' +
							'<span class="ap-seq-muted">' + $('<span>').text(thenRun).html() + '</span>' +
							'<select class="ap-select ap-seq-action" name="sequence[' + i + '][action_index]">' + opts + '</select>' +
							'<input type="hidden" name="sequence[' + i + '][step_type]" value="action">' +
						'</div>' +
						'<div class="ap-seq-line ap-seq-line--wait">' +
							'<span class="ap-seq-muted">' + $('<span>').text(waitLbl).html() + '</span>' +
							'<input type="number" class="ap-input ap-input--tiny ap-seq-delay" name="sequence[' + i + '][delay]" min="0" value="' + delay + '">' +
							'<select class="ap-select ap-seq-unit" name="sequence[' + i + '][delay_unit]">' +
								'<option value="minutes">' + ((cfg.timingUnits || {}).minutes || 'minutes') + '</option>' +
								'<option value="hours">' + ((cfg.timingUnits || {}).hours || 'hours') + '</option>' +
								'<option value="days">' + ((cfg.timingUnits || {}).days || 'days') + '</option>' +
							'</select>' +
							'<button type="button" class="ap-icon-btn ap-remove-sequence-step"' + (rmLbl ? ' aria-label="' + $('<span>').text(rmLbl).html() + '"' : '') + '>✕</button>' +
						'</div>' +
					'</div>' +
				'</div>'
			);
			$row.find('.ap-seq-unit').val(unit);
			$c.append($row);
		});
		if (window.apCartCuePlayUx) {
			window.apCartCuePlayUx.refresh();
		}
		renderTimingTimeline();
		if (window.apSequenceTimeline && typeof window.apSequenceTimeline.refresh === 'function') {
			window.apSequenceTimeline.refresh();
		}
	}

	renderSequenceBuilder();

	$('#ap-add-sequence-step').on('click', function () {
		readStepsFromDOM();
		var maxSeq = parseInt(cfg.maxSequenceSteps, 10) || 0;
		if (maxSeq > 0 && sequenceSteps.length >= maxSeq) {
			window.alert((cfg.seqStrings && cfg.seqStrings.limitReached) || 'Sequence step limit reached.');
			return;
		}
		var isFirstStep = sequenceSteps.length === 0;
		sequenceSteps.push({
			step_type: 'action',
			action_index: firstActionIndex(),
			delay: isFirstStep ? 0 : 1,
			delay_unit: 'hours'
		});
		renderSequenceBuilder();
	});

	$('#ap-add-sequence-branch').on('click', function () {
		if (!cfg.canUseBranching) {
			return;
		}
		readStepsFromDOM();
		var maxSeq = parseInt(cfg.maxSequenceSteps, 10) || 0;
		if (maxSeq > 0 && sequenceSteps.length >= maxSeq) {
			window.alert((cfg.seqStrings && cfg.seqStrings.limitReached) || 'Sequence step limit reached.');
			return;
		}
		var idx = sequenceSteps.length;
		sequenceSteps.push({
			step_type: 'branch',
			delay: 1,
			delay_unit: 'days',
			rules: [{ slug: 'email_opened', operator: 'is', value: '' }],
			next_if_true: idx + 1,
			next_if_false: idx + 2
		});
		renderSequenceBuilder();
	});

	$(document).on('click', '.ap-remove-sequence-step', function () {
		var i = $(this).closest('.ap-sequence-step').data('seq-index');
		readStepsFromDOM();
		sequenceSteps.splice(i, 1);
		renderSequenceBuilder();
	});

	$(document).on('change input', '.ap-seq-action, .ap-seq-delay, .ap-seq-unit', function () {
		readStepsFromDOM();
		if (window.apCartCuePlayUx) {
			window.apCartCuePlayUx.refresh();
		}
	});

	$(document).on('input', 'input[name*="[subject]"]', function () {
		if ($('#ap-sequence-builder').length) {
			readStepsFromDOM();
			renderSequenceBuilder();
		}
	});

	$(document).on('change', '.ap-action-type', function () {
		readStepsFromDOM();
		renderSequenceBuilder();
	});

	$(document).on('click', '#ap-add-action', function () {
		setTimeout(function () {
			readStepsFromDOM();
			renderSequenceBuilder();
		}, 0);
	});

	$(document).on('click', '.ap-remove-action', function () {
		setTimeout(function () {
			readStepsFromDOM();
			renderSequenceBuilder();
		}, 0);
	});
	}

})(jQuery);

// ============================================================
// v1.7 additions
// ============================================================

(function ($) {
	'use strict';

// ---- Preview email modal (play editor) ------------------------
var apPreviewDirty = false;

$(document).on('input change', '#ap-play-form :input', function () {
	apPreviewDirty = true;
});

function apGetPreviewCard() {
	var $emailCards = $('#ap-actions-list .ap-action-card').filter(function () {
		return $(this).find('.ap-action-type').val() === 'send_email';
	});
	if (!$emailCards.length) {
		return $();
	}

	var activeElement = document.activeElement;
	if (activeElement) {
		var $activeCard = $(activeElement).closest('.ap-action-card');
		if ($activeCard.length && $activeCard.find('.ap-action-type').val() === 'send_email') {
			return $activeCard.first();
		}
	}

	return $emailCards.first();
}

function apGetPreviewFields() {
	var $card = apGetPreviewCard();
	var subject = '';
	var body = '';

	if ($card.length) {
		subject = $card.find('[name$="[subject]"]').first().val() || '';
		body = $card.find('[name$="[body]"]').first().val() || '';
	}

	if (!subject) {
		subject = '(no subject)';
	}

	var triggerSlug = $('input[name="trigger_slug"]:checked').val() || '';
	return { subject: subject, body: body, trigger_slug: triggerSlug };
}

window.apGetPreviewFields = apGetPreviewFields;

function apCollectInlineActions() {
	var actions = [];
	$('#ap-actions-list .ap-action-card').each(function () {
		var $card = $(this);
		var type = $card.find('.ap-action-type').val();
		if (!type) {
			return;
		}
		var settings = {};
		$card.find('[name^="actions["]').each(function () {
			var match = $(this).attr('name').match(/\[settings\]\[([^\]]+)\]/);
			if (match) {
				settings[match[1]] = $(this).val();
			}
		});
		actions.push({ type: type, settings: settings });
	});
	return actions;
}

function apOpenPreviewModal() {
	var $modal = $('#ap-email-preview-modal');
	if (!$modal.length) { return; }
	$modal.removeAttr('hidden').addClass('is-open');
	$('body').addClass('ap-modal-open');
}

function apClosePreviewModal() {
	var $modal = $('#ap-email-preview-modal');
	$modal.attr('hidden', 'hidden').removeClass('is-open');
	$('body').removeClass('ap-modal-open');
}

$(document).on('click', '[data-ap-modal-close]', function () {
	apClosePreviewModal();
});

$(document).on('click', '.ap-preview-btn', function () {
	var fields = apGetPreviewFields();
	if (!fields.body) {
		alert('Add an email body first.');
		return;
	}
	var $btn = $(this);
	var prevTxt = cartcueAdmin.preview && cartcueAdmin.preview.loading ? cartcueAdmin.preview.loading : 'Loading…';
	$btn.prop('disabled', true).text(prevTxt);
	apOpenPreviewModal();
	$('#ap-email-preview-modal .ap-modal__note--warn').remove();
	if (apPreviewDirty && parseInt($('input[name="play_id"]').val(), 10) > 0) {
		$('<p class="ap-modal__note ap-modal__note--warn">Preview shows the last saved version. Save your changes first for an accurate preview.</p>')
			.insertAfter('#ap-email-preview-modal .ap-modal__header');
	}
	$('#ap-preview-subject').text('');
	$('#ap-preview-iframe').attr('srcdoc', '<p style="font-family:sans-serif;padding:20px;color:#666">Loading…</p>');
	$.post(cartcueAdmin.ajaxUrl || ajaxurl, {
		action: 'cartcue_preview_email',
		nonce: cartcueAdmin.nonces.preview_email,
		subject: fields.subject,
		body: fields.body,
		trigger_slug: fields.trigger_slug,
		inline: 1
	}).done(function (r) {
		if (r.success && r.data) {
			$('#ap-preview-subject').text(r.data.subject || fields.subject);
			$('#ap-preview-iframe').attr('srcdoc', r.data.html || '');
		} else {
			apClosePreviewModal();
			alert((r.data && r.data.message) ? r.data.message : 'Preview failed.');
		}
	}).fail(function () {
		apClosePreviewModal();
		alert('Preview failed.');
	}).always(function () {
		$btn.prop('disabled', false).text('Preview email');
	});
});

$(document).on('click', '#ap-preview-send-inbox', function () {
	var fields = apGetPreviewFields();
	if (!fields.body) { return; }
	var $btn = $(this);
	$btn.prop('disabled', true);
	$.post(cartcueAdmin.ajaxUrl || ajaxurl, {
		action: 'cartcue_preview_email',
		nonce: cartcueAdmin.nonces.preview_email,
		subject: fields.subject,
		body: fields.body,
		trigger_slug: fields.trigger_slug
	}).done(function (r) {
		var $res = $('#ap-test-result');
		if ($res.length) {
			$res.removeClass('ap-test-result--success ap-test-result--error')
				.addClass('ap-test-result ap-test-result--' + (r.success ? 'success' : 'error'))
				.text(r.data || '').show();
		} else if (r.success) {
			alert(r.data);
		}
	}).always(function () {
		$btn.prop('disabled', false);
	});
});

function wrapEmailComposerLayout($card, $fields) {
	if ($fields.find('.ap-email-workflow').length) {
		return;
	}
	var $bodyTextarea = $fields.find('textarea[name*="[body]"]').first();
	if (!$bodyTextarea.length) {
		return;
	}
	var $bodyRow = $bodyTextarea.closest('.ap-field-row');
	var $composeRows = $bodyRow.prevAll('.ap-field-row');
	if (!$composeRows.length) {
		return;
	}

	var $workflow = $('<div class="ap-email-workflow"></div>');

	var $stepSetup = $(
		'<section class="ap-email-step ap-email-step--setup">' +
			'<header class="ap-email-step__head">' +
				'<span class="ap-email-step__badge" aria-hidden="true">1</span>' +
				'<div class="ap-email-step__titles">' +
					'<span class="ap-email-step__title">Inbox details</span>' +
					'<span class="ap-email-step__desc">Template, sender, and subject line</span>' +
				'</div>' +
			'</header>' +
			'<div class="ap-email-compose"><div class="ap-email-compose__fields"></div></div>' +
		'</section>'
	);

	var $stepContent = $(
		'<section class="ap-email-step ap-email-step--content">' +
			'<header class="ap-email-step__head">' +
				'<span class="ap-email-step__badge" aria-hidden="true">2</span>' +
				'<div class="ap-email-step__titles">' +
					'<span class="ap-email-step__title">Email content</span>' +
					'<span class="ap-email-step__desc">Drag blocks to reorder · click to edit</span>' +
				'</div>' +
			'</header>' +
			'<div class="ap-email-body"></div>' +
		'</section>'
	);

	$composeRows.first().before($workflow);
	$workflow.append($stepSetup, $stepContent);

	var composeRowEls = $composeRows.get();
	composeRowEls.reverse();
	var $composeFields = $stepSetup.find('.ap-email-compose__fields');
	$composeFields.append(composeRowEls);

	var $fromName = $composeFields.find('[name$="[settings][from_name]"]').closest('.ap-field-row');
	var $fromEmail = $composeFields.find('[name$="[settings][from_email]"]').closest('.ap-field-row');
	if ($fromName.length && $fromEmail.length && !$composeFields.find('.ap-email-compose__sender').length) {
		var $sender = $('<div class="ap-email-compose__sender"></div>');
		$fromName.first().before($sender);
		$sender.append($fromName.first(), $fromEmail.first());
	}

	var $subjectRow = $fields.find('[name$="[settings][subject]"]').closest('.ap-field-row');
	if ($subjectRow.length) {
		$subjectRow.addClass('ap-field-row--subject');
	}

	if ($bodyRow.length) {
		$stepContent.find('.ap-email-body').append($bodyRow);
	}
}

function enhanceEmailActionCard($card) {
	if (!$card || !$card.length) {
		return;
	}
	if ($card.find('.ap-action-type').val() !== 'send_email') {
		return;
	}

	var $fields = $card.find('.ap-action-fields');
	if (!$fields.length) {
		return;
	}

	wrapEmailComposerLayout($card, $fields);

	var $subjectInput = $fields.find('[name$="[settings][subject]"]').first();
	if ($subjectInput.length) {
		var $subjectRow = $subjectInput.closest('.ap-field-row');
		if ($subjectRow.length) {
			if (!$subjectRow.find('.ap-tags-btn').length && typeof window.apBuildSubjectTagsControls === 'function') {
				var idx = $card.data('index');
				var tags = window.apBuildSubjectTagsControls(idx, 'subject');
				$subjectInput.after(tags.$btn, tags.$popover);
			}
			if (!$subjectRow.find('.ap-field-hint').length) {
				$subjectRow.append('<p class="ap-field-hint">Keep it short and personal. Example: “Hey {{customer.first_name|there}}, your cart is waiting”.</p>');
			}
		}
	}

	if ($fields.find('.ap-email-advanced').length) {
		return;
	}

	var advancedSelectors = [
		'[name$="[settings][to]"]',
		'[name$="[settings][content_format]"]',
		'[name$="[settings][bcc]"]'
	];

	var $advancedRows = $();
	advancedSelectors.forEach(function (selector) {
		var $row = $fields.find(selector).first().closest('.ap-field-row');
		if ($row.length) {
			$advancedRows = $advancedRows.add($row);
		}
	});
	if (!$advancedRows.length) {
		return;
	}

	var detailsHtml =
		'<details class="ap-email-advanced">' +
			'<summary><span class="ap-email-advanced__label">More options</span>' +
			'<span class="ap-email-advanced__hint">Recipient override, format, BCC</span></summary>' +
			'<div class="ap-email-advanced__body"></div>' +
		'</details>';
	var $details = $(detailsHtml);
	var $body = $details.find('.ap-email-advanced__body');
	$advancedRows.each(function () {
		$body.append($(this));
	});
	var $workflow = $fields.find('.ap-email-workflow');
	if ($workflow.length) {
		$workflow.append($details);
	} else {
		$fields.append($details);
	}
	$card.attr('data-email-enhanced', '1');
}

function enhanceExistingEmailActionCards() {
	$('#ap-actions-list .ap-action-card').each(function () {
		enhanceEmailActionCard($(this));
	});
}

$(document).on('change', '.ap-action-type', function () {
	var $card = $(this).closest('.ap-action-card');
	window.setTimeout(function () {
		enhanceEmailActionCard($card);
	}, 0);
});

$(function () {
	enhanceExistingEmailActionCards();
});

// ---- Day-of-week pills for smart timing ----------------------
$(document).on('click', '.ap-day-pill', function(){
	$(this).toggleClass('is-on');
	updateDayHiddenInput();
});

function updateDayHiddenInput() {
	var selected = [];
	$('.ap-day-pill.is-on').each(function(){ selected.push(parseInt($(this).data('day'))); });
	$('#ap-allowed-days').val(JSON.stringify(selected));
	// Update story bar
	if (typeof updateStory === 'function') updateStory();
}

// ---- Native mail delivery test (settings) --------------------
$(document).on('click', '#ap-test-mail-delivery', function () {
	var $btn = $(this);
	var $status = $('#ap-mail-delivery-status');
	if (!$status.length || !cartcueAdmin.nonces.test_mail_delivery) {
		return;
	}
	$btn.prop('disabled', true);
	$.post(cartcueAdmin.ajaxUrl, {
		action: 'cartcue_test_mail_delivery',
		nonce: cartcueAdmin.nonces.test_mail_delivery
	}).done(function (r) {
		var ok = r && r.success;
		var msg = (r.data && r.data.message) ? r.data.message : (ok ? 'OK' : 'Failed');
		$status.removeClass('ap-mail-status--unknown ap-mail-status--ok ap-mail-status--fail')
			.addClass(ok ? 'ap-mail-status--ok' : 'ap-mail-status--fail')
			.text(msg);
	}).fail(function () {
		$status.removeClass('ap-mail-status--unknown ap-mail-status--ok')
			.addClass('ap-mail-status--fail')
			.text('Request failed.');
	}).always(function () {
		$btn.prop('disabled', false);
	});
});

// ---- Export play link (add nonce to URL) ----------------------
$(document).on('click', '.ap-export-play-btn', function(e){
	e.preventDefault();
	var play_id = $(this).data('play');
	// Nonce needs to be fetched from inline data
	window.location = $(this).attr('href');
});

// ---- Card / toolbar overflow menus ---------------------------
function closeOverflowMenus() {
	document.querySelectorAll('.ap-play-overflow__menu:not([hidden])').forEach(function (menu) {
		menu.hidden = true;
		var toggle = menu.closest('.ap-play-overflow').querySelector('.ap-play-overflow__btn');
		if (toggle) {
			toggle.setAttribute('aria-expanded', 'false');
		}
	});
}
function openOverflowMenu(btn) {
	if (!btn) {
		return;
	}
	closeOverflowMenus();
	var menu = btn.nextElementSibling;
	if (!menu) {
		return;
	}
	menu.hidden = false;
	btn.setAttribute('aria-expanded', 'true');
	var firstItem = menu.querySelector('[role="menuitem"]');
	if (firstItem && typeof firstItem.focus === 'function') {
		firstItem.focus();
	}
}
function moveOverflowFocus(menu, direction) {
	if (!menu) {
		return;
	}
	var items = Array.prototype.slice.call(menu.querySelectorAll('[role="menuitem"]'));
	if (!items.length) {
		return;
	}
	var currentIndex = items.indexOf(document.activeElement);
	var nextIndex = currentIndex + direction;
	if (nextIndex < 0) {
		nextIndex = items.length - 1;
	}
	if (nextIndex >= items.length) {
		nextIndex = 0;
	}
	items[nextIndex].focus();
}

document.addEventListener('click', function (e) {
	var btn = e.target.closest('.ap-play-overflow__btn');
	closeOverflowMenus();
	if (btn) {
		var menu = btn.nextElementSibling;
		if (menu) {
			var open = !menu.hidden;
			if (open) {
				menu.hidden = true;
				btn.setAttribute('aria-expanded', 'false');
			} else {
				openOverflowMenu(btn);
			}
		}
		e.stopPropagation();
	}
});
document.addEventListener('keydown', function (e) {
	if (e.key === 'Escape') {
		closeOverflowMenus();
		return;
	}
	var btn = e.target.closest('.ap-play-overflow__btn');
	var menuItem = e.target.closest('[role="menuitem"]');
	if (btn && (e.key === 'Enter' || e.key === ' ' || e.key === 'ArrowDown')) {
		e.preventDefault();
		openOverflowMenu(btn);
		return;
	}
	if (!menuItem) {
		return;
	}
	var menu = menuItem.closest('.ap-play-overflow__menu');
	if (e.key === 'ArrowDown') {
		e.preventDefault();
		moveOverflowFocus(menu, 1);
	} else if (e.key === 'ArrowUp') {
		e.preventDefault();
		moveOverflowFocus(menu, -1);
	} else if (e.key === 'Home') {
		e.preventDefault();
		var first = menu.querySelector('[role="menuitem"]');
		if (first) {
			first.focus();
		}
	} else if (e.key === 'End') {
		e.preventDefault();
		var items = menu.querySelectorAll('[role="menuitem"]');
		if (items.length) {
			items[items.length - 1].focus();
		}
	}
});

// ---- Magic tags slide panel (all tags) -----------------------
var AP_TAG_GROUPS = [
	{
		name: 'Customer',
		tokens: [
			{ tag: '{{customer.first_name}}', label: 'First name' },
			{ tag: '{{customer.last_name}}', label: 'Last name' },
			{ tag: '{{customer.email}}', label: 'Email' }
		]
	},
	{
		name: 'Order',
		tokens: [
			{ tag: '{{order.number}}', label: 'Order number' },
			{ tag: '{{order.total}}', label: 'Order total' },
			{ tag: '{{order.items}}', label: 'Order items' },
			{ tag: '{{order.tracking_link}}', label: 'Tracking link' },
			{ tag: '{{order.billing_address}}', label: 'Billing address' },
			{ tag: '{{order.shipping_address}}', label: 'Shipping address' }
		]
	},
	{
		name: 'Cart',
		tokens: [
			{ tag: '{{cart.total}}', label: 'Cart total' },
			{ tag: '{{cart.recover_url}}', label: 'Recovery link' }
		]
	},
	{
		name: 'Coupon',
		tokens: [
			{ tag: '{{coupon.code}}', label: 'Coupon code' }
		]
	},
	{
		name: 'Shop',
		tokens: [
			{ tag: '{{shop.name}}', label: 'Shop name' },
			{ tag: '{{shop.url}}', label: 'Shop URL' },
			{ tag: '{{shop.logo_url}}', label: 'Logo URL' },
			{ tag: '{{shop.unsubscribe_url}}', label: 'Unsubscribe URL' }
		]
	}
];

var apTagsPanelTargetField = null;
var apTagsPanelReturnFocus = null;

function ensureTagsSlidePanel() {
	var panel = document.getElementById('ap-tags-slide-panel');
	if (panel) {
		return panel;
	}

	panel = document.createElement('div');
	panel.id = 'ap-tags-slide-panel';
	panel.className = 'ap-tags-slide-panel';
	panel.hidden = true;
	panel.setAttribute('aria-hidden', 'true');

	var backdrop = document.createElement('button');
	backdrop.type = 'button';
	backdrop.className = 'ap-tags-slide-panel__backdrop';
	backdrop.setAttribute('data-close-tags-panel', '');
	backdrop.setAttribute('aria-label', 'Close');

	var drawer = document.createElement('div');
	drawer.className = 'ap-tags-slide-panel__drawer';
	drawer.setAttribute('role', 'dialog');
	drawer.setAttribute('aria-modal', 'true');
	drawer.setAttribute('aria-labelledby', 'ap-tags-slide-panel-title');

	var header = document.createElement('div');
	header.className = 'ap-tags-slide-panel__header';
	header.innerHTML = '<h2 id="ap-tags-slide-panel-title">All personalization tags</h2>';
	var closeBtn = document.createElement('button');
	closeBtn.type = 'button';
	closeBtn.className = 'ap-icon-btn';
	closeBtn.setAttribute('data-close-tags-panel', '');
	closeBtn.setAttribute('aria-label', 'Close');
	closeBtn.textContent = '✕';
	header.appendChild(closeBtn);

	var grid = document.createElement('div');
	grid.className = 'ap-vars-grid ap-vars-grid--panel';

	AP_TAG_GROUPS.forEach(function (group) {
		var section = document.createElement('section');
		section.className = 'ap-tags-panel-group';

		var title = document.createElement('h3');
		title.className = 'ap-tags-panel-group__title';
		title.textContent = group.name;
		section.appendChild(title);

		var chips = document.createElement('div');
		chips.className = 'ap-tags-panel-group__chips';

		group.tokens.forEach(function (token) {
			var btn = document.createElement('button');
			btn.type = 'button';
			btn.className = 'ap-tag-insert-btn ap-tags-panel-tag';
			btn.dataset.tag = token.tag;
			btn.innerHTML = '<code>' + token.tag + '</code><span>' + token.label + '</span>';
			chips.appendChild(btn);
		});

		section.appendChild(chips);
		grid.appendChild(section);
	});

	drawer.appendChild(header);
	drawer.appendChild(grid);
	panel.appendChild(backdrop);
	panel.appendChild(drawer);
	document.body.appendChild(panel);
	return panel;
}

function closeTagsSlidePanel() {
	var panel = document.getElementById('ap-tags-slide-panel');
	if (!panel) {
		return;
	}
	panel.hidden = true;
	panel.setAttribute('aria-hidden', 'true');
	document.body.classList.remove('ap-tags-panel-open');
	apTagsPanelTargetField = null;
	if (apTagsPanelReturnFocus && typeof apTagsPanelReturnFocus.focus === 'function') {
		apTagsPanelReturnFocus.focus();
	}
}

function openTagsSlidePanel(triggerEl, targetField) {
	var panel = ensureTagsSlidePanel();
	apTagsPanelReturnFocus = triggerEl || null;
	apTagsPanelTargetField = targetField || null;
	panel.hidden = false;
	panel.setAttribute('aria-hidden', 'false');
	document.body.classList.add('ap-tags-panel-open');
	var first = panel.querySelector('.ap-tags-panel-tag, [data-close-tags-panel]');
	if (first && typeof first.focus === 'function') {
		first.focus();
	}
}

window.apOpenTagsSlidePanel = openTagsSlidePanel;
window.apCloseTagsSlidePanel = closeTagsSlidePanel;

$(function () {
	ensureTagsSlidePanel();
});

// ---- Magic tags inline popover -------------------------------
document.addEventListener('click', function (e) {
	if (e.target.closest('[data-open-tags-panel]')) {
		e.preventDefault();
		var openBtn = e.target.closest('[data-open-tags-panel]');
		var fieldRow = openBtn.closest('.ap-field-row');
		var field = fieldRow ? fieldRow.querySelector('input, textarea') : null;
		document.querySelectorAll('.ap-tags-popover:not([hidden])').forEach(function (p) {
			p.hidden = true;
		});
		openTagsSlidePanel(openBtn, field);
		return;
	}
	if (e.target.closest('[data-close-tags-panel]')) {
		e.preventDefault();
		closeTagsSlidePanel();
		return;
	}
	if (e.target.closest('.ap-tags-panel-tag')) {
		var panelBtn = e.target.closest('.ap-tags-panel-tag');
		var panelTag = panelBtn.dataset.tag;
		var panelField = apTagsPanelTargetField;
		if (!panelField) {
			var activePopover = document.querySelector('.ap-tags-popover:not([hidden])');
			var activeRow = activePopover ? activePopover.closest('.ap-field-row') : null;
			panelField = activeRow ? activeRow.querySelector('input, textarea') : null;
		}
		if (panelField && panelTag) {
			var pStart = panelField.selectionStart != null ? panelField.selectionStart : panelField.value.length;
			var pEnd = panelField.selectionEnd != null ? panelField.selectionEnd : panelField.value.length;
			panelField.value = panelField.value.slice(0, pStart) + panelTag + panelField.value.slice(pEnd);
			panelField.setSelectionRange(pStart + panelTag.length, pStart + panelTag.length);
			panelField.focus();
			panelField.dispatchEvent(new Event('input', { bubbles: true }));
		}
		closeTagsSlidePanel();
		return;
	}
	if (e.target.closest('.ap-tags-btn')) {
		e.preventDefault();
		var tagBtn = e.target.closest('.ap-tags-btn');
		var row = tagBtn.closest('.ap-field-row');
		var popover = row ? row.querySelector('.ap-tags-popover') : null;
		document.querySelectorAll('.ap-tags-popover:not([hidden])').forEach(function (p) {
			if (p !== popover) {
				p.hidden = true;
			}
		});
		if (popover) {
			popover.hidden = !popover.hidden;
		}
		return;
	}
	if (e.target.closest('.ap-tag-insert-btn')) {
		var insertBtn = e.target.closest('.ap-tag-insert-btn');
		var tag = insertBtn.dataset.tag;
		var pop = insertBtn.closest('.ap-tags-popover');
		var fieldRow = pop ? pop.closest('.ap-field-row') : null;
		var field = fieldRow ? fieldRow.querySelector('input, textarea') : null;
		if (field && tag) {
			var start = field.selectionStart != null ? field.selectionStart : field.value.length;
			var end = field.selectionEnd != null ? field.selectionEnd : field.value.length;
			field.value = field.value.slice(0, start) + tag + field.value.slice(end);
			field.setSelectionRange(start + tag.length, start + tag.length);
			field.focus();
			field.dispatchEvent(new Event('input', { bubbles: true }));
		}
		if (pop) {
			pop.hidden = true;
		}
		return;
	}
	document.querySelectorAll('.ap-tags-popover:not([hidden])').forEach(function (p) {
		if (!p.contains(e.target) && !e.target.closest('.ap-tags-btn')) {
			p.hidden = true;
		}
	});
});

// ---- Template preview modal ----------------------------------
(function () {
	var modal = document.getElementById('ap-recipe-modal');
	if (!modal) {
		return;
	}
	var titleEl = modal.querySelector('.ap-recipe-modal__title');
	var descEl = modal.querySelector('.ap-recipe-modal__desc');
	var triggerEl = modal.querySelector('.ap-recipe-modal__trigger');
	var waitEl = modal.querySelector('.ap-recipe-modal__wait');
	var actionEl = modal.querySelector('.ap-recipe-modal__action-label');
	var activateBtn = modal.querySelector('#ap-recipe-modal-activate');
	var customizeBtn = modal.querySelector('#ap-recipe-modal-customize');
	var emailPreview = modal.querySelector('.ap-recipe-modal__email-preview');
	var emailSubjectEl = modal.querySelector('.ap-recipe-modal__email-subject');
	var emailSnippetEl = modal.querySelector('.ap-recipe-modal__email-snippet');
	var currentUrl = '';
	var modalReturnFocus = null;
	var focusableSelector = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';

	function closeModal() {
		if (modal.hasAttribute('hidden')) {
			return;
		}
		modal.setAttribute('hidden', '');
		if (modalReturnFocus && typeof modalReturnFocus.focus === 'function') {
			modalReturnFocus.focus();
		}
	}
	document.querySelectorAll('.ap-recipe-card[data-recipe-key]').forEach(function (card) {
		card.addEventListener('click', function () {
			modalReturnFocus = card;
			titleEl.textContent = card.dataset.recipeName || '';
			descEl.textContent = card.dataset.recipeDesc || '';
			triggerEl.textContent = card.dataset.recipeTrigger || '';
			if (waitEl) {
				waitEl.textContent = card.dataset.recipeWait || '';
			}
			if (actionEl) {
				actionEl.textContent = card.dataset.recipeAction || '';
			}
			var emailSubject = card.dataset.recipeEmailSubject || '';
			var emailSnippet = card.dataset.recipeEmailSnippet || '';
			if (emailPreview) {
				if (emailSubject || emailSnippet) {
					emailPreview.hidden = false;
					if (emailSubjectEl) {
						emailSubjectEl.textContent = emailSubject;
					}
					if (emailSnippetEl) {
						emailSnippetEl.textContent = emailSnippet;
					}
				} else {
					emailPreview.hidden = true;
				}
			}
			currentUrl = card.dataset.recipeUrl || '';
			if (activateBtn) {
				activateBtn.href = card.dataset.recipeActivate || currentUrl;
			}
			modal.removeAttribute('hidden');
			var primary = modal.querySelector('.ap-btn-primary');
			if (primary) {
				primary.focus();
			}
		});
	});
	if (customizeBtn) {
		customizeBtn.addEventListener('click', function () {
			if (currentUrl) {
				window.location.href = currentUrl;
			}
		});
	}
	modal.querySelector('.ap-recipe-modal__close').addEventListener('click', closeModal);
	modal.querySelector('.ap-recipe-modal__backdrop').addEventListener('click', closeModal);
	document.addEventListener('keydown', function (ev) {
		if (modal.hasAttribute('hidden')) {
			return;
		}
		if ('Escape' === ev.key) {
			closeModal();
			return;
		}
		if ('Tab' !== ev.key) {
			return;
		}
		var focusable = modal.querySelectorAll(focusableSelector);
		if (!focusable.length) {
			return;
		}
		var first = focusable[0];
		var last = focusable[focusable.length - 1];
		if (ev.shiftKey && document.activeElement === first) {
			ev.preventDefault();
			last.focus();
		} else if (!ev.shiftKey && document.activeElement === last) {
			ev.preventDefault();
			first.focus();
		}
	});
})();

})(jQuery);
