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

	const api = ZS_SEO.ajax_url;
	const nonce = ZS_SEO.nonce;
	const proUrl = ZS_SEO.pro_url || 'https://zenseo.dev/#pro';

	// ── Helpers ────────────────────────────────────────────────────────────────
	function spinner() {
		return '<span class="zs-seo-spinner"></span>';
	}

	function scoreClass(s) {
		return s >= 70 ? 'high' : s >= 40 ? 'medium' : 'low';
	}

	function escHtml(str) {
		return String(str)
			.replace(/&/g, '&amp;')
			.replace(/</g, '&lt;')
			.replace(/>/g, '&gt;')
			.replace(/"/g, '&quot;');
	}

	// ── Pro Upgrade Modal ──────────────────────────────────────────────────────
	function showProModal(title, tip) {
		$('#zs-seo-pro-modal').remove();
		const isPro = ZS_SEO.is_pro === 'yes';
		const modalTitle = isPro ? 'ZS_SEO Pro Active ⚡' : 'ZS_SEO Pro Feature';
		const ctaButton = isPro
			? '<button class="button button-primary zs-seo-modal-cta" id="zs-seo-pro-modal-close-btn-cta">✓ Feature Active</button>'
			: '<a href="' +
				proUrl +
				'" target="_blank" class="button button-primary zs-seo-modal-cta">🚀 Upgrade to Pro</a>';

		const html =
			'<div id="zs-seo-pro-modal" class="zs-seo-modal-overlay">' +
			'<div class="zs-seo-modal-box">' +
			'<button class="zs-seo-modal-close" id="zs-seo-modal-close-btn">✕</button>' +
			'<div class="zs-seo-modal-icon">⚡</div>' +
			'<h2 class="zs-seo-modal-title">' +
			modalTitle +
			'</h2>' +
			'<p class="zs-seo-modal-issue"><strong>' +
			escHtml(title) +
			'</strong></p>' +
			'<p class="zs-seo-modal-tip">' +
			escHtml(tip) +
			'</p>' +
			(isPro
				? ''
				: '<div class="zs-seo-modal-features">' +
					'<div class="zs-seo-modal-feat">✅ Auto PNG → WebP conversion</div>' +
					'<div class="zs-seo-modal-feat">✅ Auto inject loading="lazy"</div>' +
					'<div class="zs-seo-modal-feat">✅ Auto fix image dimensions</div>' +
					'<div class="zs-seo-modal-feat">✅ One-click bulk fix all issues</div>' +
					'<div class="zs-seo-modal-feat">✅ Scheduled SEO scans</div>' +
					'<div class="zs-seo-modal-feat">✅ PDF reports & white-label</div>' +
					'</div>') +
			ctaButton +
			(isPro
				? ''
				: '<p class="zs-seo-modal-note">14-day money-back guarantee</p>') +
			'</div></div>';
		$('body').append(html);
		$('#zs-seo-pro-modal').css('display', 'flex').hide().fadeIn(200);
	}

	$(document).on(
		'click',
		'#zs-seo-modal-close-btn, #zs-seo-pro-modal-close-btn-cta, .zs-seo-modal-overlay',
		function (e) {
			if (
				$(e.target).is('.zs-seo-modal-overlay') ||
				$(e.target).is('#zs-seo-modal-close-btn') ||
				$(e.target).is('#zs-seo-pro-modal-close-btn-cta')
			) {
				$('#zs-seo-pro-modal').fadeOut(150, function () {
					$(this).remove();
				});
			}
		},
	);

	// ── Custom Notification Modal ───────────────────────────────────────────────
	function showNotification(
		title,
		message,
		isSuccess,
		filename = '',
		imgSrc = '',
		attachmentId = 0,
		postId = 0,
		themeFile = '',
	) {
		$('#zs-seo-notification-modal').remove();
		const icon = isSuccess ? '✅' : 'ℹ';
		const titleColor = isSuccess ? '#00b894' : '#6c5ce7';

		let imgHtml = '';
		if (imgSrc) {
			imgHtml =
				'<div style="margin: 15px 0 20px; border: 1px solid #e2e8f0; border-radius: 8px; padding: 12px; background: #f8fafc; display: inline-block; max-width: 100%; box-sizing: border-box; text-align: center; width: 100%;">' +
				'<p style="margin: 0 0 10px; font-size: 11px; color: #64748b; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; text-align: center;">Target Image Details</p>' +
				'<div style="display: flex; justify-content: center; align-items: center; background: #fff; border: 1px solid #f1f5f9; padding: 10px; border-radius: 6px; min-height: 80px; max-height: 140px; overflow: hidden; margin-bottom: 10px;">' +
				'<img src="' +
				escHtml(imgSrc) +
				'" style="max-height: 120px; max-width: 100%; object-fit: contain; border-radius: 4px; display: block;" />' +
				'</div>' +
				'<p style="margin: 8px 0 0; font-size: 12px; color: #1e293b; word-break: break-all; font-family: monospace; background: #e2e8f0; padding: 6px 10px; border-radius: 4px; font-weight: 600; text-align: center;">' +
				escHtml(filename) +
				'</p>' +
				'<p style="margin: 6px 0 0; font-size: 11px; color: #94a3b8; word-break: break-all; text-align: center;">Full Path: <a href="' +
				escHtml(imgSrc) +
				'" target="_blank" style="color: #6c5ce7; text-decoration: underline;">' +
				escHtml(imgSrc) +
				'</a></p>' +
				(themeFile
					? '<p style="margin: 8px 0 0; font-size: 11px; color: #7c3aed; word-break: break-all; text-align: center; font-family: monospace;">📁 Modified file: <strong>' +
						escHtml(themeFile.replace(/.*\/themes\//, 'themes/')) +
						'</strong></p>'
					: '') +
				'</div>';
		}

		const isPngFix =
			isSuccess &&
			(attachmentId > 0 ||
				imgSrc.toLowerCase().indexOf('.png') !== -1 ||
				themeFile !== '');
		const ctaButton = isPngFix
			? '<div style="display: flex; gap: 12px; margin-top: 16px; width: 100%;">' +
				'<button type="button" class="button" id="zs-seo-noti-revert-btn" data-attachment-id="' +
				attachmentId +
				'" data-img-src="' +
				escHtml(imgSrc) +
				'" data-post-id="' +
				postId +
				'" data-theme-file="' +
				escHtml(themeFile) +
				'" style="flex: 1; height: 38px; font-size: 13px; font-weight: 600; border-radius: 6px; color: #dc2626; border-color: #fca5a5; background: #fff5f5; cursor: pointer;">↩ Revert</button>' +
				'<button type="button" class="button button-primary" id="zs-seo-noti-close-btn-cta" style="flex: 1; height: 38px; font-size: 13px; font-weight: 600; border-radius: 6px; text-align: center;">Got it, Thanks!</button>' +
				'</div>'
			: '<button type="button" class="button button-primary zs-seo-modal-cta" id="zs-seo-noti-close-btn-cta" style="width: 100%; font-size: 14px; padding: 8px 0; border-radius: 6px;">Got it, Thanks!</button>';

		const html =
			'<div id="zs-seo-notification-modal" class="zs-seo-modal-overlay">' +
			'<div class="zs-seo-modal-box" style="max-width: 520px; padding: 32px 28px 24px; box-sizing: border-box;">' +
			'<button class="zs-seo-modal-close" id="zs-seo-noti-close-btn">✕</button>' +
			'<div class="zs-seo-modal-icon" style="font-size: 48px; margin-bottom: 28px;">' +
			icon +
			'</div>' +
			'<h2 class="zs-seo-modal-title" style="color: ' +
			titleColor +
			'; margin-top: 0; font-size: 22px;">' +
			escHtml(title) +
			'</h2>' +
			imgHtml +
			'<p style="margin: 12px 0 24px; font-size:14px; line-height:1.6; color:#334155; text-align: left; background: ' +
			(isSuccess ? '#f0fdf4' : '#fef2f2') +
			'; padding: 14px 18px; border-left: 4px solid ' +
			(isSuccess ? '#00b894' : '#ef4444') +
			'; border-radius: 4px; box-sizing: border-box;">' +
			escHtml(message) +
			'</p>' +
			ctaButton +
			'</div></div>';
		$('body').append(html);
		$('#zs-seo-notification-modal')
			.css({ display: 'flex', opacity: 0 })
			.animate({ opacity: 1 }, 220);
	}

	$(document).on(
		'click',
		'#zs-seo-noti-close-btn, #zs-seo-noti-close-btn-cta',
		function () {
			$('#zs-seo-notification-modal').fadeOut(150, function () {
				$(this).remove();
			});
		},
	);

	$(document).on('click', '#zs-seo-noti-revert-btn', function () {
		const btn = $(this);
		const attachmentId = btn.data('attachment-id');
		const imgSrc = btn.data('img-src');
		const postId = btn.data('post-id');
		const themeFile = btn.data('theme-file') || '';

		btn.prop('disabled', true).text('↩ Reverting...');
		$.post(
			api,
			{
				action: 'zs_seo_pro_revert_issue',
				nonce: nonce,
				post_id: postId,
				attachment_id: attachmentId,
				img_src: imgSrc,
				theme_file: themeFile,
			},
			function (r) {
				if (r.success) {
					$('#zs-seo-notification-modal').fadeOut(150, function () {
						$(this).remove();
					});
					// Refresh scan
					if ($('#zs-seo-run-single').length) {
						$('#zs-seo-run-single').trigger('click');
					} else if ($('#zs-seo-run-audit').length) {
						$('#zs-seo-run-audit').trigger('click');
					} else {
						// Fallback: click view issues if inside detail row
						location.reload();
					}
				} else {
					alert(r.data.message || 'Failed to revert image.');
					btn.prop('disabled', false).text('↩ Revert');
				}
			},
		);
	});

	// ── JS Defer Notification Modal ─────────────────────────────────────────────
	function showJsDeferNotification(message, postId) {
		$('#zs-seo-js-defer-modal').remove();
		const html =
			'<div id="zs-seo-js-defer-modal" class="zs-seo-modal-overlay">' +
			'<div class="zs-seo-modal-box" style="max-width: 480px; padding: 32px 28px 24px; box-sizing: border-box;">' +
			'<button class="zs-seo-modal-close" id="zs-seo-defer-close-x">✕</button>' +
			'<div style="font-size: 42px; text-align: center; margin-bottom: 12px;">⚡</div>' +
			'<h3 style="margin: 0 0 8px; text-align: center; color: #15803d; font-size: 18px; font-weight: 700;">Script Defer Activated!</h3>' +
			'<p style="text-align: center; color: #64748b; font-size: 13px; margin: 0 0 16px;">' +
			escHtml(message) +
			'</p>' +
			'<div style="background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 8px; padding: 14px 16px; margin-bottom: 18px;">' +
			'<p style="margin: 0 0 6px; font-size: 12px; font-weight: 700; color: #15803d; text-transform: uppercase; letter-spacing: 0.5px;">✅ What Happened</p>' +
			'<ul style="margin: 0; padding-left: 18px; font-size: 12px; color: #374151; line-height: 1.8;">' +
			'<li>All safe scripts now load with <code>defer</code></li>' +
			'<li>jQuery &amp; jQuery Migrate are <strong>excluded</strong> (no conflicts)</li>' +
			'<li>Scripts already with async/defer are untouched</li>' +
			'<li>Applied globally on every page — no file editing</li>' +
			'</ul>' +
			'</div>' +
			'<div style="display: flex; gap: 10px; width: 100%;">' +
			'<button type="button" id="zs-seo-defer-disable-btn" data-post-id="' +
			postId +
			'" class="button" style="flex: 1; height: 38px; font-size: 12px; font-weight: 600; border-radius: 6px; color: #dc2626; border-color: #fca5a5; background: #fff5f5;">↩ Disable Defer</button>' +
			'<button type="button" id="zs-seo-defer-close-btn" class="button button-primary" style="flex: 2; height: 38px; font-size: 13px; font-weight: 600; border-radius: 6px;">Got it!</button>' +
			'</div>' +
			'</div></div>';
		$('body').append(html);
		$('#zs-seo-js-defer-modal')
			.css({ display: 'flex', opacity: 0 })
			.animate({ opacity: 1 }, 220);
	}

	$(document).on(
		'click',
		'#zs-seo-defer-close-btn, #zs-seo-defer-close-x',
		function () {
			$('#zs-seo-js-defer-modal').fadeOut(150, function () {
				$(this).remove();
			});
		},
	);

	$(document).on('click', '#zs-seo-defer-disable-btn', function () {
		const btn = $(this);
		btn.prop('disabled', true).text('↩ Disabling...');
		$.post(
			api,
			{
				action: 'zs_seo_pro_fix_issue',
				nonce: nonce,
				post_id: btn.data('post-id'),
				fix_key: 'js_defer_disable',
			},
			function (r) {
				$('#zs-seo-js-defer-modal').fadeOut(150, function () {
					$(this).remove();
				});
				if ($('#zs-seo-run-single').length) {
					$('#zs-seo-run-single').trigger('click');
				} else if ($('#zs-seo-run-audit').length) {
					$('#zs-seo-run-audit').trigger('click');
				} else {
					location.reload();
				}
			},
		);
	});

	// ── Edit Alt Modal (replaces browser prompt) ───────────────────────────────

	function showEditModal(id, currentAlt, $card) {
		$('#zs-seo-edit-modal').remove();
		const html =
			'<div id="zs-seo-edit-modal" class="zs-seo-modal-overlay">' +
			'<div class="zs-seo-modal-box zs-seo-edit-modal-box">' +
			'<button class="zs-seo-modal-close" id="zs-seo-edit-close-btn">✕</button>' +
			'<h3>✏ Edit Alt Text</h3>' +
			'<textarea id="zs-seo-edit-alt-input" class="widefat" rows="3" placeholder="Enter descriptive alt text...">' +
			escHtml(currentAlt) +
			'</textarea>' +
			'<p class="description" style="margin-top:6px;">Describe the image clearly. Include keywords naturally.</p>' +
			'<div class="zs-seo-edit-modal-actions">' +
			'<button type="button" id="zs-seo-edit-save-btn" class="button button-primary" data-id="' +
			id +
			'">💾 Save Alt Text</button>' +
			'<button type="button" id="zs-seo-edit-cancel-btn" class="button">Cancel</button>' +
			'</div>' +
			'</div></div>';
		$('body').append(html);
		$('#zs-seo-edit-modal').css('display', 'flex').hide().fadeIn(200);
		$('#zs-seo-edit-alt-input').focus().select();

		// Save
		$(document).one('click', '#zs-seo-edit-save-btn', function () {
			const newAlt = $('#zs-seo-edit-alt-input').val().trim();
			if (!newAlt) {
				$('#zs-seo-edit-alt-input').css('border-color', 'red');
				return;
			}
			$.post(
				api,
				{ action: 'zs_seo_save_alt', nonce: nonce, attachment_id: id, alt: newAlt },
				function (r) {
					if (r.success) {
						$card.find('.zs-seo-img-alt-current').text(newAlt);
						$card.find('.zs-seo-edit-alt').data('alt', newAlt);
						$('#zs-seo-edit-modal').fadeOut(150, function () {
							$(this).remove();
						});
					}
				},
			);
		});

		// Cancel / close
		$(document).on(
			'click',
			'#zs-seo-edit-cancel-btn, #zs-seo-edit-close-btn',
			function () {
				$('#zs-seo-edit-modal').fadeOut(150, function () {
					$(this).remove();
				});
			},
		);
	}

	// ── Render Audit Results ───────────────────────────────────────────────────
	function renderIssues(label, section, postId) {
		if (!section) return '';
		let html =
			'<div class="zs-seo-audit-section"><h4>' +
			label +
			'</h4><ul class="zs-seo-issue-list">';
		const isPro = ZS_SEO.is_pro === 'yes';

		(section.issues || []).forEach(function (issue) {
			const proBtn = issue.pro
				? isPro
					? ' <button type="button" class="zs-seo-fix-pro-btn" data-post-id="' +
						postId +
						'" data-fix-key="' +
						escHtml(issue.fix_key) +
						'" data-msg="' +
						escHtml(issue.msg) +
						'" data-tip="' +
						escHtml(issue.fix_tip || '') +
						'" data-filename="' +
						escHtml(issue.filename || '') +
						'" data-img-src="' +
						escHtml(issue.img_src || '') +
						'">🔧 Fix Now</button>'
					: ' <button type="button" class="zs-seo-fix-pro-btn" data-msg="' +
						escHtml(issue.msg) +
						'" data-tip="' +
						escHtml(issue.fix_tip || '') +
						'">⚡ Fix Now (Pro)</button>'
				: issue.fix_url
					? ' <a href="' +
						escHtml(issue.fix_url) +
						'" class="zs-seo-fix-free-btn">🔧 Fix Now</a>'
					: issue.fix_tip
						? ' <button type="button" class="zs-seo-fix-tip-btn" data-tip="' +
							escHtml(issue.fix_tip) +
							'">💡 How to Fix</button>'
						: '';

			let detailsBtn = '';
			let detailsHtml = '';
			if (issue.details && issue.details.length > 0) {
				const detailsId =
					'zs-seo-details-' + Math.random().toString(36).substr(2, 9);
				detailsBtn =
					' <button type="button" class="zs-seo-toggle-details-btn button button-small" data-target="#' +
					detailsId +
					'" style="margin-left: 8px; font-size: 11px; padding: 0 8px; height: 24px; min-height: 24px; line-height: 22px; cursor: pointer;">🔍 Show Links (' +
					issue.details.length +
					')</button>';

				let rows = '';
				issue.details.forEach(function (detail) {
					rows +=
						'<tr>' +
						'<td style="padding: 6px; border-bottom: 1px solid #f1f5f9; color: #334155; font-weight: 600;">' +
						escHtml(detail.text) +
						'</td>' +
						'<td style="padding: 6px; border-bottom: 1px solid #f1f5f9; color: #64748b; font-family: monospace; font-size: 11px; word-break: break-all;">' +
						escHtml(detail.href || '#') +
						'</td>' +
						'</tr>';
				});

				detailsHtml =
					'<div id="' +
					detailsId +
					'" class="zs-seo-details-panel" style="display: none; margin-top: 10px; background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 6px; padding: 12px; box-sizing: border-box; width: 100%;">' +
					'<p style="margin: 0 0 8px; font-size: 11px; color: #475569; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; text-align: left;">Links Missing aria-label Attribute:</p>' +
					'<table style="width: 100%; border-collapse: collapse; text-align: left;">' +
					'<thead>' +
					'<tr style="color: #64748b; font-size: 11px; font-weight: 600; text-transform: uppercase; border-bottom: 1px solid #cbd5e1; text-align: left;">' +
					'<th style="padding: 4px 6px;">Link Text</th>' +
					'<th style="padding: 4px 6px;">URL (href)</th>' +
					'</tr>' +
					'</thead>' +
					'<tbody>' +
					rows +
					'</tbody>' +
					'</table>' +
					'</div>';
			}

			html +=
				'<li class="zs-seo-issue-' +
				escHtml(issue.type) +
				'" style="display: flex; flex-direction: column; align-items: flex-start; gap: 8px; width: 100%; box-sizing: border-box;">' +
				'<div style="display: flex; align-items: center; flex-wrap: wrap; gap: 6px; width: 100%;">' +
				'<span class="zs-seo-issue-text">' +
				escHtml(issue.msg) +
				'</span>' +
				proBtn +
				detailsBtn +
				'</div>' +
				(issue.location
					? '<div class="zs-seo-issue-location" style="display: flex; align-items: center; gap: 6px; font-size: 11px; color: #64748b; background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 4px; padding: 4px 10px; max-width: 100%; box-sizing: border-box; overflow: hidden;">' +
						'<span style="font-size: 13px; flex-shrink: 0;">📁</span>' +
						'<span style="font-family: monospace; word-break: break-all; font-weight: 600; color: ' +
						(issue.location === 'Database (Post Content)' ? '#0369a1' : '#7c3aed') +
						';">' +
						escHtml(issue.location) +
						'</span>' +
						'</div>'
					: '') +
				detailsHtml +
				(issue.fix_tip && !issue.pro && !issue.fix_url
					? '<div class="zs-seo-fix-tip-text" style="display:none; width: 100%;">' +
						escHtml(issue.fix_tip) +
						'</div>'
					: '') +
				'</li>';
		});

		(section.good || []).forEach(function (msg) {
			html += '<li class="zs-seo-issue-good">' + escHtml(msg) + '</li>';
		});

		html += '</ul></div>';
		return html;
	}

	function renderFullAudit(data, postId) {
		const sc = scoreClass(data.score);
		let html =
			'<div class="zs-seo-audit-score-row">' +
			'<span class="zs-seo-badge zs-seo-score-' +
			sc +
			'">Score: ' +
			data.score +
			'/100</span>' +
			'</div>';
		html += renderIssues('&#x1F4C4; On-Page SEO', data.on_page, postId);
		html += renderIssues('&#x1F524; Heading Structure', data.headings, postId);
		html += renderIssues('&#x1F5BC; Images', data.images, postId);
		html += renderIssues('&#x26A1; Performance', data.performance, postId);
		html += renderIssues('&#x267F; Accessibility', data.accessibility, postId);
		html += renderIssues('&#x1F916; GEO / AI Search', data.geo, postId);
		return html;
	}

	// ── Toggle Issue Details Dropdown ──────────────────────────────────────────
	$(document).on('click', '.zs-seo-toggle-details-btn', function () {
		const btn = $(this);
		const targetSelector = btn.data('target');
		const $target = $(targetSelector);
		$target.slideToggle(150);
		if (btn.text().indexOf('Show') !== -1) {
			btn.text(btn.text().replace('Show', 'Hide').replace('🔍', '✕'));
		} else {
			btn.text(btn.text().replace('Hide', 'Show').replace('✕', '🔍'));
		}
	});

	// ── Fix Now Pro button click ───────────────────────────────────────────────
	$(document).on('click', '.zs-seo-fix-pro-btn', function () {
		const btn = $(this);
		const msg = btn.data('msg');
		const tip = btn.data('tip');
		const filename = btn.data('filename') || '';
		const imgSrc = btn.data('img-src') || '';

		if (ZS_SEO.is_pro === 'yes') {
			const postId = btn.data('post-id');
			const fixKey = btn.data('fix-key');
			if (!postId || !fixKey) return;

			// ── JS Defer: site-wide option fix, special handler ─────────────────
			if (fixKey === 'js_defer') {
				btn.prop('disabled', true).html(spinner() + ' Activating...');
				$.post(
					api,
					{
						action: 'zs_seo_pro_fix_issue',
						nonce: nonce,
						post_id: postId,
						fix_key: 'js_defer',
					},
					function (r) {
						btn.prop('disabled', false).text('✅ Defer Active');
						btn.css({
							background: '#dcfce7',
							color: '#15803d',
							borderColor: '#86efac',
						});
						if (r.success) {
							showJsDeferNotification(r.data.message, postId);
							if ($('#zs-seo-run-single').length) {
								setTimeout(function () {
									$('#zs-seo-run-single').trigger('click');
								}, 1500);
							} else if ($('#zs-seo-run-audit').length) {
								setTimeout(function () {
									$('#zs-seo-run-audit').trigger('click');
								}, 1500);
							}
						} else {
							showNotification('Error', r.data.message, false, '', '', 0, postId, '');
						}
					},
				);
				return;
			}

			btn.prop('disabled', true).html(spinner() + ' Fixing...');
			$.post(
				api,
				{
					action: 'zs_seo_pro_fix_issue',
					nonce: nonce,
					post_id: postId,
					fix_key: fixKey,
					img_src: imgSrc,
				},
				function (r) {
					btn.prop('disabled', false).text('🔧 Fix Now');
					if (r.success) {
						const themeFile = r.data.theme_file || '';
						showNotification(
							'Success',
							r.data.message,
							true,
							filename,
							imgSrc,
							r.data.attachment_id || 0,
							postId,
							themeFile,
						);
						// Refresh audit view after fix
						if ($('#zs-seo-run-single').length) {
							$('#zs-seo-run-single').trigger('click');
						} else if ($('#zs-seo-run-audit').length) {
							$('#zs-seo-run-audit').trigger('click');
						} else {
							const $detRow = btn.closest('.zs-seo-detail-row');
							if ($detRow.length) {
								const pid = $detRow.attr('id').replace('zs-seo-detail-', '');
								delete auditCache[pid];
								const $btnView = $('.zs-seo-view-issues[data-post-id="' + pid + '"]');
								$detRow.hide();
								$btnView.trigger('click');
							}
						}
					} else {
						showNotification(
							'Optimization Info',
							r.data.message,
							false,
							filename,
							imgSrc,
							0,
							postId,
						);
					}
				},
			);
		} else {
			showProModal(msg, tip);
		}
	});

	// ── How to Fix tip toggle ──────────────────────────────────────────────────
	$(document).on('click', '.zs-seo-fix-tip-btn', function () {
		$(this).next('.zs-seo-fix-tip-text').slideToggle(200);
	});

	// ── Character counters ─────────────────────────────────────────────────────
	function initCounters() {
		$('#zs_seo_title')
			.on('input', function () {
				$('#zs-seo-title-count').text($(this).val().length);
			})
			.trigger('input');
		$('#zs_seo_description')
			.on('input', function () {
				$('#zs-seo-desc-count').text($(this).val().length);
			})
			.trigger('input');
	}

	// ── Meta box audit ─────────────────────────────────────────────────────────
	$(document).on('click', '#zs-seo-run-audit', function () {
		const btn = $(this);
		const postId = btn.data('post-id');
		const $res = $('#zs-seo-audit-results');
		const $badge = $('#zs-seo-score-badge');
		btn.prop('disabled', true).text(ZS_SEO.i18n.analyzing);
		$res.html(spinner() + ' Analyzing...');
		$.post(
			api,
			{ action: 'zs_seo_analyze_post', nonce: nonce, post_id: postId },
			function (r) {
				btn.prop('disabled', false).text('🔍 Run SEO Audit');
				if (r.success) {
					const sc = scoreClass(r.data.score);
					$badge
						.removeClass('zs-seo-score-high zs-seo-score-medium zs-seo-score-low')
						.addClass('zs-seo-score-' + sc)
						.text('Score: ' + r.data.score + '/100')
						.show();
					$res.html(renderFullAudit(r.data, postId));
				} else {
					$res.html('<p style="color:red;">' + ZS_SEO.i18n.error + '</p>');
				}
			},
		);
	});

	// ── Audit page single ──────────────────────────────────────────────────────
	$(document).on('click', '#zs-seo-run-single', function () {
		const postId = $('#zs-seo-post-select').val();
		const $res = $('#zs-seo-single-results');
		if (!postId) {
			alert('Please select a post/page.');
			return;
		}
		$res.html(spinner() + ' Analyzing...');
		$.post(
			api,
			{ action: 'zs_seo_analyze_post', nonce: nonce, post_id: postId },
			function (r) {
				$res.html(
					r.success
						? renderFullAudit(r.data, postId)
						: '<p style="color:red;">' + ZS_SEO.i18n.error + '</p>',
				);
			},
		);
	});

	// ── Dashboard Scan All ─────────────────────────────────────────────────────
	var auditCache = {};

	$(document).on('click', '#zs-seo-scan-all', function () {
		const btn = $(this);
		const $res = $('#zs-seo-scan-results');
		btn.prop('disabled', true).html(spinner() + ' Scanning...');
		$res.html('');
		auditCache = {};
		$.post(api, { action: 'zs_seo_analyze_all', nonce: nonce }, function (r) {
			btn.prop('disabled', false).text('🚀 Scan All Pages');
			if (!r.success) {
				$res.html('<p style="color:red;">' + ZS_SEO.i18n.error + '</p>');
				return;
			}
			let html =
				'<table class="wp-list-table widefat fixed" id="zs-seo-all-table">' +
				'<thead><tr><th>Page / Post</th><th style="width:120px;">Score</th><th style="width:70px;">Issues</th><th style="width:220px;">Actions</th></tr></thead><tbody>';
			r.data.forEach(function (item) {
				const sc = scoreClass(item.score);
				const bar =
					'<div class="zs-seo-score-bar"><div class="zs-seo-score-fill zs-seo-fill-' +
					sc +
					'" style="width:' +
					item.score +
					'%"></div></div>';
				html +=
					'<tr>' +
					'<td><strong>' +
					escHtml(item.title) +
					'</strong></td>' +
					'<td><span class="zs-seo-score-cell zs-seo-score-' +
					sc +
					'-text">' +
					item.score +
					'/100</span>' +
					bar +
					'</td>' +
					'<td><span class="zs-seo-issue-count' +
					(item.issues > 10
						? ' zs-seo-count-high'
						: item.issues > 5
							? ' zs-seo-count-med'
							: '') +
					'">' +
					item.issues +
					'</span></td>' +
					'<td><button type="button" class="button button-small zs-seo-view-issues" data-post-id="' +
					item.post_id +
					'">🔍 Issues</button> ' +
					'<a href="' +
					item.edit_url +
					'" class="button button-small">✏ Edit</a> ' +
					'<a href="' +
					item.view_url +
					'" class="button button-small" target="_blank">👁 View</a></td>' +
					'</tr>' +
					'<tr class="zs-seo-detail-row" id="zs-seo-detail-' +
					item.post_id +
					'" style="display:none;">' +
					'<td colspan="4" class="zs-seo-detail-cell"><div class="zs-seo-detail-inner">' +
					spinner() +
					'</div></td></tr>';
			});
			html += '</tbody></table>';
			$res.html(html);
		});
	});

	$(document).on('click', '.zs-seo-view-issues', function () {
		const postId = $(this).data('post-id');
		const $detRow = $('#zs-seo-detail-' + postId);
		const $inner = $detRow.find('.zs-seo-detail-inner');
		const isOpen = $detRow.is(':visible');
		if (isOpen) {
			$detRow.hide();
			$(this).text('🔍 Issues');
			return;
		}
		$detRow.show();
		$(this).text('✕ Hide');
		if (auditCache[postId]) {
			$inner.html(renderFullAudit(auditCache[postId], postId));
			return;
		}
		$inner.html(spinner() + ' Analyzing...');
		$.post(
			api,
			{ action: 'zs_seo_analyze_post', nonce: nonce, post_id: postId },
			function (r) {
				if (r.success) {
					auditCache[postId] = r.data;
					$inner.html(renderFullAudit(r.data, postId));
				} else {
					$inner.html('<p style="color:red;">' + ZS_SEO.i18n.error + '</p>');
				}
			},
		);
	});

	// ── Redirects ──────────────────────────────────────────────────────────────
	$(document).on('click', '#zs-seo-save-redirect', function () {
		const source = $('#zs-seo-redirect-source').val().trim();
		const target = $('#zs-seo-redirect-target').val().trim();
		const type = $('#zs-seo-redirect-type').val();
		if (!source || !target) {
			alert('Source and target are required.');
			return;
		}
		$.post(
			api,
			{ action: 'zs_seo_save_redirect', nonce: nonce, source, target, type },
			function (r) {
				if (r.success) location.reload();
				else alert(r.data.message || ZS_SEO.i18n.error);
			},
		);
	});
	$(document).on('click', '.zs-seo-delete-redirect', function () {
		if (!confirm('Delete this redirect?')) return;
		const id = $(this).data('id'),
			$row = $(this).closest('tr');
		$.post(
			api,
			{ action: 'zs_seo_delete_redirect', nonce: nonce, id },
			function (r) {
				if (r.success)
					$row.fadeOut(300, function () {
						$(this).remove();
					});
			},
		);
	});

	// ── FAQ ────────────────────────────────────────────────────────────────────
	var faqIndex = $('.zs-seo-faq-row').length;
	$(document).on('click', '#zs-seo-add-faq', function () {
		$('#zs-seo-faq-list').append(
			'<div class="zs-seo-faq-row" data-index="' +
				faqIndex +
				'">' +
				'<input type="text" name="zs_seo_faq_question[]" placeholder="Question" class="widefat" style="margin-bottom:5px;" />' +
				'<textarea name="zs_seo_faq_answer[]" class="widefat" rows="2" placeholder="Answer"></textarea>' +
				'<button type="button" class="button zs-seo-remove-faq" style="margin-top:4px;">✕ Remove</button>' +
				'<hr style="border-color:#eee;"></div>',
		);
		faqIndex++;
	});
	$(document).on('click', '.zs-seo-remove-faq', function () {
		$(this).closest('.zs-seo-faq-row').remove();
	});

	// ══════════════════════════════════════════════════════════════════════════
	// IMAGE ALT MANAGER
	// ══════════════════════════════════════════════════════════════════════════

	function updateSelectedCount() {
		const count = $('.zs-seo-img-select:checked').length;
		$('#zs-seo-selected-count').text(count + ' selected');
		$('#zs-seo-bulk-auto-generate, #zs-seo-bulk-save').prop(
			'disabled',
			count === 0,
		);
	}

	$(document).on('change', '#zs-seo-select-all', function () {
		const checked = $(this).is(':checked');
		$('.zs-seo-img-select').prop('checked', checked);
		$('.zs-seo-img-card').toggleClass('zs-seo-selected', checked);
		updateSelectedCount();
	});

	$(document).on('change', '.zs-seo-img-select', function () {
		$(this)
			.closest('.zs-seo-img-card')
			.toggleClass('zs-seo-selected', $(this).is(':checked'));
		updateSelectedCount();
		const total = $('.zs-seo-img-select').length,
			checked = $('.zs-seo-img-select:checked').length;
		$('#zs-seo-select-all')
			.prop('indeterminate', checked > 0 && checked < total)
			.prop('checked', checked === total);
	});

	// Single Auto Generate
	$(document).on('click', '.zs-seo-auto-generate', function () {
		const btn = $(this),
			id = btn.data('id');
		const $input = $('.zs-seo-alt-input[data-id="' + id + '"]');
		const $status = $('#zs-seo-status-' + id);
		btn.prop('disabled', true).text('...');
		$status.removeClass('success error').text('Generating...');
		$.post(
			api,
			{
				action: 'zs_seo_auto_alt',
				nonce: nonce,
				attachment_id: id,
				filename: btn.data('filename'),
				title: btn.data('title'),
			},
			function (r) {
				btn.prop('disabled', false).text('🤖 Auto');
				if (r.success) {
					$input.val(r.data.alt).addClass('zs-seo-alt-filled');
					$status.addClass('success').text('✓ Generated!');
					setTimeout(function () {
						$status.text('');
					}, 3000);
				} else {
					$status.addClass('error').text('✕ Failed');
				}
			},
		);
	});

	// Single Save
	$(document).on('click', '.zs-seo-save-alt', function () {
		const btn = $(this),
			id = btn.data('id');
		const alt = $('.zs-seo-alt-input[data-id="' + id + '"]')
			.val()
			.trim();
		const $status = $('#zs-seo-status-' + id),
			$card = btn.closest('.zs-seo-img-card');
		if (!alt) {
			$status.addClass('error').text('⚠ Enter alt text!');
			setTimeout(function () {
				$status.removeClass('error').text('');
			}, 3000);
			return;
		}
		btn.prop('disabled', true).text('...');
		$.post(
			api,
			{ action: 'zs_seo_save_alt', nonce: nonce, attachment_id: id, alt: alt },
			function (r) {
				btn.prop('disabled', false).text('💾 Save');
				if (r.success) {
					$card.addClass('zs-seo-saved');
					$status.addClass('success').text('✓ Saved!');
					setTimeout(function () {
						$card.fadeOut(400, function () {
							$(this).remove();
						});
					}, 1500);
				} else {
					$status.addClass('error').text('✕ Failed');
				}
			},
		);
	});

	// Bulk Auto Generate
	$(document).on('click', '#zs-seo-bulk-auto-generate', function () {
		const btn = $(this),
			ids = [];
		$('.zs-seo-img-select:checked').each(function () {
			ids.push($(this).data('id'));
		});
		if (!ids.length) return;
		btn.prop('disabled', true).html(spinner() + ' Generating...');
		$.post(
			api,
			{ action: 'zs_seo_bulk_auto_alt', nonce: nonce, ids: ids },
			function (r) {
				btn.prop('disabled', false).text('🤖 Auto Generate Alt (Selected)');
				if (r.success) {
					$.each(r.data.alts, function (id, alt) {
						$('.zs-seo-alt-input[data-id="' + id + '"]')
							.val(alt)
							.addClass('zs-seo-alt-filled');
						$('#zs-seo-status-' + id)
							.addClass('success')
							.text('✓ Generated!');
					});
					$('#zs-seo-bulk-save').prop('disabled', false);
				}
			},
		);
	});

	// Bulk Save
	$(document).on('click', '#zs-seo-bulk-save', function () {
		const btn = $(this),
			alts = {};
		$('.zs-seo-alt-input').each(function () {
			const v = $(this).val().trim();
			if (v) alts[$(this).data('id')] = v;
		});
		if (!Object.keys(alts).length) {
			alert('No alt text entered yet.');
			return;
		}
		btn.prop('disabled', true).html(spinner() + ' Saving...');
		$.post(
			api,
			{ action: 'zs_seo_bulk_save_alts', nonce: nonce, alts: alts },
			function (r) {
				btn.prop('disabled', false).text('💾 Save All Edited');
				if (r.success) {
					Object.keys(alts).forEach(function (id) {
						$('.zs-seo-img-card[data-id="' + id + '"]')
							.addClass('zs-seo-saved')
							.delay(600)
							.fadeOut(400, function () {
								$(this).remove();
							});
					});
					alert('✅ ' + r.data.message);
				}
			},
		);
	});

	// Edit existing alt — now uses modal
	$(document).on('click', '.zs-seo-edit-alt', function () {
		const $card = $(this).closest('.zs-seo-img-card');
		showEditModal($(this).data('id'), $(this).data('alt'), $card);
	});

	// Trigger Freemius checkout when custom pricing upgrade button is clicked
	$(document).on('click', '.zs-seo-pricing-btn-pro', function (e) {
		e.preventDefault();

		let $freemiusBtn = $('#fs_pricing_wrapper')
			.find('button, a, .fs-button')
			.filter(function () {
				const txt = $(this).text().toUpperCase();
				return (
					txt.indexOf('UPGRADE') !== -1 ||
					txt.indexOf('BUY') !== -1 ||
					txt.indexOf('NOW') !== -1
				);
			});

		if ($freemiusBtn.length) {
			$freemiusBtn.first().trigger('click');
		} else {
			const btn = $(this);
			const originalText = btn.html();
			btn.prop('disabled', true).html(spinner() + ' Opening Checkout...');

			let attempts = 0;
			const interval = setInterval(function () {
				attempts++;
				$freemiusBtn = $('#fs_pricing_wrapper')
					.find('button, a, .fs-button')
					.filter(function () {
						const txt = $(this).text().toUpperCase();
						return (
							txt.indexOf('UPGRADE') !== -1 ||
							txt.indexOf('BUY') !== -1 ||
							txt.indexOf('NOW') !== -1
						);
					});

				if ($freemiusBtn.length) {
					clearInterval(interval);
					btn.prop('disabled', false).html(originalText);
					$freemiusBtn.first().trigger('click');
				} else if (attempts > 20) {
					// 2 seconds timeout
					clearInterval(interval);
					btn.prop('disabled', false).html(originalText);
					window.open(btn.attr('href'), '_blank');
				}
			}, 100);
		}
	});

	// ── Image Manager Tab Switcher ─────────────────────────────────────────────
	$(document).on('click', '.zs-seo-tab-btn', function () {
		const tab = $(this).data('tab');
		$('.zs-seo-tab-btn').removeClass('active');
		$(this).addClass('active');
		$('.zs-seo-tab-panel').hide();
		$('#zs-seo-tab-' + tab).show();

		// Lazy-load optimizer data on first open
		if (tab === 'optimizer' && !$('#zs-seo-opt-grid').data('loaded')) {
			loadOptimizerData();
		}
	});

	// ── Load Optimizer Data ────────────────────────────────────────────────────
	function loadOptimizerData() {
		$('#zs-seo-opt-grid-loading').show();
		$('#zs-seo-opt-grid').hide();

		$.post(api, { action: 'zs_seo_get_optimization_data', nonce: nonce }, function (r) {
			$('#zs-seo-opt-grid-loading').hide();
			if (!r.success) return;
			renderOptimizerGrid(r.data);
			$('#zs-seo-opt-grid').data('loaded', true).show();
			updateOptimizerStats(r.data);
		}).fail(function () {
			$('#zs-seo-opt-grid-loading').html('<p style="color:#d63031;">Failed to load image data. Please refresh the page.</p>');
		});
	}

	// ── Render Optimizer Grid ──────────────────────────────────────────────────
	function renderOptimizerGrid(images) {
		const $grid = $('#zs-seo-opt-grid');
		$grid.empty();

		if (!images || images.length === 0) {
			$grid.html('<p style="color:#636e72;padding:20px;">No images found in the Media Library.</p>');
			return;
		}

		images.forEach(function (img) {
			$grid.append(buildOptimizerCard(img));
		});
	}

	// ── Build single optimizer card HTML ──────────────────────────────────────
	function buildOptimizerCard(img) {
		const statusLabel = img.status === 'optimized' ? 'Optimized'
			: img.status === 'needs_opt' ? 'Heavy' : 'OK';
		const statusClass = img.status === 'optimized' ? 'optimized'
			: img.status === 'needs_opt' ? 'needs-opt' : 'ok';

		const savingsBadge = img.est_savings_pct >= 10
			? '<span class="zs-seo-savings-badge">&#x1F4BE; ~' + img.est_savings_pct + '% savings</span>'
			: '<span class="zs-seo-savings-badge small">Already optimal</span>';

		const dimsStr = img.width && img.height ? img.width + ' x ' + img.height + 'px' : 'Unknown dims';

		const revertBtn = img.has_bak
			? '<button type="button" class="button zs-seo-revert-btn" data-id="' + img.id + '">&#x21A9; Revert</button>'
			: '';

		const optimizeDisabled = img.status === 'ok' ? '' : '';

		return $('<div>')
			.addClass('zs-seo-opt-card status-' + img.status)
			.attr('data-id', img.id)
			.attr('data-status', img.status)
			.html(
				'<div class="zs-seo-opt-check">' +
				(img.is_optimizable ? '<input type="checkbox" class="zs-seo-opt-select" data-id="' + img.id + '" />' : '') +
				'</div>' +
				'<div class="zs-seo-opt-preview">' +
				(img.src ? '<img src="' + escHtml(img.src) + '" alt="" loading="lazy" />' : '<div style="font-size:11px;color:#aaa;">No preview</div>') +
				'<span class="zs-seo-opt-status-badge ' + statusClass + '">' + statusLabel + '</span>' +
				'</div>' +
				'<div class="zs-seo-opt-card-body">' +
				'<div class="zs-seo-opt-filename" title="' + escHtml(img.filename) + '">' + escHtml(img.filename.length > 28 ? img.filename.substr(0, 28) + '...' : img.filename) + '</div>' +
				'<div class="zs-seo-opt-meta">' +
				'<div>' +
				'<div class="zs-seo-opt-size">' + img.file_size_kb + ' KiB</div>' +
				'<div class="zs-seo-opt-dims">' + dimsStr + '</div>' +
				'</div>' +
				savingsBadge +
				'</div>' +
				'<div class="zs-seo-opt-result" id="zs-seo-opt-result-' + img.id + '" style="display:none;"></div>' +
				'<div class="zs-seo-opt-actions">' +
				'<button type="button" class="button zs-seo-opt-btn" data-id="' + img.id + '" data-filename="' + escHtml(img.filename) + '">' +
				'&#x1F5DC; Optimize' +
				'</button>' +
				revertBtn +
				'</div>' +
				'</div>'
			);
	}

	// ── Update Optimizer Stats Cards ───────────────────────────────────────────
	function updateOptimizerStats(images) {
		const total     = images.length;
		const needsOpt  = images.filter(i => i.status === 'needs_opt').length;
		const optimized = images.filter(i => i.status === 'optimized').length;
		$('#zs-seo-opt-total').text(total);
		$('#zs-seo-opt-needs').text(needsOpt);
		$('#zs-seo-opt-done').text(optimized);
	}

	// ── Optimizer: Select All ──────────────────────────────────────────────────
	$(document).on('change', '#zs-seo-opt-select-all', function () {
		const checked = $(this).prop('checked');
		$('.zs-seo-opt-select').prop('checked', checked);
		$('.zs-seo-opt-card').toggleClass('zs-seo-selected', checked);
		updateOptSelectedCount();
	});

	$(document).on('change', '.zs-seo-opt-select', function () {
		$(this).closest('.zs-seo-opt-card').toggleClass('zs-seo-selected', $(this).prop('checked'));
		updateOptSelectedCount();
	});

	function updateOptSelectedCount() {
		const count = $('.zs-seo-opt-select:checked').length;
		$('#zs-seo-opt-selected-count').text(count + ' selected');
		$('#zs-seo-bulk-optimize').prop('disabled', count === 0);
	}

	// ── Single Image Optimize ──────────────────────────────────────────────────
	$(document).on('click', '.zs-seo-opt-btn', function () {
		const btn  = $(this);
		const id   = btn.data('id');
		const maxW = $('#zs-seo-opt-max-width').val() || 1920;
		const webp = $('#zs-seo-opt-webp').prop('checked') ? 1 : 0;

		btn.prop('disabled', true).html(spinner() + ' Optimizing...');

		$.post(api, {
			action: 'zs_seo_optimize_image',
			nonce: nonce,
			attachment_id: id,
			target_width: maxW,
			to_webp: webp,
		}, function (r) {
			const $card   = btn.closest('.zs-seo-opt-card');
			const $result = $('#zs-seo-opt-result-' + id);

			if (r.success) {
				const d = r.data;
				btn.html('&#x2705; Done');
				btn.css({ background: '#d4f5e9', color: '#00695c', border: '1px solid #b2f0e0' });

				$result.removeClass('error').addClass('').show().html(
					'<strong>' + d.original_kb + ' KiB</strong> &#x2192; <strong style="color:#00b894;">' + d.new_kb + ' KiB</strong>' +
					' &nbsp; <span style="background:#d4f5e9;color:#00695c;padding:1px 7px;border-radius:10px;font-size:10px;font-weight:700;">-' + d.saved_pct + '%</span>' +
					(d.new_width ? '<br><span style="color:#636e72;">' + d.new_width + ' x ' + d.new_height + 'px</span>' : '') +
					(d.webp_created ? '<br><span style="color:#6c5ce7;">WebP &#x2713; created</span>' : '')
				);

				$card.removeClass('status-needs_opt').addClass('status-optimized');
				$card.attr('data-status', 'optimized');

				// Add revert button if not already there
				if ( !$card.find('.zs-seo-revert-btn').length ) {
					btn.after('<button type="button" class="button zs-seo-revert-btn" data-id="' + id + '">&#x21A9; Revert</button>');
				}

				// Refresh stats
				refreshOptimizerStats();

			} else {
				btn.prop('disabled', false).html('&#x1F5DC; Optimize');
				$result.addClass('error').show().text(r.data.message || 'Optimization failed.');
			}
		}).fail(function () {
			btn.prop('disabled', false).html('&#x1F5DC; Optimize');
		});
	});

	// ── Revert Single Image ────────────────────────────────────────────────────
	$(document).on('click', '.zs-seo-revert-btn', function () {
		const btn  = $(this);
		const id   = btn.data('id');

		if (!confirm('Restore original image? This will undo all optimizations for this image.')) return;

		btn.prop('disabled', true).text('Reverting...');

		$.post(api, { action: 'zs_seo_revert_image', nonce: nonce, attachment_id: id }, function (r) {
			const $card   = btn.closest('.zs-seo-opt-card');
			const $result = $('#zs-seo-opt-result-' + id);

			if (r.success) {
				$card.removeClass('status-optimized').addClass('status-needs_opt');
				$card.attr('data-status', 'needs_opt');
				$card.find('.zs-seo-opt-btn').prop('disabled', false).html('&#x1F5DC; Optimize');
				btn.remove();
				$result.removeClass('error').show().html('<span style="color:#00b894;">&#x2713; Reverted to original (' + r.data.new_size_kb + ' KiB)</span>');
				refreshOptimizerStats();
			} else {
				btn.prop('disabled', false).text('&#x21A9; Revert');
				alert(r.data.message || 'Revert failed.');
			}
		});
	});

	// ── Bulk Optimize ──────────────────────────────────────────────────────────
	$(document).on('click', '#zs-seo-bulk-optimize', function () {
		const ids    = [];
		$('.zs-seo-opt-select:checked').each(function () { ids.push($(this).data('id')); });
		if (!ids.length) return;

		const maxW = $('#zs-seo-opt-max-width').val() || 1920;
		const webp = $('#zs-seo-opt-webp').prop('checked') ? 1 : 0;
		const total = ids.length;

		$('#zs-seo-bulk-optimize').prop('disabled', true).html(spinner() + ' Optimizing ' + total + ' images...');
		$('#zs-seo-opt-progress-wrap').show();
		$('#zs-seo-opt-progress-bar').css('width', '0%');
		$('#zs-seo-opt-progress-label').text('0 / ' + total);
		$('#zs-seo-opt-progress-msg').text('Starting...');

		let done = 0;
		let totalSaved = 0;

		function optimizeNext() {
			if (done >= total) {
				// All done
				$('#zs-seo-bulk-optimize').prop('disabled', false).html('&#x1F5DC; Bulk Optimize Selected');
				$('#zs-seo-opt-progress-msg').html(
					'<strong style="color:#00b894;">&#x2713; Done!</strong> Optimized ' + done + ' images. Total saved: ' + totalSaved.toFixed(1) + ' KiB'
				);
				refreshOptimizerStats();
				return;
			}

			const id = ids[done];
			$('#zs-seo-opt-progress-msg').text('Optimizing: ' + (done + 1) + ' of ' + total + '...');

			$.post(api, {
				action: 'zs_seo_optimize_image',
				nonce: nonce,
				attachment_id: id,
				target_width: maxW,
				to_webp: webp,
			}, function (r) {
				done++;
				const pct = Math.round((done / total) * 100);
				$('#zs-seo-opt-progress-bar').css('width', pct + '%');
				$('#zs-seo-opt-progress-label').text(done + ' / ' + total);

				if (r.success) {
					totalSaved += r.data.saved_kb || 0;
					const $card = $('.zs-seo-opt-card[data-id="' + id + '"]');
					const $result = $('#zs-seo-opt-result-' + id);
					$card.removeClass('status-needs_opt').addClass('status-optimized');
					$result.show().html(
						'<strong>' + r.data.original_kb + ' KiB &#x2192; ' + r.data.new_kb + ' KiB</strong> (-' + r.data.saved_pct + '%)'
					);
					$card.find('.zs-seo-opt-btn').html('&#x2705; Done').prop('disabled', true);
					if (!$card.find('.zs-seo-revert-btn').length) {
						$card.find('.zs-seo-opt-btn').after('<button type="button" class="button zs-seo-revert-btn" data-id="' + id + '">&#x21A9; Revert</button>');
					}
				}

				// Small delay between requests to avoid server overload
				setTimeout(optimizeNext, 300);
			}).fail(function () {
				done++;
				setTimeout(optimizeNext, 300);
			});
		}

		optimizeNext();
	});

	// ── Refresh optimizer stats after operations ───────────────────────────────
	function refreshOptimizerStats() {
		const $cards  = $('.zs-seo-opt-card');
		const total   = $cards.length;
		const needsOpt = $cards.filter('[data-status="needs_opt"]').length;
		const optimized = $cards.filter('[data-status="optimized"]').length;
		$('#zs-seo-opt-total').text(total);
		$('#zs-seo-opt-needs').text(needsOpt);
		$('#zs-seo-opt-done').text(optimized);
	}

	// ── Init ───────────────────────────────────────────────────────────────────
	$(function () {
		initCounters();
	});
})(jQuery);

