/* global cartcueAdmin, jQuery */
(function ($) {
	'use strict';

	var cfg = window.cartcueAdmin || {};
	var tl = cfg.timelineStrings || {};
	var triggers = cfg.triggers || {};
	var actions = cfg.actions || {};
	var actionIcons = (cfg.playUx && cfg.playUx.actionIcons) || {};
	var timingUnits = cfg.timingUnits || {};

	var $form;
	var $rail;
	var selectedId = null;
	var timingHome = null;
	var seqStepHome = null;

	function isTimelineEligible() {
		return $form && ($form.hasClass('ap-editor-timeline-mode') || $form.data('editorLayout') === 'timeline');
	}

	function isTimelineActive() {
		return isTimelineEligible() && $form.attr('data-guided-step') === 'action';
	}

	function t(key, fallback) {
		return tl[key] || fallback;
	}

	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 readSequenceSteps() {
		var steps = [];
		$('#ap-sequence-builder .ap-sequence-step').each(function () {
			var $row = $(this);
			if ($row.hasClass('ap-sequence-step--branch')) {
				var ruleSlug = $row.find('.ap-seq-branch-rule').val() || 'email_opened';
				steps.push({
					step_type: 'branch',
					rules: [{
						slug: ruleSlug,
						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,
					delay: parseInt($row.find('.ap-seq-delay').val(), 10) || 0,
					delay_unit: $row.find('.ap-seq-unit').val() || 'hours'
				});
				return;
			}
			steps.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'
			});
		});
		if (steps.length) {
			return steps;
		}
		if ($.isArray(window.apSequenceInitial) && window.apSequenceInitial.length) {
			return window.apSequenceInitial.slice();
		}
		return [];
	}

	function branchStepLabel(step, stepNum) {
		var rules = cfg.branchRules || [];
		var slug = step.rules && step.rules[0] ? step.rules[0].slug : 'email_opened';
		var op = step.rules && step.rules[0] ? step.rules[0].operator : 'is';
		var match = null;
		rules.forEach(function (br) {
			if (br.slug === slug) {
				match = br;
			}
		});
		var label = match ? match.label : t('branchFallback', 'If / Else');
		if (match && match.operators && match.operators[op]) {
			label += ' — ' + match.operators[op];
		}
		return t('branchStep', 'Branch %1$d: %2$s').replace('%1$d', String(stepNum)).replace('%2$s', label);
	}

	function formatWait(value, unit) {
		var v = parseInt(value, 10);
		if (isNaN(v) || v <= 0) {
			return t('waitImmediate', 'Right away');
		}
		var u = timingUnits[unit] || unit || 'hours';
		return t('waitFor', 'Wait for %1$d %2$s').replace('%1$d', String(v)).replace('%2$s', u);
	}

	function getTriggerLabel() {
		var slug = $('input[name="trigger_slug"]:checked').val() || '';
		if (slug && triggers[slug] && triggers[slug].label) {
			return triggers[slug].label;
		}
		return t('triggerFallback', 'Trigger');
	}

	function actionNodeComplete(actionIndex) {
		if (window.apPlayValidation && typeof window.apPlayValidation.getActionCompleteness === 'function') {
			return window.apPlayValidation.getActionCompleteness(actionIndex).ok;
		}
		return true;
	}

	function getActionLabel(actionIndex, stepNum) {
		var slug = '';
		$('#ap-actions-list .ap-action-card').each(function () {
			if (String($(this).data('index')) === String(actionIndex)) {
				slug = $(this).find('.ap-action-type').val();
				return false;
			}
		});
		var base = slug && actions[slug] ? actions[slug].label : t('actionFallback', 'Action');
		var $card = $('#ap-actions-list .ap-action-card[data-index="' + actionIndex + '"]');
		var subject = $card.find('[name$="[subject]"]').val() || '';
		if (subject) {
			return subject.length > 36 ? subject.substring(0, 36) + '…' : subject;
		}
		if (stepNum !== undefined) {
			return t('messageStep', 'Message %1$d').replace('%1$d', String(stepNum));
		}
		return base;
	}

	function buildNodes() {
		var nodes = [];
		nodes.push({
			id: 'trigger',
			type: 'trigger',
			label: getTriggerLabel(),
			meta: t('triggerMeta', 'Starts this automation')
		});

		var timingType = $('#ap-timing-type').val() || 'immediate';
		if (timingType === 'delay') {
			nodes.push({
				id: 'initial-wait',
				type: 'wait',
				label: formatWait($('#ap-delay-value').val(), $('#ap-delay-unit').val()),
				meta: t('initialWaitMeta', 'Before the first message')
			});
		} else if (timingType === 'schedule_time') {
			nodes.push({
				id: 'initial-wait',
				type: 'wait',
				label: t('atTime', 'At ') + ($('#ap-schedule-time').val() || '09:00'),
				meta: t('initialWaitMeta', 'Before the first message')
			});
		}

		var seq = readSequenceSteps();
		if (!seq.length) {
			var ai = firstActionIndex();
			nodes.push({
				id: 'action-' + ai,
				type: 'action',
				actionIndex: ai,
				label: getActionLabel(ai),
				meta: t('actionMeta', 'Edit content on the right'),
				complete: actionNodeComplete(ai)
			});
			return nodes;
		}

		seq.forEach(function (step, i) {
			if (step.step_type === 'branch') {
				if (step.delay > 0) {
					nodes.push({
						id: 'seq-' + i + '-wait',
						type: 'wait',
						seqIndex: i,
						label: formatWait(step.delay, step.delay_unit),
						meta: t('branchWaitMeta', 'Before evaluating branch')
					});
				}
				nodes.push({
					id: 'seq-' + i + '-branch',
					type: 'branch',
					seqIndex: i,
					label: branchStepLabel(step, i + 1),
					meta: t('branchMeta', 'Opens or clicks can route the path')
				});
				return;
			}
			var ai = String(step.action_index != null ? step.action_index : firstActionIndex());
			nodes.push({
				id: 'seq-' + i + '-wait',
				type: 'wait',
				seqIndex: i,
				label: formatWait(step.delay, step.delay_unit),
				meta: i === 0
					? t('seqWaitMetaFirst', 'Then send the first message')
					: t('seqWaitMeta', 'Before the next message')
			});
			nodes.push({
				id: 'seq-' + i + '-action',
				type: 'action',
				seqIndex: i,
				actionIndex: ai,
				label: getActionLabel(step.action_index, i + 1),
				meta: t('actionMeta', 'Edit content on the right'),
				complete: actionNodeComplete(ai)
			});
		});

		return nodes;
	}

	function renderRail() {
		if (!$rail.length) {
			return;
		}
		var nodes = buildNodes();
		var html = '<p class="ap-timeline-rail__title">' + $('<span>').text(t('railTitle', 'Sequence')).html() + '</p>';
		html += '<ul class="ap-timeline-rail__list" role="listbox" aria-label="' + $('<span>').text(t('railAria', 'Sequence steps')).html() + '">';

		nodes.forEach(function (node, idx) {
			if (idx > 0) {
				html += '<li class="ap-timeline-rail__connector" aria-hidden="true"></li>';
			}
			var icon = 'ti-bolt';
			if (node.type === 'wait') {
				icon = 'ti-clock';
			} else if (node.type === 'branch') {
				icon = 'ti-git-branch';
			} else if (node.type === 'action') {
				var slug = '';
				$('#ap-actions-list .ap-action-card').each(function () {
					if (String($(this).data('index')) === String(node.actionIndex)) {
						slug = $(this).find('.ap-action-type').val();
						return false;
					}
				});
				icon = actionIcons[slug] || 'ti-mail';
			}
			var selected = node.id === selectedId ? ' is-selected' : '';
			html += '<li class="ap-timeline-rail__item" role="presentation">';
			html += '<button type="button" class="ap-timeline-node ap-timeline-node--' + node.type + selected + '" role="option" aria-selected="' + (node.id === selectedId ? 'true' : 'false') + '" data-timeline-id="' + $('<span>').text(node.id).html() + '">';
			html += '<span class="ap-timeline-node__icon"><i class="ti ' + icon + '" aria-hidden="true"></i></span>';
			html += '<span class="ap-timeline-node__body">';
			html += '<span class="ap-timeline-node__label">' + $('<span>').text(node.label).html() + '</span>';
			if (node.type === 'action') {
				if (node.complete) {
					html += '<span class="ap-timeline-node__status ap-timeline-node__status--ready">' + $('<span>').text(t('stepReady', 'Ready')).html() + '</span>';
				} else {
					html += '<span class="ap-timeline-node__status ap-timeline-node__status--missing">' + $('<span>').text(t('missingContent', 'Missing content')).html() + '</span>';
				}
			} else if (node.meta) {
				html += '<span class="ap-timeline-node__meta">' + $('<span>').text(node.meta).html() + '</span>';
			}
			html += '</span></button></li>';
		});

		html += '</ul>';

		if ($('#ap-sequence-builder').length && $('#ap-add-sequence-step').length) {
			html += '<button type="button" class="ap-btn ap-btn-ghost ap-btn-sm ap-timeline-rail__add" id="ap-timeline-add-step">+ ' + $('<span>').text(t('addStep', 'Add step')).html() + '</button>';
		}

		$rail.html(html);
	}

	function defaultSelection(nodes) {
		if (!nodes.length) {
			return 'trigger';
		}
		var seq = readSequenceSteps();
		if (seq.length) {
			return 'seq-0-action';
		}
		if (nodes.some(function (n) { return n.id === 'initial-wait'; })) {
			return 'initial-wait';
		}
		var actionNode = nodes.filter(function (n) { return n.type === 'action'; })[0];
		return actionNode ? actionNode.id : nodes[0].id;
	}

	function restoreTimingPanel() {
		var $timing = $('#ap-section-then-wait');
		if (timingHome && $timing.length && !$timing.parent().is(timingHome)) {
			$timing.removeClass('ap-timeline-embedded').appendTo(timingHome);
		}
	}

	function restoreSequenceSteps() {
		var $builder = $('#ap-sequence-builder');
		if (!$builder.length) {
			return;
		}
		$('#ap-timeline-pane-seq .ap-sequence-step').appendTo($builder);
	}

	function attachWaitStepper($delayInput) {
		if (!$delayInput.length || $delayInput.closest('.ap-wait-stepper').length) {
			return;
		}
		var $wrap = $('<div class="ap-wait-stepper"></div>');
		var $minus = $('<button type="button" class="ap-wait-stepper__btn" aria-label="-">−</button>');
		var $plus = $('<button type="button" class="ap-wait-stepper__btn" aria-label="+">+</button>');
		$delayInput.before($minus);
		$delayInput.after($plus);
		$minus.add($delayInput).add($plus).wrapAll($wrap);
		$minus.on('click', function () {
			var v = parseInt($delayInput.val(), 10) || 0;
			$delayInput.val(Math.max(0, v - 1)).trigger('input');
		});
		$plus.on('click', function () {
			var v = parseInt($delayInput.val(), 10) || 0;
			$delayInput.val(v + 1).trigger('input');
		});
	}

	function enhanceSeqWaitStep($step, seqIndex) {
		var $waitLine = $step.find('.ap-seq-line--wait');
		if (!$waitLine.length) {
			return;
		}
		$step.addClass('ap-timeline-wait-editor');
		if (!$step.find('.ap-timeline-wait-help').length) {
			var help = seqIndex === 0
				? t('waitHelpFollowUp', 'If the customer has not completed the action yet, send the next message after this wait.')
				: t('waitHelpFollowUp', 'If the customer has not completed the action yet, send the next message after this wait.');
			$waitLine.after('<p class="ap-timeline-wait-help">' + $('<span>').text(help).html() + '</p>');
		}
		attachWaitStepper($waitLine.find('.ap-seq-delay'));
	}

	function enhanceInitialWaitPane() {
		var $pane = $('#ap-timeline-pane-timing');
		if (!$pane.find('.ap-timeline-wait-help').length) {
			$pane.append(
				'<p class="ap-timeline-wait-help ap-timeline-wait-help--initial">' +
				$('<span>').text(t('waitHelpInitial', 'After the trigger fires, wait this long before the first message is sent.')).html() +
				'</p>'
			);
		}
		var $customVal = $pane.find('#ap-custom-val');
		if ($customVal.length) {
			attachWaitStepper($customVal);
		}
	}

	function mountTimingInCanvas() {
		var $timing = $('#ap-section-then-wait');
		var $pane = $('#ap-timeline-pane-timing');
		if (!$timing.length || !$pane.length) {
			return;
		}
		if (!timingHome) {
			timingHome = $('<div id="ap-timing-panel-home" class="ap-timing-panel-home"></div>');
			$timing.before(timingHome);
		}
		$timing.addClass('ap-timeline-embedded').appendTo($pane);
		$pane.prop('hidden', false).addClass('is-active');
		enhanceInitialWaitPane();
	}

	function hideAllPanes() {
		$('#ap-timeline-pane-timing, #ap-timeline-pane-seq, #ap-timeline-pane-actions').each(function () {
			$(this).prop('hidden', true).removeClass('is-active');
		});
		$('#ap-actions-list .ap-action-card').removeClass('ap-timeline-card--visible');
		$('#ap-timeline-trigger-hint').remove();
		restoreTimingPanel();
		restoreSequenceSteps();
	}

	function selectStep(id) {
		if (!isTimelineActive()) {
			selectedId = id;
			return;
		}

		selectedId = id;
		$form.attr('data-timeline-selection', id);
		hideAllPanes();

		$rail.find('.ap-timeline-node').removeClass('is-selected').attr('aria-selected', 'false');
		$rail.find('[data-timeline-id="' + id + '"]').addClass('is-selected').attr('aria-selected', 'true');

		if (id === 'trigger') {
			var $pane = $('#ap-timeline-pane-actions');
			$pane.prop('hidden', false).addClass('is-active');
			if (!$('#ap-timeline-trigger-hint').length) {
				$pane.prepend(
					'<div class="ap-timeline-trigger-hint" id="ap-timeline-trigger-hint">' +
					'<p>' + $('<span>').text(t('triggerHint', 'Edit when this automation runs in the “When…” step.')).html() + '</p>' +
					'<button type="button" class="ap-btn ap-btn-primary ap-timeline-goto-trigger">' + $('<span>').text(t('gotoTrigger', 'Go to When…')).html() + '</button>' +
					'</div>'
				);
			}
			return;
		}

		if (id === 'initial-wait') {
			mountTimingInCanvas();
			return;
		}

		var seqWait = id.match(/^seq-(\d+)-wait$/);
		if (seqWait) {
			var si = parseInt(seqWait[1], 10);
			var $step = $('#ap-sequence-builder .ap-sequence-step[data-seq-index="' + si + '"]');
			var $seqPane = $('#ap-timeline-pane-seq');
			var $builder = $('#ap-sequence-builder');
			if (!$builder.length || !$step.length) {
				return;
			}
			if (!seqStepHome) {
				seqStepHome = $builder;
			}
			restoreSequenceSteps();
			$seqPane.prop('hidden', false).addClass('is-active').empty();
			$step.appendTo($seqPane);
			enhanceSeqWaitStep($step, si);
			return;
		}

		var actionMatch = id.match(/^action-(\d+)$/);
		var seqAction = id.match(/^seq-(\d+)-action$/);
		var actionIndex = null;
		if (actionMatch) {
			actionIndex = actionMatch[1];
		} else if (seqAction) {
			var row = readSequenceSteps()[parseInt(seqAction[1], 10)];
			actionIndex = row ? String(row.action_index) : firstActionIndex();
		}

		if (actionIndex !== null) {
			var $actionsPane = $('#ap-timeline-pane-actions');
			$actionsPane.prop('hidden', false).addClass('is-active');
			$('#ap-actions-list .ap-action-card').each(function () {
				var $card = $(this);
				if (String($card.data('index')) === String(actionIndex)) {
					$card.addClass('ap-timeline-card--visible');
					if ($card[0] && typeof $card[0].scrollIntoView === 'function') {
						setTimeout(function () {
							$card[0].scrollIntoView({ behavior: 'smooth', block: 'start' });
						}, 50);
					}
				}
			});
		}
	}

	function syncReviewIncomplete() {
		var $box = $('#ap-review-incomplete');
		var $list = $('#ap-review-incomplete-list');
		if (!$box.length || !$list.length || !window.apPlayValidation) {
			return;
		}
		var items = window.apPlayValidation.getIncompleteTimelineSteps();
		if (!items.length) {
			$box.prop('hidden', true);
			$list.empty();
			return;
		}
		var html = '';
		items.forEach(function (item) {
			html += '<li><button type="button" class="ap-review-incomplete__link" data-timeline-jump="' +
				$('<span>').text(item.nodeId).html() + '">' +
				$('<span>').text(item.label).html() + ' — ' +
				$('<span>').text(item.reasons.join(', ')).html() +
				'</button></li>';
		});
		$list.html(html);
		$box.prop('hidden', false);
	}

	function refresh() {
		if (!$form || !$form.length) {
			return;
		}
		maybeEnableTimelineMode();
		if (!isTimelineEligible()) {
			syncReviewIncomplete();
			return;
		}
		renderRail();
		syncReviewIncomplete();
		if (isTimelineActive()) {
			var nodes = buildNodes();
			if (!selectedId || !nodes.some(function (n) { return n.id === selectedId; })) {
				selectStep(defaultSelection(nodes));
			} else {
				selectStep(selectedId);
			}
		}
		if (typeof window.renderTimingTimeline === 'function') {
			window.renderTimingTimeline();
		}
		if (typeof window.apSyncSetupChecklist === 'function') {
			window.apSyncSetupChecklist();
		}
	}

	function maybeEnableTimelineMode() {
		if (!$form.length) {
			return;
		}
		if ($form.data('editorLayout') === 'timeline') {
			$form.addClass('ap-editor-timeline-mode');
			return;
		}
		if ($form.data('timelineEligible') === 1 || $form.data('timelineEligible') === '1') {
			var hasSeq = $('#ap-sequence-builder .ap-sequence-step').length > 0;
			var hasSeqData = $.isArray(window.apSequenceInitial) && window.apSequenceInitial.length > 0;
			if (hasSeq || hasSeqData) {
				$form.addClass('ap-editor-timeline-mode');
			}
		}
	}

	function onGuidedStepChange() {
		if (!isTimelineEligible()) {
			return;
		}
		if (isTimelineActive()) {
			var nodes = buildNodes();
			selectStep(selectedId && nodes.some(function (n) { return n.id === selectedId; }) ? selectedId : defaultSelection(nodes));
		} else {
			hideAllPanes();
			$('#ap-actions-list .ap-action-card').removeClass('ap-timeline-card--visible');
		}
	}

	function bindEvents() {
		if ($form.data('timelineBound')) {
			return;
		}
		$form.data('timelineBound', true);

		$(document).on('click', '.ap-timeline-node', function () {
			selectStep($(this).data('timelineId'));
		});

		$(document).on('click', '.ap-timeline-goto-trigger', function () {
			$('.ap-guided-stepper__item[data-guided-step="trigger"]').trigger('click');
		});

		$(document).on('click', '#ap-timeline-add-step', function () {
			$('#ap-add-sequence-step').trigger('click');
		});

		$form.on('cartcue:guided-step-changed', onGuidedStepChange);

		$(document).on('change input', '#ap-timing-type, #ap-delay-value, #ap-delay-unit, #ap-schedule-time', function () {
			refresh();
		});

		$(document).on('change input', '.ap-seq-action, .ap-seq-delay, .ap-seq-unit, .ap-seq-branch-rule, .ap-seq-branch-op, .ap-seq-branch-val, .ap-seq-branch-true, .ap-seq-branch-false', function () {
			refresh();
		});

		$(document).on('input', 'input[name*="[subject]"], textarea[name*="[body]"], textarea[name*="[message]"]', function () {
			refresh();
		});

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

		$(document).on('click', '.ap-review-incomplete__link', function () {
			var nodeId = $(this).data('timelineJump');
			$('.ap-guided-stepper__item[data-guided-step="action"]').trigger('click');
			setTimeout(function () {
				selectStep(nodeId);
			}, 50);
		});

		$(document).on('click', '#ap-add-sequence-step, #ap-add-sequence-branch, .ap-remove-sequence-step, #ap-timing-add-followup', function () {
			setTimeout(refresh, 0);
		});
	}

	function init() {
		$form = $('#ap-play-form');
		$rail = $('#ap-timeline-rail');
		if (!$form.length || !$rail.length) {
			return;
		}
		maybeEnableTimelineMode();
		bindEvents();
		refresh();
	}

	window.apSequenceTimeline = {
		init: init,
		refresh: refresh,
		selectStep: selectStep,
		onGuidedStepChange: onGuidedStepChange
	};

	$(function () {
		init();
	});
})(jQuery);
