(function ($) {
	'use strict';

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

	var strings = AltifyAIAdmin.strings || {};

	function getString(key, fallback) {
		return strings[key] || fallback;
	}

	function postAjax(payload) {
		return $.ajax({
			url: AltifyAIAdmin.ajaxUrl,
			method: 'POST',
			dataType: 'json',
			data: payload
		});
	}

	function toInt(value, fallback, min, max) {
		var parsed = parseInt(value, 10);
		if (isNaN(parsed)) {
			parsed = fallback;
		}
		if (typeof min === 'number' && parsed < min) {
			parsed = min;
		}
		if (typeof max === 'number' && parsed > max) {
			parsed = max;
		}
		return parsed;
	}

	function getFirstElement(selectors) {
		if (!selectors) {
			return $();
		}

		var list = Array.isArray(selectors) ? selectors : [selectors];
		for (var i = 0; i < list.length; i++) {
			var $element = $(list[i]).first();
			if ($element.length) {
				return $element;
			}
		}

		return $();
	}

	function setElementValue(selectors, value) {
		var $element = getFirstElement(selectors);
		if ($element.length) {
			$element.val(value);
		}
		return $element;
	}

	function setElementChecked(selectors, checked) {
		var $element = getFirstElement(selectors);
		if ($element.length) {
			$element.prop('checked', !!checked);
		}
		return $element;
	}

	function setText(selector, value) {
		if (!selector) {
			return;
		}
		$(selector).text(value);
	}

	function formatDateTime(dateObj) {
		if (!(dateObj instanceof Date)) {
			return '-';
		}
		return dateObj.toLocaleString();
	}

	function formatDuration(totalSeconds) {
		totalSeconds = Math.max(0, toInt(totalSeconds, 0, 0, 999999));
		var hours = Math.floor(totalSeconds / 3600);
		var minutes = Math.floor((totalSeconds % 3600) / 60);
		var seconds = totalSeconds % 60;
		if (hours > 0) {
			return hours + 'h ' + minutes + 'm ' + seconds + 's';
		}
		if (minutes > 0) {
			return minutes + 'm ' + seconds + 's';
		}
		return seconds + 's';
	}

	function mapSourceLabel(source) {
		var sourceMap = {
			upload: 'Upload',
			bulk_media: 'Bulk Media',
			bulk_offline: 'Bulk Offline',
			bulk_woo: 'Bulk Woo',
			bulk_woo_offline: 'Woo Offline',
			daily_scan: 'Daily Scan',
			daily_scan_cron: 'Daily Scan (Cron)',
			daily_scan_manual: 'Daily Scan (Manual)',
			manual: 'Manual'
		};
		if (!source) {
			return '';
		}
		return sourceMap[source] || source;
	}

	function mapMethodLabel(method) {
		var methodMap = {
			ai: 'AI',
			offline: 'Offline',
			offline_fallback: 'Offline Fallback',
			cache: 'Cache',
			failed: 'Failed'
		};
		if (!method) {
			return '';
		}
		return methodMap[method] || method;
	}

	function renderLogs(selector, logs) {
		var $tbody = $(selector);
		if (!$tbody.length) {
			return;
		}

		$tbody.empty();

		if (!Array.isArray(logs) || logs.length === 0) {
			$tbody.append(
				$('<tr class="no-items" />').append(
					$('<td colspan="8" />').text(getString('noHistoryRows', 'No history found.'))
				)
			);
			$tbody.trigger('altify:logs-rendered');
			return;
		}

		logs.forEach(function (entry) {
			if (!entry || typeof entry !== 'object') {
				return;
			}

			var logId = entry.id || '';
			var time = entry.time || '';
			var level = (entry.level || 'INFO').toUpperCase();
			var message = entry.message || '';
			var context = entry.context || {};
			var sourceLabel = context.source ? mapSourceLabel(context.source) : '-';
			var methodLabel = context.generation_method ? mapMethodLabel(context.generation_method) : '-';
			var attachmentLabel = context.attachment_id ? ('#' + context.attachment_id) : '-';
			var altPreview = context.alt_text || '-';

			var $checkbox = $('<input type="checkbox" class="altify-ai-log-select-item" />')
				.val(logId)
				.attr('aria-label', getString('selectHistoryRow', 'Select history row'));
			if (!logId) {
				$checkbox.prop('disabled', true);
			}

			var $row = $('<tr />')
				.append($('<th scope="row" class="check-column" />').append($checkbox))
				.append($('<td />').text(time))
				.append($('<td />').text(level))
				.append($('<td />').text(sourceLabel))
				.append($('<td />').text(methodLabel))
				.append($('<td />').text(attachmentLabel))
				.append($('<td />').text(altPreview))
				.append($('<td />').text(message));

			$tbody.append($row);
		});

		$tbody.trigger('altify:logs-rendered');
	}

	function getSettingsLogStatus(entry, context) {
		var level = ((entry && entry.level) ? String(entry.level) : 'INFO').toUpperCase();
		var message = ((entry && entry.message) ? String(entry.message) : '').toLowerCase();
		var method = context && context.generation_method ? String(context.generation_method) : '';

		if (level === 'ERROR' || method === 'failed') {
			return {
				label: 'Failed',
				className: 'badge badge-danger'
			};
		}

		if (message.indexOf('skip') !== -1 || level === 'WARNING') {
			return {
				label: 'Skipped',
				className: 'badge badge-muted'
			};
		}

		return {
			label: 'Success',
			className: 'badge badge-success'
		};
	}

	function renderSettingsLogs(selector, logs, limit) {
		var $tbody = $(selector);
		if (!$tbody.length) {
			return;
		}

		$tbody.empty();
		if (!Array.isArray(logs) || logs.length === 0) {
			$tbody.append(
				$('<tr />').append(
					$('<td class="no-history-cell" colspan="7" />').text(getString('noHistoryRows', 'No history found.'))
				)
			);
			$tbody.trigger('altify:logs-rendered');
			return;
		}

		var orderedLogs = logs.slice().reverse();
		if (typeof limit === 'number' && limit > 0) {
			orderedLogs = orderedLogs.slice(0, limit);
		}

		orderedLogs.forEach(function (entry) {
			if (!entry || typeof entry !== 'object') {
				return;
			}

			var context = (entry.context && typeof entry.context === 'object') ? entry.context : {};
			var logId = entry.id || '';
			var time = entry.time || '';
			var source = context.source ? mapSourceLabel(context.source) : '-';
			var method = context.generation_method ? mapMethodLabel(context.generation_method) : '-';
			var attachment = context.attachment_id ? ('#' + context.attachment_id) : '-';
			var altPreview = context.alt_text || '-';
			var status = getSettingsLogStatus(entry, context);

			var $checkbox = $('<input type="checkbox" class="altify-ai-log-select-item" />')
				.val(logId)
				.attr('aria-label', getString('selectHistoryRow', 'Select history row'));
			if (!logId) {
				$checkbox.prop('disabled', true);
			}

			var $statusBadge = $('<span />')
				.addClass(status.className)
				.text(status.label);

			var $row = $('<tr />')
				.append($('<td class="check-col" />').append($checkbox))
				.append($('<td />').text(time))
				.append($('<td />').text(method))
				.append($('<td />').text(source))
				.append($('<td />').text(attachment))
				.append($('<td />').text(altPreview))
				.append($('<td />').append($statusBadge));

			$tbody.append($row);
		});

		$tbody.trigger('altify:logs-rendered');
	}

	function initHistoryManager(config) {
		if (!config || !config.logsSelector || !config.selectAllSelector || !config.deleteSelectedSelector || !config.clearAllSelector) {
			return;
		}

		var $tbody = $(config.logsSelector);
		var $selectAll = $(config.selectAllSelector);
		var $deleteSelected = $(config.deleteSelectedSelector);
		var $clearAll = $(config.clearAllSelector);
		var renderHistory = (typeof config.render === 'function') ? config.render : renderLogs;

		if (!$tbody.length || !$selectAll.length || !$deleteSelected.length || !$clearAll.length) {
			return;
		}

		function setStatus(message) {
			if (!config.statusSelector) {
				return;
			}
			setText(config.statusSelector, message);
		}

		function selectedLogIds() {
			return $tbody.find('.altify-ai-log-select-item:checked').map(function () {
				return $(this).val();
			}).get();
		}

		function syncSelectAll() {
			var $items = $tbody.find('.altify-ai-log-select-item:not(:disabled)');
			if (!$items.length) {
				$selectAll.prop('checked', false);
				return;
			}
			$selectAll.prop('checked', $items.length === $items.filter(':checked').length);
		}

		$selectAll.off('change.altify').on('change.altify', function () {
			var checked = $(this).is(':checked');
			$tbody.find('.altify-ai-log-select-item:not(:disabled)').prop('checked', checked);
		});

		$tbody.off('change.altify', '.altify-ai-log-select-item').on('change.altify', '.altify-ai-log-select-item', function () {
			syncSelectAll();
		});
		$tbody.off('altify:logs-rendered.altify').on('altify:logs-rendered.altify', function () {
			syncSelectAll();
		});

		$deleteSelected.off('click.altify').on('click.altify', function () {
			var ids = selectedLogIds();
			if (!ids.length) {
				setStatus(getString('noRowsSelected', 'Select at least one history row.'));
				return;
			}

			setStatus(getString('deletingHistory', 'Updating history...'));
			postAjax({
				action: 'altify_ai_manage_logs',
				nonce: AltifyAIAdmin.nonce,
				operation: 'delete_selected',
				log_ids: ids
			})
				.done(function (response) {
					if (!response || !response.success || !response.data) {
						setStatus(getString('requestFailed', 'Request failed.'));
						return;
					}
					renderHistory(config.logsSelector, response.data.logs || []);
					$selectAll.prop('checked', false);
					setStatus(response.data.message || getString('historyUpdated', 'History updated.'));
				})
				.fail(function () {
					setStatus(getString('requestFailed', 'Request failed.'));
				});
		});

		$clearAll.off('click.altify').on('click.altify', function () {
			if (!window.confirm(getString('confirmClearHistory', 'Clear all history rows?'))) {
				return;
			}

			setStatus(getString('deletingHistory', 'Updating history...'));
			postAjax({
				action: 'altify_ai_manage_logs',
				nonce: AltifyAIAdmin.nonce,
				operation: 'clear_all'
			})
				.done(function (response) {
					if (!response || !response.success || !response.data) {
						setStatus(getString('requestFailed', 'Request failed.'));
						return;
					}
					renderHistory(config.logsSelector, response.data.logs || []);
					$selectAll.prop('checked', false);
					setStatus(response.data.message || getString('historyUpdated', 'History updated.'));
				})
				.fail(function () {
					setStatus(getString('requestFailed', 'Request failed.'));
				});
		});

		syncSelectAll();
	}

	function renderAutomationStatus(status) {
		if (!status || typeof status !== 'object') {
			return;
		}

		var countersText = status.counters_display;
		if (!countersText) {
			countersText = 'Processed ' + toInt(status.processed, 0, 0, 999999999) + ', Success ' + toInt(status.success, 0, 0, 999999999) + ', Skipped ' + toInt(status.skipped, 0, 0, 999999999) + ', Failed ' + toInt(status.failed, 0, 0, 999999999);
		}

		var modeScopeText = status.mode_scope_display;
		if (!modeScopeText) {
			modeScopeText = (status.last_mode_label || '-') + ' / ' + (status.last_scope_label || '-');
		}

		setText('#altify-ai-auto-last-run', status.last_run_display || '-');
		setText('#altify-ai-auto-next-run', status.next_run_display || '-');
		setText('#altify-ai-auto-counters', countersText);
		setText('#altify-ai-auto-mode-scope', modeScopeText);
	}

	function initAutomation() {
		var $runNow = $('#altify-ai-run-scan-now');
		if (!$runNow.length) {
			return;
		}

		renderAutomationStatus(AltifyAIAdmin.automationStatus || {});

		var $result = $('#altify-ai-automation-result');
		$runNow.on('click', function () {
			$runNow.prop('disabled', true);
			$result.text(getString('runningScanNow', 'Running scan now...'));

			postAjax({
				action: 'altify_ai_run_scan_now',
				nonce: AltifyAIAdmin.nonce
			})
				.done(function (response) {
					if (!response || !response.data) {
						$result.text(getString('requestFailed', 'Request failed.'));
						return;
					}

					if (response.data.status) {
						renderAutomationStatus(response.data.status);
					}

					if (response.data.message) {
						$result.text(response.data.message);
					} else if (response.success) {
						$result.text(getString('runScanComplete', 'Scan completed.'));
					} else {
						$result.text(getString('requestFailed', 'Request failed.'));
					}
				})
				.fail(function () {
					$result.text(getString('requestFailed', 'Request failed.'));
				})
				.always(function () {
					$runNow.prop('disabled', false);
				});
		});
	}

	function initPrimaryModeCards() {
		var $cards = $('.mode-card, .altify-ai-mode-card');
		var $offlineToggle = getFirstElement(['#enable_offline', '#altify-offline-mode-toggle']);
		var $aiToggle = getFirstElement('#enable_ai');
		if (!$cards.length || !$offlineToggle.length) {
			return;
		}

		var $offlineCard = getFirstElement(['#card-offline', '#altify-card-offline']);
		var $aiCard = getFirstElement(['#card-ai', '#altify-card-ai']);

		function setMode(mode) {
			mode = (mode === 'offline') ? 'offline' : 'ai';
			$cards.removeClass('is-active active');
			if (mode === 'offline') {
				$offlineCard.addClass('is-active active');
			} else {
				$aiCard.addClass('is-active active');
			}
			$('input[name="altify_ai_primary_mode"][value="' + mode + '"]').prop('checked', true);
			$offlineToggle.prop('checked', mode === 'offline');
			if ($aiToggle.length) {
				$aiToggle.prop('checked', mode === 'ai');
			}
		}

		$cards.on('click', function (event) {
			if ($(event.target).is('input')) {
				return;
			}
			setMode($(this).data('mode'));
		});

		$('input[name="altify_ai_primary_mode"]').on('change', function () {
			setMode($(this).val());
		});

		$offlineToggle.on('change', function () {
			setMode($(this).is(':checked') ? 'offline' : 'ai');
		});

		if ($aiToggle.length) {
			$aiToggle.on('change', function () {
				setMode($(this).is(':checked') ? 'ai' : 'offline');
			});
		}

		setMode($offlineToggle.is(':checked') ? 'offline' : 'ai');
	}

	function initAdvancedAccordion() {
		var $accordion = $('#altify-ai-advanced-accordion');
		var $toggle = $('#altify-ai-advanced-toggle');
		var $content = $('#altify-ai-advanced-content');
		if (!$accordion.length || !$toggle.length || !$content.length) {
			return;
		}

		$toggle.on('click', function () {
			var expanded = ($toggle.attr('aria-expanded') === 'true');
			$toggle.attr('aria-expanded', expanded ? 'false' : 'true');
			$content.prop('hidden', expanded);
			$accordion.toggleClass('open', !expanded);
		});
	}

	function initPresets() {
		var $buttons = $('.altify-ai-preset-button');
		if (!$buttons.length) {
			return;
		}

		var presets = {
			budget: {
				model: 'gpt-4o-mini',
				temperature: 0.1,
				max_tokens: 45,
				alt_language: 'auto',
				max_alt_length: 110,
				only_fill_empty_alt: true,
				overwrite_existing_alt: false,
				requests_per_minute: 15,
				use_vision: false
			},
			balanced: {
				model: 'gpt-4o-mini',
				temperature: 0.2,
				max_tokens: 60,
				alt_language: 'auto',
				max_alt_length: 125,
				only_fill_empty_alt: true,
				overwrite_existing_alt: false,
				requests_per_minute: 40,
				use_vision: false
			},
			quality: {
				model: 'gpt-4o',
				temperature: 0.2,
				max_tokens: 90,
				alt_language: 'auto',
				max_alt_length: 140,
				only_fill_empty_alt: true,
				overwrite_existing_alt: false,
				requests_per_minute: 80,
				use_vision: true
			}
		};

		function applyPreset(preset, presetKey) {
			setElementValue(['#ai_model', '#altify-model'], preset.model);
			setElementValue(['#ai_temp', '#altify-temperature'], preset.temperature);
			setElementValue(['#ai_tokens', '#altify-max-tokens'], preset.max_tokens);
			setElementValue(['#offline_max_len', '#altify-max-alt-length'], preset.max_alt_length);
			setElementValue(['#ai_rpm', '#altify-rpm'], preset.requests_per_minute);

			var $language = getFirstElement(['#offline_lang', '#altify-alt-language']);
			if ($language.length) {
				$language.val(preset.alt_language).trigger('change');
			}
			setElementValue(['#offline_lang_custom', '#altify-alt-language-custom'], '');

			setElementChecked(['#off_only_empty', 'input[type="checkbox"][name="altify_ai_settings[only_fill_empty_alt]"]'], !!preset.only_fill_empty_alt);
			setElementChecked(['#off_overwrite', 'input[type="checkbox"][name="altify_ai_settings[overwrite_existing_alt]"]'], !!preset.overwrite_existing_alt);
			setElementChecked(['#enable_offline', '#altify-offline-mode-toggle', 'input[type="checkbox"][name="altify_ai_settings[offline_mode]"]'], false);
			setElementChecked(['#enable_ai'], true);
			setElementChecked(['#ai_vision', 'input[type="checkbox"][name="altify_ai_settings[use_vision_analysis]"]'], !!preset.use_vision);
			$('input[type="radio"][name="altify_ai_primary_mode"][value="ai"]').prop('checked', true).trigger('change');

			var message = getString('presetApplied', 'Preset applied. Review and click Save Settings.');
			if (presetKey === 'quality') {
				message = getString('qualityPresetWarning', 'Quality preset applied. If your API key does not support this model, switch to gpt-4o-mini or use the Balanced preset.');
			}
			setText('#altify-ai-preset-result', message);
		}

		$buttons.on('click', function () {
			var presetKey = $(this).data('preset');
			if (!presetKey || !presets[presetKey]) {
				return;
			}
			$buttons.removeClass('is-active active');
			$(this).addClass('is-active active');
			applyPreset(presets[presetKey], presetKey);
		});
	}

	function initLanguageCustomField() {
		var $language = getFirstElement(['#offline_lang', '#altify-alt-language']);
		var $custom = getFirstElement(['#offline_lang_custom', '#altify-alt-language-custom']);
		if (!$language.length || !$custom.length) {
			return;
		}

		function toggleCustom() {
			var isCustom = ($language.val() === 'custom');
			$custom.prop('disabled', !isCustom);
			$custom.toggle(isCustom);
		}

		$language.on('change', toggleCustom);
		toggleCustom();
	}

	function applyRecommendedDefaults() {
		setElementChecked(['#auto_upload'], true).trigger('change');
		setElementValue(['#upload_mode'], 'offline_first').trigger('change');
		setElementChecked(['#daily_scan'], true).trigger('change');
		setElementValue(['#scan_time'], '02:00').trigger('change');
		setElementValue(['#scan_max'], 50).trigger('change');
		setElementValue(['#scan_scope'], 'missing').trigger('change');
		setElementValue(['#scan_mode'], 'offline_first').trigger('change');

		setElementChecked(['#enable_offline', '#altify-offline-mode-toggle'], true).trigger('change');
		setElementChecked(['#enable_ai'], false).trigger('change');
		setElementValue(['#offline_lang', '#altify-alt-language'], 'auto').trigger('change');
		setElementValue(['#offline_lang_custom', '#altify-alt-language-custom'], '').trigger('change');
		setElementValue(['#offline_max_len', '#altify-max-alt-length'], 125).trigger('change');
		setElementChecked(['#off_only_empty', 'input[type="checkbox"][name="altify_ai_settings[only_fill_empty_alt]"]'], true).trigger('change');
		setElementChecked(['#off_overwrite', 'input[type="checkbox"][name="altify_ai_settings[overwrite_existing_alt]"]'], false).trigger('change');

		setElementValue(['#ai_model', '#altify-model'], 'gpt-4o-mini').trigger('change');
		setElementValue(['#ai_temp', '#altify-temperature'], 0.2).trigger('change');
		setElementValue(['#ai_tokens', '#altify-max-tokens'], 60).trigger('change');
		setElementValue(['#ai_rpm', '#altify-rpm'], 60).trigger('change');
		setElementChecked(['#ai_vision', 'input[type="checkbox"][name="altify_ai_settings[use_vision_analysis]"]'], false).trigger('change');
		$('input[type="radio"][name="altify_ai_primary_mode"][value="offline"]').prop('checked', true).trigger('change');
	}

	function initUnsavedChanges() {
		var $form = $('#altify-ai-settings-form');
		var $hint = $('#unsaved-hint');
		if (!$form.length || !$hint.length || !$('#settings-form').length) {
			return;
		}

		function markUnsaved() {
			$hint.addClass('visible');
		}

		$form.on('change input', '.track-change', function () {
			markUnsaved();
		});

		$('#altify-reset-recommended').on('click', function () {
			applyRecommendedDefaults();
			markUnsaved();
		});
	}

	function initStickyFooterVisibility() {
		var $footer = $('.sticky-footer');
		if (!$footer.length || !$('#settings-form').length) {
			return;
		}

		var lastScrollTop = window.pageYOffset || document.documentElement.scrollTop || 0;
		var ticking = false;
		var scrollDelta = 2;

		function updateVisibility() {
			var currentScrollTop = window.pageYOffset || document.documentElement.scrollTop || 0;
			var scrollingUp = currentScrollTop < (lastScrollTop - scrollDelta);
			var scrollingDown = currentScrollTop > (lastScrollTop + scrollDelta);

			if (scrollingUp) {
				$footer.addClass('is-visible');
			} else if (scrollingDown) {
				$footer.removeClass('is-visible');
			}

			lastScrollTop = currentScrollTop;
			ticking = false;
		}

		function onScroll() {
			if (ticking) {
				return;
			}
			ticking = true;
			window.requestAnimationFrame(updateVisibility);
		}

		window.addEventListener('scroll', onScroll, { passive: true });
		$footer.removeClass('is-visible');
	}

	function initAjaxSettingsSave() {
		var $form = $('#altify-ai-settings-form');
		var $saveBtn = $('#altify-save-settings');
		var $saveStartBtn = $('#altify-save-start');
		var $hint = $('#unsaved-hint');
		var $message = $('#altify-settings-save-message');
		var messageTimer = null;
		var isSaving = false;

		if (!$form.length || !$('#settings-form').length || (!$saveBtn.length && !$saveStartBtn.length)) {
			return;
		}

		function showSaveMessage(text, isError) {
			if (!$message.length) {
				return;
			}

			if (messageTimer) {
				window.clearTimeout(messageTimer);
				messageTimer = null;
			}

			var output = text || '';
			$message.text(output);
			$message.toggleClass('is-visible', output !== '');
			$message.css('color', isError ? '#d63638' : '#2271b1');

			if (output !== '') {
				messageTimer = window.setTimeout(function () {
					$message.removeClass('is-visible');
					$message.text('');
				}, 2600);
			}
		}

		function runSave($triggerButton) {
			if (isSaving) {
				return;
			}

			isSaving = true;
			var originalText = $triggerButton.text();
			var savingText = getString('savingSettings', 'Saving settings...');
			var $buttons = $('#altify-save-settings, #altify-save-start');

			$buttons.prop('disabled', true);
			$triggerButton.text(savingText);
			showSaveMessage(savingText, false);

			postAjax({
				action: 'altify_ai_save_settings',
				nonce: AltifyAIAdmin.nonce,
				form_data: $form.serialize()
			})
				.done(function (response) {
					if (!response || !response.success || !response.data) {
						var fallbackError = getString('settingsSaveFailed', 'Unable to save settings right now.');
						if (response && response.data && response.data.message) {
							fallbackError = response.data.message;
						}
						showSaveMessage(fallbackError, true);
						return;
					}

					var successMessage = response.data.message || getString('settingsSaved', 'Settings saved.');
					showSaveMessage(successMessage, false);
					$hint.removeClass('visible');

					if (response.data.status) {
						renderAutomationStatus(response.data.status);
					}
				})
				.fail(function () {
					showSaveMessage(getString('settingsSaveFailed', 'Unable to save settings right now.'), true);
				})
				.always(function () {
					isSaving = false;
					$buttons.prop('disabled', false);
					$triggerButton.text(originalText);
				});
		}

		$form.on('submit', function (event) {
			event.preventDefault();
			runSave($saveBtn.length ? $saveBtn : $saveStartBtn);
		});

		if ($saveBtn.length) {
			$saveBtn.on('click', function (event) {
				event.preventDefault();
				runSave($saveBtn);
			});
		}

		if ($saveStartBtn.length) {
			$saveStartBtn.on('click', function (event) {
				event.preventDefault();
				runSave($saveStartBtn);
			});
		}
	}

	function initQuickActionButtons() {
		var hasSettingsLayout = $('#settings-form').length > 0;
		var $offlineButton = $('#altify-open-offline-tab');
		var $aiButtons = $('#altify-open-bulk-tab, #altify-open-bulk-tab-history');
		if (!hasSettingsLayout || (!$offlineButton.length && !$aiButtons.length)) {
			return;
		}

		var isRunning = false;
		var $historyStatus = $('#altify-settings-history-status');
		var $saveMessage = $('#altify-settings-save-message');
		var originalOfflineText = $offlineButton.length ? $offlineButton.text() : '';

		$aiButtons.each(function () {
			var $button = $(this);
			if (!$button.data('originalText')) {
				$button.data('originalText', $button.text());
			}
		});

		function setMessage(message, isError) {
			var color = isError ? '#d63638' : '#2271b1';
			if ($historyStatus.length) {
				$historyStatus.text(message || '');
				$historyStatus.css('color', color);
			}

			if ($saveMessage.length) {
				$saveMessage.text(message || '');
				$saveMessage.css('color', color);
				$saveMessage.toggleClass('is-visible', !!message);
			}
		}

		function setButtonsState(disabled, activeButton, activeText) {
			if ($offlineButton.length) {
				$offlineButton.prop('disabled', disabled);
				$offlineButton.text((activeButton === 'offline' && disabled) ? activeText : originalOfflineText);
			}
			if ($aiButtons.length) {
				$aiButtons.each(function () {
					var $button = $(this);
					var originalText = $button.data('originalText') || $button.text();
					$button.prop('disabled', disabled);
					$button.text((activeButton === 'ai' && disabled) ? activeText : originalText);
				});
			}
		}

		function startInlineBulkRun(config) {
			if (isRunning) {
				return;
			}

			isRunning = true;
			var offset = 0;
			var mode = $('#off_overwrite').is(':checked') ? 'all' : 'missing';
			var totals = {
				processed: 0,
				success: 0,
				skipped: 0,
				failed: 0
			};

			setButtonsState(true, config.activeButton, config.runningText);
			setMessage(config.startMessage, false);

			function runNextBatch() {
				postAjax({
					action: 'altify_ai_bulk_process_media',
					nonce: AltifyAIAdmin.nonce,
					mode: mode,
					run_mode: config.runMode,
					generation_mode: config.generationMode,
					offset: offset,
					batch_size: 10
				})
					.done(function (response) {
						if (!response || !response.success || !response.data) {
							var errorMessage = getString('requestFailed', 'Request failed.');
							if (response && response.data && response.data.message) {
								errorMessage = response.data.message;
							}
							setMessage(errorMessage, true);
							isRunning = false;
							setButtonsState(false);
							return;
						}

						var data = response.data || {};
						var batch = data.batch || {};
						totals.processed += toInt(batch.processed, 0, 0, 999999999);
						totals.success += toInt(batch.success, 0, 0, 999999999);
						totals.skipped += toInt(batch.skipped, 0, 0, 999999999);
						totals.failed += toInt(batch.failed, 0, 0, 999999999);
						offset = toInt(data.next_offset, 0, 0, 999999999);

						if (Array.isArray(data.logs)) {
							renderSettingsLogs('#altify-settings-logs', data.logs);
						}

						if (data.done) {
							var doneMessage = config.doneMessage + ' ' +
								'Processed ' + totals.processed +
								' (Success ' + totals.success +
								', Skipped ' + totals.skipped +
								', Failed ' + totals.failed + ').';
							setMessage(doneMessage, false);
							isRunning = false;
							setButtonsState(false);
							return;
						}

						setMessage(
							config.progressMessage + ' ' +
							'Processed ' + totals.processed +
							' (Success ' + totals.success +
							', Skipped ' + totals.skipped +
							', Failed ' + totals.failed + ').',
							false
						);

						window.setTimeout(runNextBatch, 220);
					})
					.fail(function () {
						setMessage(getString('requestFailed', 'Request failed.'), true);
						isRunning = false;
						setButtonsState(false);
					});
			}

			runNextBatch();
		}

		if ($offlineButton.length) {
			$offlineButton.on('click', function (event) {
				event.preventDefault();
				startInlineBulkRun({
					activeButton: 'offline',
					runMode: 'offline',
					generationMode: 'offline_only',
					runningText: 'Running...',
					startMessage: 'Running Offline bulk generator...',
					progressMessage: 'Offline bulk generator running...',
					doneMessage: 'Offline bulk generator completed.'
				});
			});
		}

		if ($aiButtons.length) {
			$aiButtons.on('click', function (event) {
				event.preventDefault();
				startInlineBulkRun({
					activeButton: 'ai',
					runMode: 'auto',
					generationMode: 'ai_first',
					runningText: 'Running...',
					startMessage: 'Running AI bulk generator...',
					progressMessage: 'AI bulk generator running...',
					doneMessage: 'AI bulk generator completed.'
				});
			});
		}
	}

	function initDailyScanToggleButton() {
		var $button = $('#altify-ai-toggle-daily-scan');
		var $checkbox = $('#daily_scan');
		if (!$button.length || !$checkbox.length) {
			return;
		}

		function refreshButtonText() {
			if ($checkbox.is(':checked')) {
				$button.text(getString('pauseDailyScan', 'Pause Daily Scan'));
			} else {
				$button.text(getString('resumeDailyScan', 'Resume Daily Scan'));
			}
		}

		$button.on('click', function () {
			$checkbox.prop('checked', !$checkbox.is(':checked')).trigger('change');
			refreshButtonText();
		});

		$checkbox.on('change', refreshButtonText);
		refreshButtonText();
	}

	function initSettingsHistory() {
		if (!$('#altify-settings-logs').length) {
			return;
		}

		renderSettingsLogs('#altify-settings-logs', AltifyAIAdmin.initialLogs || [], 10);
		initHistoryManager({
			logsSelector: '#altify-settings-logs',
			selectAllSelector: '#altify-settings-log-select-all',
			deleteSelectedSelector: '#altify-settings-log-delete-selected',
			clearAllSelector: '#altify-settings-log-clear-all',
			statusSelector: '#altify-settings-history-status',
			render: function (selector, logs) {
				renderSettingsLogs(selector, logs, 10);
			}
		});
	}

	function initGenerateHistoryPage() {
		if (!$('#altify-history-logs').length) {
			return;
		}

		renderSettingsLogs('#altify-history-logs', AltifyAIAdmin.initialLogs || []);
		initHistoryManager({
			logsSelector: '#altify-history-logs',
			selectAllSelector: '#altify-history-log-select-all',
			deleteSelectedSelector: '#altify-history-log-delete-selected',
			clearAllSelector: '#altify-history-log-clear-all',
			statusSelector: '#altify-history-status',
			render: function (selector, logs) {
				renderSettingsLogs(selector, logs);
			}
		});
	}

	function createRunner(config) {
		var state = {
			running: false,
			paused: false,
			offset: 0,
			processed: 0,
			success: 0,
			skipped: 0,
			failed: 0,
			fallback: 0,
			cached: 0,
			ai: 0,
			offline: 0,
			offlineFallback: 0,
			startedAt: null,
			lastError: '-'
		};

		function setStatus(message) {
			setText(config.statusSelector, message);
		}

		function updateSummary() {
			if (!config.summaryStartedSelector) {
				return;
			}

			var elapsed = '-';
			var speed = '-';
			if (state.startedAt instanceof Date) {
				var seconds = Math.max(1, Math.floor((Date.now() - state.startedAt.getTime()) / 1000));
				elapsed = formatDuration(seconds);
				speed = (state.processed > 0) ? (state.processed / seconds).toFixed(2) + ' items/s' : '0.00 items/s';
			}

			setText(config.summaryStartedSelector, state.startedAt ? formatDateTime(state.startedAt) : '-');
			setText(config.summaryElapsedSelector, elapsed);
			setText(config.summarySpeedSelector, speed);
			setText(config.summaryErrorSelector, state.lastError || '-');
		}

		function resetCounters() {
			state.offset = (typeof config.getStartOffset === 'function') ? config.getStartOffset() : 0;
			state.processed = 0;
			state.success = 0;
			state.skipped = 0;
			state.failed = 0;
			state.fallback = 0;
			state.cached = 0;
			state.ai = 0;
			state.offline = 0;
			state.offlineFallback = 0;
			state.startedAt = new Date();
			state.lastError = '-';
			updateCounters();
			updateSummary();
		}

		function updateCounters() {
			setText(config.processedSelector, state.processed);
			setText(config.successSelector, state.success);
			setText(config.skippedSelector, state.skipped);
			setText(config.failedSelector, state.failed);
			setText(config.fallbackSelector, state.fallback);
			setText(config.cachedSelector, state.cached);
			if (config.aiSelector) {
				setText(config.aiSelector, state.ai);
			}
			if (config.offlineSelector) {
				setText(config.offlineSelector, state.offline);
			}
			if (config.offlineFallbackSelector) {
				setText(config.offlineFallbackSelector, state.offlineFallback);
			}
			updateSummary();
		}

		function makePayload() {
			var payload = {
				action: config.action,
				nonce: AltifyAIAdmin.nonce,
				offset: state.offset,
				batch_size: config.getBatchSize()
			};

			if (config.runMode) {
				payload.run_mode = config.runMode;
			}

			var filters = config.getFilters();
			Object.keys(filters).forEach(function (key) {
				payload[key] = filters[key];
			});

			return payload;
		}

		function handleBatchResponse(response) {
			if (!response || !response.success) {
				var errorMessage = getString('requestFailed', 'Request failed.');
				if (response && response.data && response.data.message) {
					errorMessage = response.data.message;
				}
				state.lastError = errorMessage;
				state.running = false;
				state.paused = false;
				setStatus(errorMessage);
				updateSummary();
				return;
			}

			var data = response.data || {};
			var batch = data.batch || {};

			state.offset = toInt(data.next_offset, state.offset, 0, 999999999);
			state.processed += toInt(batch.processed, 0, 0, 999999999);
			state.success += toInt(batch.success, 0, 0, 999999999);
			state.skipped += toInt(batch.skipped, 0, 0, 999999999);
			state.failed += toInt(batch.failed, 0, 0, 999999999);
			state.fallback += toInt(batch.fallback, 0, 0, 999999999);
			state.cached += toInt(batch.cached, 0, 0, 999999999);
			var methodCounts = batch.method_counts || {};
			state.ai += toInt(methodCounts.ai, 0, 0, 999999999);
			state.offline += toInt(methodCounts.offline, 0, 0, 999999999);
			state.offlineFallback += toInt(methodCounts.offline_fallback, 0, 0, 999999999);

			if (data.diagnostics && data.diagnostics.last_error) {
				state.lastError = data.diagnostics.last_error;
			}

			updateCounters();
			renderLogs(config.logsSelector, data.logs || []);

			if (data.done) {
				state.running = false;
				state.paused = false;
				setStatus(getString('completed', 'Completed.'));
				updateSummary();
				return;
			}

			if (!state.running || state.paused) {
				return;
			}

			window.setTimeout(processNextBatch, 250);
		}

		function processNextBatch() {
			if (!state.running || state.paused) {
				return;
			}

			setStatus(getString('processing', 'Processing...'));

			postAjax(makePayload())
				.done(handleBatchResponse)
				.fail(function () {
					state.running = false;
					state.paused = false;
					state.lastError = getString('requestFailed', 'Request failed.');
					setStatus(state.lastError);
					updateSummary();
				});
		}

		function start() {
			if (state.running) {
				return;
			}
			state.running = true;
			state.paused = false;
			resetCounters();
			setStatus(getString('runStarted', 'Run started.'));
			processNextBatch();
		}

		function pause() {
			if (!state.running) {
				return;
			}
			state.paused = true;
			setStatus(getString('paused', 'Paused.'));
			updateSummary();
		}

		function resume() {
			if (!state.running || !state.paused) {
				return;
			}
			state.paused = false;
			setStatus(getString('resuming', 'Resuming...'));
			processNextBatch();
		}

		function stop() {
			state.running = false;
			state.paused = false;
			state.offset = 0;
			setStatus(getString('runStopped', 'Run stopped.'));
			updateSummary();
		}

		$(config.startSelector).on('click', start);
		$(config.pauseSelector).on('click', pause);
		$(config.resumeSelector).on('click', resume);
		$(config.stopSelector).on('click', stop);

		renderLogs(config.logsSelector, AltifyAIAdmin.initialLogs || []);
		initHistoryManager({
			logsSelector: config.logsSelector,
			selectAllSelector: config.logSelectAllSelector,
			deleteSelectedSelector: config.logDeleteSelectedSelector,
			clearAllSelector: config.logClearAllSelector,
			statusSelector: config.statusSelector
		});
	}

	function initTestApi() {
		var $btn = $('#altify-ai-test-api');
		if (!$btn.length) {
			return;
		}

		$btn.on('click', function () {
			var $result = getFirstElement(['#altify-ai-test-api-result', '#api-status']);
			$btn.prop('disabled', true);
			$result.text(getString('testing', 'Testing API...'));

			postAjax({
				action: 'altify_ai_test_api',
				nonce: AltifyAIAdmin.nonce
			})
				.done(function (response) {
					if (response && response.success) {
						$result.text(response.data.message || 'OK');
						return;
					}
					if (response && response.data && response.data.message) {
						$result.text(response.data.message);
					} else {
						$result.text(getString('requestFailed', 'Request failed.'));
					}
				})
				.fail(function () {
					$result.text(getString('requestFailed', 'Request failed.'));
				})
				.always(function () {
					$btn.prop('disabled', false);
				});
		});
	}

	$(function () {
		initTestApi();
		initPresets();
		initLanguageCustomField();
		initAutomation();
		initDailyScanToggleButton();
		initPrimaryModeCards();
		initAdvancedAccordion();
		initUnsavedChanges();
		initStickyFooterVisibility();
		initAjaxSettingsSave();
		initQuickActionButtons();
		initSettingsHistory();
		initGenerateHistoryPage();

		if ($('#altify-media-start').length) {
			createRunner({
				action: 'altify_ai_bulk_process_media',
				startSelector: '#altify-media-start',
				pauseSelector: '#altify-media-pause',
				resumeSelector: '#altify-media-resume',
				stopSelector: '#altify-media-stop',
				statusSelector: '#altify-media-status',
				processedSelector: '#altify-media-processed',
				successSelector: '#altify-media-success',
				skippedSelector: '#altify-media-skipped',
				failedSelector: '#altify-media-failed',
				aiSelector: '#altify-media-ai',
				offlineSelector: '#altify-media-offline',
				offlineFallbackSelector: '#altify-media-offline-fallback',
				fallbackSelector: '#altify-media-fallback',
				cachedSelector: '#altify-media-cached',
				summaryStartedSelector: '#altify-media-summary-started',
				summaryElapsedSelector: '#altify-media-summary-elapsed',
				summarySpeedSelector: '#altify-media-summary-speed',
				summaryErrorSelector: '#altify-media-summary-error',
				logsSelector: '#altify-media-logs',
				logSelectAllSelector: '#altify-media-log-select-all',
				logDeleteSelectedSelector: '#altify-media-log-delete-selected',
				logClearAllSelector: '#altify-media-log-clear-all',
				getStartOffset: function () {
					return toInt($('#altify-media-start-offset').val(), 0, 0, 999999999);
				},
				getBatchSize: function () {
					return toInt($('#altify-media-batch-size').val(), 10, 1, 100);
				},
				getFilters: function () {
					return {
						mode: $('#altify-media-mode').val() || 'missing',
						date_from: $('#altify-media-date-from').val() || '',
						date_to: $('#altify-media-date-to').val() || ''
					};
				}
			});
		}

		if ($('#altify-woo-start').length) {
			createRunner({
				action: 'altify_ai_bulk_process_woo',
				startSelector: '#altify-woo-start',
				pauseSelector: '#altify-woo-pause',
				resumeSelector: '#altify-woo-resume',
				stopSelector: '#altify-woo-stop',
				statusSelector: '#altify-woo-status',
				processedSelector: '#altify-woo-processed',
				successSelector: '#altify-woo-success',
				skippedSelector: '#altify-woo-skipped',
				failedSelector: '#altify-woo-failed',
				aiSelector: '#altify-woo-ai',
				offlineSelector: '#altify-woo-offline',
				offlineFallbackSelector: '#altify-woo-offline-fallback',
				fallbackSelector: '#altify-woo-fallback',
				cachedSelector: '#altify-woo-cached',
				summaryStartedSelector: '#altify-woo-summary-started',
				summaryElapsedSelector: '#altify-woo-summary-elapsed',
				summarySpeedSelector: '#altify-woo-summary-speed',
				summaryErrorSelector: '#altify-woo-summary-error',
				logsSelector: '#altify-woo-logs',
				logSelectAllSelector: '#altify-woo-log-select-all',
				logDeleteSelectedSelector: '#altify-woo-log-delete-selected',
				logClearAllSelector: '#altify-woo-log-clear-all',
				getStartOffset: function () {
					return toInt($('#altify-woo-start-offset').val(), 0, 0, 999999999);
				},
				getBatchSize: function () {
					return toInt($('#altify-woo-batch-size').val(), 10, 1, 50);
				},
				getFilters: function () {
					return {
						mode: $('#altify-woo-mode').val() || 'missing',
						product_category: $('#altify-woo-category').val() || '',
						date_from: $('#altify-woo-date-from').val() || '',
						date_to: $('#altify-woo-date-to').val() || ''
					};
				}
			});
		}

		if ($('#altify-offline-start').length) {
			createRunner({
				action: 'altify_ai_bulk_process_media',
				runMode: 'offline',
				startSelector: '#altify-offline-start',
				pauseSelector: '#altify-offline-pause',
				resumeSelector: '#altify-offline-resume',
				stopSelector: '#altify-offline-stop',
				statusSelector: '#altify-offline-status',
				processedSelector: '#altify-offline-processed',
				successSelector: '#altify-offline-success',
				skippedSelector: '#altify-offline-skipped',
				failedSelector: '#altify-offline-failed',
				aiSelector: '#altify-offline-ai',
				offlineSelector: '#altify-offline-offline',
				offlineFallbackSelector: '#altify-offline-offline-fallback',
				fallbackSelector: '#altify-offline-fallback',
				cachedSelector: '#altify-offline-cached',
				summaryStartedSelector: '#altify-offline-summary-started',
				summaryElapsedSelector: '#altify-offline-summary-elapsed',
				summarySpeedSelector: '#altify-offline-summary-speed',
				summaryErrorSelector: '#altify-offline-summary-error',
				logsSelector: '#altify-offline-logs',
				logSelectAllSelector: '#altify-offline-log-select-all',
				logDeleteSelectedSelector: '#altify-offline-log-delete-selected',
				logClearAllSelector: '#altify-offline-log-clear-all',
				getStartOffset: function () {
					return toInt($('#altify-offline-start-offset').val(), 0, 0, 999999999);
				},
				getBatchSize: function () {
					return toInt($('#altify-offline-batch-size').val(), 10, 1, 100);
				},
				getFilters: function () {
					return {
						mode: $('#altify-offline-mode').val() || 'missing',
						date_from: $('#altify-offline-date-from').val() || '',
						date_to: $('#altify-offline-date-to').val() || ''
					};
				}
			});
		}
	});
})(jQuery);
