(function () {
	'use strict';
	if (!window.lens) { return; }

	var pickerInput = document.getElementById('lens-post-search');
	var postIdField = document.getElementById('lens-post-id');
	var runBtn      = document.getElementById('lens-run-scan');
	var withAiCb    = document.getElementById('lens-with-ai');
	var resultCard  = document.getElementById('lens-scan-result');

	if (!pickerInput || !runBtn) { return; }

	// Wire the picker with onSelect — enables the Run button.
	window.lens.postPicker(pickerInput, {
		onSelect: function (item) {
			runBtn.disabled = false;
			runBtn.focus();
		}
	});

	pickerInput.addEventListener('input', function () {
		// Clear selection if the user types more
		runBtn.disabled = !postIdField.value;
	});

	runBtn.addEventListener('click', function () {
		var postId = parseInt(postIdField.value, 10);
		if (!postId) {
			lens.toast('Please pick a post first.', 'warn');
			return;
		}
		var withAi = withAiCb && withAiCb.checked;
		lens.busy(runBtn, true);
		runBtn.textContent = withAi ? 'Scanning with AI…' : 'Scanning…';
		// Re-insert spinner since textContent wiped it
		var s = document.createElement('span');
		s.className = 'spinner';
		runBtn.insertBefore(s, runBtn.firstChild);

		lens.api('run_scan', { post_id: postId, with_ai: withAi ? 1 : 0 }).then(function (data) {
			renderResult(data);
			lens.toast(lens.i18n.scanComplete || 'Scan complete.', 'ok');
			// Add to top of recent table without page reload would be nice — for now skip.
		}).catch(function (e) {
			lens.toast(e.message, 'bad');
		}).finally(function () {
			lens.busy(runBtn, false);
			runBtn.innerHTML = '<span class="spinner"></span> Run scan';
		});
	});

	function renderResult(data) {
		var title = document.getElementById('lens-scan-result-title');
		var score = document.getElementById('lens-scan-result-score');
		var fill  = document.getElementById('lens-scan-result-fill');
		var list  = document.getElementById('lens-scan-result-findings');
		var aiBox = document.getElementById('lens-scan-result-ai');
		var aiTxt = document.getElementById('lens-scan-result-ai-text');

		title.textContent = data.post_title || ('#' + data.post_id);

		var s = data.score;
		var cls = s == null ? '' : (s >= 75 ? 's-high' : s >= 50 ? 's-mid' : 's-low');
		score.innerHTML = s == null ? '' : '<span class="lens-score ' + cls + '" style="font-size:14px;padding:5px 14px;">' + s + ' / 100</span>';
		fill.style.background = s >= 75 ? '#117a3a' : s >= 50 ? '#d4a017' : '#b32d2e';
		fill.style.width = (s || 0) + '%';

		list.innerHTML = '';
		(data.findings || []).forEach(function (f) {
			var kind = f.pass ? 'pass' : (f.severity === 'info' ? 'info' : 'fail');
			var icon = f.pass ? '✓' : (f.severity === 'info' ? 'i' : '!');
			var d = document.createElement('div');
			d.className = 'lens-finding ' + kind;
			d.innerHTML = '<div class="indicator">' + icon + '</div>'
				+ '<div class="body"><div class="title">' + escapeHtml(humaniseKey(f.key)) + '</div><div class="message">' + escapeHtml(f.message) + '</div></div>';
			list.appendChild(d);
		});

		if (data.ai_text) {
			aiBox.style.display = '';
			aiTxt.textContent = data.ai_text;
		} else {
			aiBox.style.display = 'none';
		}

		resultCard.style.display = '';
		resultCard.scrollIntoView({ behavior: 'smooth', block: 'start' });
	}

	function humaniseKey(k) {
		return String(k).replace(/_/g, ' ').replace(/\b\w/g, function (c) { return c.toUpperCase(); });
	}

	function escapeHtml(s) {
		return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
			return { '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[c];
		});
	}

	// ====================================================================
	// Bulk scan controller — single-button flow with live estimate.
	// ====================================================================
	(function setupBulkScan() {
		var startBtn   = document.getElementById('lens-bulk-start');
		var refreshBtn = document.getElementById('lens-bulk-refresh');
		var cancelBtn  = document.getElementById('lens-bulk-cancel');
		var typeSel    = document.getElementById('lens-bulk-type');
		var filterSel  = document.getElementById('lens-bulk-filter');
		var withAiCb   = document.getElementById('lens-bulk-with-ai');
		var estimate   = document.getElementById('lens-bulk-estimate');
		var progress   = document.getElementById('lens-bulk-progress');
		var label      = document.getElementById('lens-bulk-progress-label');
		var eta        = document.getElementById('lens-bulk-progress-eta');
		var bar        = document.getElementById('lens-bulk-progress-bar');
		var log        = document.getElementById('lens-bulk-log');
		var summary    = document.getElementById('lens-bulk-summary');

		if (!startBtn) { return; }
		if (!estimate || !progress || !typeSel || !filterSel) {
			console.warn('[Lens] Bulk-scan UI missing DOM elements — check view template.');
			return;
		}

		var lastTargets = null;   // null when stale, [] when known empty
		var lastSig = null;       // signature of filter set used for lastTargets
		var running = false;
		var cancelled = false;
		var fetchingEstimate = false;

		function currentSig() {
			return typeSel.value + '|' + filterSel.value;
		}

		// ---- Live estimate ----------------------------------------------
		function loadEstimate() {
			if (running) { return; }                  // don't poll while running
			if (fetchingEstimate) { return; }         // de-bounce
			fetchingEstimate = true;
			var sig = currentSig();
			estimate.innerHTML = '<span style="color:#646970">Counting…</span>';

			lens.api('bulk_scan_targets', {
				post_type: typeSel.value,
				filter:    filterSel.value
			}).then(function (data) {
				if (sig !== currentSig()) { return; }  // filters changed mid-flight
				lastTargets = data.items || [];
				lastSig = sig;
				renderEstimate(data);
			}).catch(function (e) {
				console.error('[Lens] bulk_scan_targets failed:', e);
				estimate.innerHTML = '<strong style="color:#b32d2e">Could not fetch the post list:</strong> ' + escapeHtml(e.message);
				lastTargets = null;
			}).finally(function () {
				fetchingEstimate = false;
			});
		}

		function renderEstimate(data) {
			var n = (data.items || []).length;
			if (n === 0) {
				estimate.innerHTML = '<strong>Nothing to scan</strong> with the current filters. Try changing "Which posts" to a wider option.';
				return;
			}
			var ai = withAiCb && withAiCb.checked;
			var costStr = ai ? ' · est. cost <strong>' + formatCost(n) + '</strong>' : '';
			var timeStr = ' · est. <strong>' + formatTime(n, ai) + '</strong>';
			var capStr  = (data.count === data.hard_cap)
				? '  <span class="lens-pill warn" style="margin-left:6px">capped at ' + data.hard_cap + '</span>'
				: '';
			estimate.innerHTML = '<strong>' + n + ' post' + (n === 1 ? '' : 's') + '</strong> will be scanned' + timeStr + costStr + capStr;
		}

		function formatCost(n) {
			var cost = n * 0.0005;
			if (cost < 0.01) { return '~< $0.01'; }
			return '~$' + cost.toFixed(2);
		}

		function formatTime(n, withAi) {
			var perPost = withAi ? 8 : 0.6;
			var total = n * perPost;
			if (total < 60) { return Math.ceil(total) + 's'; }
			if (total < 3600) { return Math.ceil(total / 60) + ' min'; }
			return (total / 3600).toFixed(1) + ' hr';
		}

		// Wire filter changes
		typeSel.addEventListener('change', loadEstimate);
		filterSel.addEventListener('change', loadEstimate);
		if (withAiCb) { withAiCb.addEventListener('change', function () { if (lastTargets) { renderEstimate({ items: lastTargets, count: lastTargets.length, hard_cap: 500 }); } }); }
		if (refreshBtn) {
			refreshBtn.addEventListener('click', function () {
				lens.busy(refreshBtn, true);
				lastSig = null;  // force refresh
				loadEstimate();
				setTimeout(function () { lens.busy(refreshBtn, false); }, 800);
			});
		}

		// ---- Start ------------------------------------------------------
		startBtn.addEventListener('click', function () {
			if (running) { return; }

			// If we don't have a fresh list, fetch first.
			var sig = currentSig();
			var promise;
			if (lastTargets !== null && lastSig === sig) {
				promise = Promise.resolve(lastTargets);
			} else {
				lens.busy(startBtn, true);
				promise = lens.api('bulk_scan_targets', { post_type: typeSel.value, filter: filterSel.value })
					.then(function (data) {
						lastTargets = data.items || [];
						lastSig = sig;
						renderEstimate(data);
						return lastTargets;
					});
			}

			promise.then(function (targets) {
				lens.busy(startBtn, false);
				if (!targets || targets.length === 0) {
					lens.toast('Nothing to scan with the current filters.', 'warn');
					return;
				}
				var withAi = withAiCb && withAiCb.checked;
				var msg = 'Scan ' + targets.length + ' post' + (targets.length === 1 ? '' : 's') +
					(withAi ? ' WITH AI enrichment (est. ' + formatCost(targets.length) + ').' : '') +
					' Continue?';
				if (!lens.confirm(msg)) { return; }
				runBulk(targets.slice(), withAi);
			}).catch(function (e) {
				lens.busy(startBtn, false);
				console.error('[Lens] Could not start bulk scan:', e);
				lens.toast('Could not start bulk scan: ' + e.message, 'bad');
			});
		});

		// ---- Cancel -----------------------------------------------------
		if (cancelBtn) {
			cancelBtn.addEventListener('click', function () {
				cancelled = true;
				cancelBtn.disabled = true;
				cancelBtn.textContent = 'Cancelling…';
			});
		}

		// ---- Runner -----------------------------------------------------
		function runBulk(queue, withAi) {
			running = true;
			cancelled = false;
			var total = queue.length;
			var done = 0;
			var ok = 0;
			var failed = 0;
			var sumScore = 0;
			var sumScored = 0;
			var start = Date.now();

			startBtn.style.display = 'none';
			if (refreshBtn) { refreshBtn.disabled = true; }
			if (cancelBtn) { cancelBtn.style.display = ''; cancelBtn.disabled = false; cancelBtn.textContent = 'Cancel'; }
			progress.style.display = '';
			if (log) { log.style.display = ''; log.innerHTML = ''; }
			if (summary) { summary.style.display = 'none'; }
			bar.style.background = '#2271b1';

			function next() {
				if (cancelled) { finish(true); return; }
				if (queue.length === 0) { finish(false); return; }
				var target = queue.shift();
				done++;
				updateProgress(done, total, start);
				label.textContent = 'Scanning ' + done + ' of ' + total + ' — ' + (target.title || ('#' + target.id));

				lens.api('run_scan', { post_id: target.id, with_ai: withAi ? 1 : 0 }).then(function (data) {
					ok++;
					if (typeof data.score === 'number') { sumScore += data.score; sumScored++; }
					appendLog(target, data, null);
				}).catch(function (e) {
					failed++;
					console.warn('[Lens] scan failed for post ' + target.id + ':', e);
					appendLog(target, null, e.message);
				}).finally(function () {
					setTimeout(next, withAi ? 400 : 50);
				});
			}

			function finish(wasCancelled) {
				running = false;
				cancelled = false;
				if (refreshBtn) { refreshBtn.disabled = false; }
				startBtn.style.display = '';
				if (cancelBtn) { cancelBtn.style.display = 'none'; }
				bar.style.background = wasCancelled ? '#8a5a00' : '#117a3a';

				var avg = sumScored ? Math.round(sumScore / sumScored) : null;
				var html =
					'<strong>' + (wasCancelled ? '⏸ Cancelled' : '✓ Bulk scan complete') + '</strong><br>' +
					ok + ' succeeded · ' + failed + ' failed · ' +
					(avg !== null ? 'average score ' + avg + '/100' : 'no scores recorded') +
					' · took ' + formatElapsed(Date.now() - start);
				if (summary) {
					summary.innerHTML = html;
					summary.style.display = '';
					if (wasCancelled) {
						summary.style.background = '#fcf0d3';
						summary.style.borderColor = '#d4a017';
						summary.style.color = '#5e3f00';
						summary.style.border = '1px solid #d4a017';
					} else {
						summary.style.background = '#e6f6ea';
						summary.style.borderColor = '#117a3a';
						summary.style.color = '#0c4e25';
						summary.style.border = '1px solid #117a3a';
					}
				}
				lens.toast((wasCancelled ? 'Cancelled. ' : 'Done. ') + ok + ' scanned, ' + failed + ' failed.', wasCancelled ? 'warn' : 'ok');

				// Refresh the estimate so the user can see what's left.
				lastSig = null;
				loadEstimate();
			}

			next();
		}

		function updateProgress(done, total, start) {
			var pct = (done / total) * 100;
			bar.style.width = pct.toFixed(1) + '%';
			var elapsed = Date.now() - start;
			var per = elapsed / Math.max(1, done);
			var remain = per * (total - done);
			eta.textContent = done >= 2 ? formatElapsed(remain) + ' remaining' : '';
		}

		function appendLog(target, data, err) {
			if (!log) { return; }
			var row = document.createElement('div');
			row.style.padding = '4px 6px';
			row.style.borderBottom = '1px solid #f0f0f1';
			if (err) {
				row.innerHTML = '<span style="color:#b32d2e">✗</span> #' + target.id + ' ' + escapeHtml(target.title) + ' — <em>' + escapeHtml(err) + '</em>';
			} else {
				var s = data.score;
				var scoreCls = s == null ? '' : (s >= 75 ? 's-high' : s >= 50 ? 's-mid' : 's-low');
				row.innerHTML = '<span style="color:#117a3a">✓</span> #' + target.id + ' ' + escapeHtml(target.title) +
					(s == null ? '' : ' <span class="lens-score ' + scoreCls + '" style="font-size:10px;padding:1px 8px;">' + s + '</span>');
			}
			log.appendChild(row);
			log.scrollTop = log.scrollHeight;
		}

		function formatElapsed(ms) {
			var s = Math.round(ms / 1000);
			if (s < 60) { return s + 's'; }
			if (s < 3600) { return Math.floor(s / 60) + 'm ' + (s % 60) + 's'; }
			var h = Math.floor(s / 3600);
			var m = Math.floor((s - h * 3600) / 60);
			return h + 'h ' + m + 'm';
		}

		function escapeHtml(s) {
			return String(s == null ? '' : s).replace(/[&<>"\']/g, function (c) {
				return { '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[c];
			});
		}

		// Kick off the initial estimate.
		document.addEventListener('DOMContentLoaded', loadEstimate);
		if (document.readyState !== 'loading') { loadEstimate(); }
	})();

})();
