(function($) {
	'use strict';

	// Chunking constants — must match PHP SiteStaffr_Content_Chunker.
	var TARGET_CHUNK_CHARS = 200 * 4; // 800 chars
	var MAX_CHUNK_CHARS    = 300 * 4; // 1200 chars
	var OVERLAP_CHARS      = 100 * 4; // 400 chars

	var contentItems = [];
	var isSyncing = false;

	// Component-styled replacement for the native alert().
	function notify(message) {
		if (window.SiteStaffrModal) {
			window.SiteStaffrModal.alertDialog({ message: message });
		}
	}

	function init() {
		logDiagnostics();
		loadContentList();
		bindEvents();
	}

	function logDiagnostics() {
		var version = (sitestaffr_knowledge && sitestaffr_knowledge.version) || 'unknown';
		console.log('[SiteStaffr] Plugin version: ' + version);
		$.post(sitestaffr_knowledge.ajax_url, {
			action: 'sitestaffr_knowledge_schema_check',
			nonce:  sitestaffr_knowledge.nonce
		}, function(response) {
			if (response && response.success) {
				console.log('[SiteStaffr] Knowledge schema diagnostic:', response.data);
				if (!response.data.chunk_title_column) {
					console.warn('[SiteStaffr] chunk_title column MISSING — migration did not run. Deactivate + reactivate the plugin to trigger dbDelta.');
				}
			} else {
				console.warn('[SiteStaffr] Knowledge schema diagnostic failed:', response);
			}
		}).fail(function(xhr) {
			console.warn('[SiteStaffr] Knowledge schema diagnostic request failed:', xhr && xhr.status);
		});
	}

	function bindEvents() {
		$('#sync-knowledge-btn').on('click', startSync);
		$('#unsync-knowledge-btn').on('click', startUnsync);
		$('#resync-changed-btn').on('click', resyncChanged);
		$('#knowledge-filter-text').on('input', applyFilters);
		$('#knowledge-filter-status').on('change', applyFilters);
		$('#knowledge-hero-cta, #sitestaffr-knows-manage').on('click', function() {
			expandFirstGroup();
			var target = document.getElementById('knowledge-content-sections');
			if (target && target.scrollIntoView) {
				target.scrollIntoView({ behavior: 'smooth', block: 'start' });
			}
		});

		// The "What your agent knows" panel drives the existing controls below it.
		$('#sitestaffr-knows-add').on('click', function() {
			$('#sitestaffr-add-standalone-knowledge').trigger('click');
			var form = document.getElementById('sitestaffr-manual-knowledge-form');
			if (form && form.scrollIntoView) {
				form.scrollIntoView({ behavior: 'smooth', block: 'center' });
			}
		});

		// --- Manual knowledge form ---
		$('#sitestaffr-add-standalone-knowledge').on('click', function() {
			var $form = $('#sitestaffr-manual-knowledge-form');
			$form.is(':visible') ? $form.slideUp(150) : $form.slideDown(150);
		});

		$('#sitestaffr-cancel-manual-knowledge').on('click', function() {
			$('#sitestaffr-manual-knowledge-form').slideUp(150);
			$('#sitestaffr-manual-title').val('');
			$('#sitestaffr-manual-text').val('');
		});

		$('#sitestaffr-save-manual-knowledge').on('click', function() {
			var title = $('#sitestaffr-manual-title').val().trim();
			var text  = $('#sitestaffr-manual-text').val().trim();
			if (!text) {
				notify('Knowledge text is required.');
				return;
			}
			var $btn = $(this).prop('disabled', true).text('Saving...');
			$.post(sitestaffr_knowledge.ajax_url, {
				action:  'sitestaffr_add_manual_knowledge',
				nonce:   sitestaffr_knowledge.manual_nonce,
				title:   title,
				text:    text,
				post_id: 0
			}, function(response) {
				if (response.success) {
					$('#sitestaffr-manual-knowledge-form').slideUp(150);
					$('#sitestaffr-manual-title').val('');
					$('#sitestaffr-manual-text').val('');
					loadContentList();
				} else {
					notify(response.data && response.data.message ? response.data.message : 'Failed to save.');
				}
			}).fail(function() {
				notify('Request failed. Please try again.');
			}).always(function() {
				$btn.prop('disabled', false).text('Save');
			});
		});

		$(document).on('click', '.sitestaffr-delete-manual-chunk', function() {
			var chunkId = $(this).data('chunk-id');
			if (!chunkId) return;
			var $chunkEl = $(this).closest('.sitestaffr-manual-chunk-item');
			window.SiteStaffrModal.confirm({
				message: 'Delete this manual knowledge entry?',
				danger: true
			}).then(function(ok) {
				if (!ok) return;
				$.post(sitestaffr_knowledge.ajax_url, {
					action:   'sitestaffr_delete_manual_knowledge',
					nonce:    sitestaffr_knowledge.manual_nonce,
					chunk_id: chunkId
				}, function(response) {
					if (response.success) {
						if ($chunkEl.length) {
							$chunkEl.fadeOut(200, function() { $(this).remove(); });
						} else {
							loadContentList();
						}
					} else {
						notify(response.data && response.data.message ? response.data.message : 'Delete failed.');
					}
				}).fail(function() {
					notify('Request failed. Please try again.');
				});
			});
		});

		$(document).on('change', '.select-all-group', function() {
			var group = $(this).data('group');
			var checked = $(this).prop('checked');
			$('#' + group + '-list').find('input[type="checkbox"]').prop('checked', checked);
			updateSyncButton();
		});

		$(document).on('change', '.content-item input[type="checkbox"]', function() {
			updateSyncButton();
			var group = $(this).closest('.sitestaffr-knowledge-section').find('.select-all-group').data('group');
			var allInGroup = $('#' + group + '-list input[type="checkbox"]');
			var checkedInGroup = allInGroup.filter(':checked');
			$('.select-all-group[data-group="' + group + '"]').prop('checked', allInGroup.length === checkedInGroup.length);
		});

		$(document).on('click', '.view-chunks-link', function(e) {
			e.preventDefault();
			var postId = $(this).data('id');
			var $preview = $('.chunk-preview[data-id="' + postId + '"]');

			if ($preview.is(':visible')) {
				$preview.slideUp(150);
				$(this).text('View sections');
				return;
			}

			$(this).text('Loading...');
			var $link = $(this);

			$.ajax({
				url: sitestaffr_knowledge.rest_url + 'knowledge/chunks?post_id=' + postId,
				method: 'GET',
				beforeSend: function(xhr) {
					xhr.setRequestHeader('X-WP-Nonce', sitestaffr_knowledge.rest_nonce);
				},
				success: function(response) {
					if (response.success && response.chunks.length > 0) {
						$preview.empty();
						response.chunks.forEach(function(chunk, i) {
							var badge = '';
							var deleteBtn = '';
							var hitBadge = '';
							if (chunk.source === 'manual') {
								badge = ' <span class="sitestaffr-chunk-badge sitestaffr-chunk-manual">Manual</span>';
								deleteBtn = ' <button type="button" class="button-link sitestaffr-delete-manual-chunk" data-chunk-id="' + chunk.id + '">Delete</button>';
							}
							if (chunk.hit_count > 0) {
								hitBadge = ' <span class="sitestaffr-chunk-badge sitestaffr-chunk-hits" title="Search hits">' + chunk.hit_count + ' hit' + (chunk.hit_count !== 1 ? 's' : '') + '</span>';
							}
							var $item = $('<div class="sitestaffr-manual-chunk-item">');
							var $header = $('<div class="sitestaffr-chunk-item-header">');
							$header.append('Section ' + i + ' (' + $('<span>').text(chunk.post_title).html() + ')' + badge + hitBadge + deleteBtn);
							if (chunk.chunk_title) {
								var $aiTitle = $('<div class="sitestaffr-chunk-ai-title">');
								$aiTitle.text('AI title: ' + chunk.chunk_title);
								$header.append($aiTitle);
							}
							var $body = $('<div class="sitestaffr-chunk-item-body">').text(chunk.content);
							$item.append($header).append($body);
							$preview.append($item);
						});
						$preview.slideDown(150);
						$link.text('Hide sections');
					} else {
						$preview.text('No sections found.').slideDown(150);
						$link.text('Hide sections');
					}
				},
				error: function() {
					$preview.text('Failed to load sections.').slideDown(150);
					$link.text('Hide sections');
				}
			});
		});
	}

	// --- Client-side content extraction ---

	/**
	 * Extract plain text from raw WordPress post_content.
	 * Runs entirely in the browser — no PHP processing needed.
	 */
	function extractText(rawContent) {
		// Strip Gutenberg block comments.
		var content = rawContent.replace(/<!--\s*\/?wp:\S[^]*?-->/g, '');

		// Strip shortcode tags (keep inner content).
		content = content.replace(/\[\/?[a-zA-Z_][a-zA-Z0-9_-]*[^\]]*\]/g, '');

		// Strip HTML using DOM — safe and handles all edge cases.
		var tmp = document.createElement('div');
		tmp.innerHTML = content;
		var text = tmp.textContent || tmp.innerText || '';

		// Normalize whitespace.
		text = text.replace(/\s+/g, ' ').trim();

		return text;
	}

	/**
	 * Chunk text into overlapping segments.
	 * Mirrors PHP SiteStaffr_Content_Chunker::chunk_text().
	 */
	function chunkText(text, postId) {
		if (text.length <= MAX_CHUNK_CHARS) {
			return [{ chunk_index: 0, text: text }];
		}

		var chunks = [];
		var position = 0;
		var chunkIndex = 0;

		while (position < text.length) {
			var end = Math.min(position + TARGET_CHUNK_CHARS, text.length);

			// Try to break at a sentence boundary.
			if (end < text.length) {
				var searchStart = Math.max(end - 200, position);
				var segment = text.substring(searchStart, end);
				var lastPeriod = segment.lastIndexOf('. ');
				if (lastPeriod !== -1) {
					end = searchStart + lastPeriod + 2;
				}
			}

			var chunkStr = text.substring(position, end).trim();
			if (chunkStr.length > 0) {
				chunks.push({ chunk_index: chunkIndex, text: chunkStr });
				chunkIndex++;
			}

			// Reached end of text — all content covered.
			if (end >= text.length) break;

			position = end - OVERLAP_CHARS;
		}

		return chunks;
	}

	// --- AJAX / REST helpers ---

	function loadContentList() {
		$.post(sitestaffr_knowledge.ajax_url, {
			action: 'sitestaffr_knowledge_get_content_list',
			nonce: sitestaffr_knowledge.nonce
		}, function(response) {
			if (response.success) {
				contentItems = response.data.items;
				renderContentList(response.data.items);
				updateStats(response.data.stats);
				updateFirstSyncHero(response.data.stats);
				updateModeRecommendation(response.data.items);
				renderTopChunks(response.data.top_chunks || []);
				$('#knowledge-filters').show();
			} else {
				showError(response.data.message || 'Failed to load content.');
			}
		}).fail(function() {
			showError('Failed to load content list.');
		});
	}

	// First-sync hero: shown until anything is synced; CTA opens the first group.
	function updateFirstSyncHero(stats) {
		var nothingSynced = !stats || !stats.total_posts;
		$('#knowledge-hero').toggle(nothingSynced);
		if (nothingSynced) {
			// Open the first content group so choosing pages is one step away.
			expandFirstGroup();
		}
	}

	function expandFirstGroup() {
		var $first = $('#knowledge-content-sections .sitestaffr-knowledge-section').first();
		var $list = $first.find('.content-list');
		if ($list.length && !$list.is(':visible')) {
			$list.show();
			$first.find('.toggle-arrow').css('transform', 'rotate(90deg)');
		}
	}

	// Recommend a Knowledge Mode from how much content the site has.
	// Many detailed pages -> Page Expert; a handful -> Search. Radio stays
	// the override — this is a hint, never an auto-switch.
	function updateModeRecommendation(items) {
		var pageExpert = (items || []).length >= 15;
		$('#knowledge-reco-page').prop('hidden', !pageExpert);
		$('#knowledge-reco-search').prop('hidden', pageExpert);
	}

	// "Most-used knowledge" mini-panel: top sections by retrieval hits.
	function renderTopChunks(chunks) {
		var $panel = $('#knowledge-top-chunks');
		var $list = $('#knowledge-top-chunks-list');
		if (!chunks.length) {
			$panel.hide();
			return;
		}
		$list.empty();
		chunks.forEach(function(chunk) {
			var title = chunk.chunk_title || chunk.post_title || '(untitled)';
			var $li = $('<li>');
			$li.append($('<span class="sitestaffr-top-chunk-title">').text(title));
			$li.append($('<span class="sitestaffr-chunk-badge sitestaffr-chunk-hits">').text(chunk.hit_count + ' hit' + (chunk.hit_count !== 1 ? 's' : '')));
			$list.append($li);
		});
		$panel.show();
	}

	// --- Filter-as-you-type + status filter ---

	function applyFilters() {
		var text = ($('#knowledge-filter-text').val() || '').toLowerCase().trim();
		var status = $('#knowledge-filter-status').val() || '';
		var filtering = text !== '' || status !== '';

		$('#knowledge-content-sections .sitestaffr-knowledge-section').each(function() {
			var $section = $(this);
			var visibleCount = 0;
			$section.find('.content-item').each(function() {
				var $item = $(this);
				var title = ($item.find('.title').text() || '').toLowerCase();
				var itemStatus = $item.attr('data-status') || '';
				var show = (text === '' || title.indexOf(text) !== -1) &&
					(status === '' || itemStatus === status);
				$item.toggle(show);
				if (show) visibleCount++;
			});
			// While filtering: open groups with matches, hide empty ones.
			if (filtering) {
				$section.toggle(visibleCount > 0);
				var $list = $section.find('.content-list');
				if (visibleCount > 0 && !$list.is(':visible')) {
					$list.show();
					$section.find('.toggle-arrow').css('transform', 'rotate(90deg)');
				}
			} else {
				$section.show();
			}
		});
	}

	function renderContentList(items) {
		var $sections = $('#knowledge-content-sections');
		$sections.empty();

		// Group items by post_type.
		var groups = {};
		items.forEach(function(item) {
			var type = item.post_type || 'page';
			if (!groups[type]) groups[type] = [];
			groups[type].push(item);
		});

		// Render pages first, posts second, then CPTs alphabetically.
		var order = ['page', 'post'];
		Object.keys(groups).sort().forEach(function(type) {
			if (order.indexOf(type) === -1) order.push(type);
		});

		order.forEach(function(type) {
			if (!groups[type] || groups[type].length === 0) return;

			var count = groups[type].length;
			var label = type.charAt(0).toUpperCase() + type.slice(1).replace(/-/g, ' ') + 's';
			var containerId = type + '-list';

			var section = '<div class="sitestaffr-knowledge-section">' +
				'<h2 class="sitestaffr-knowledge-section-toggle">' +
				'<span class="toggle-arrow">&#9654;</span>' +
				'<label onclick="event.stopPropagation();">' +
				'<input type="checkbox" class="select-all-group" data-group="' + type + '">' +
				' ' + $('<span>').text(label).html() +
				' <span class="sitestaffr-knowledge-section-count">(' + count + ')</span>' +
				'</label></h2>' +
				'<div class="content-list" id="' + containerId + '" style="display: none;"></div>' +
				'</div>';
			$sections.append(section);

			renderGroup(containerId, groups[type]);
		});

		// Bind collapse/expand toggle.
		$sections.find('.sitestaffr-knowledge-section-toggle').on('click', function(e) {
			if ($(e.target).is('input[type="checkbox"]')) return;
			var $list = $(this).next('.content-list');
			var $arrow = $(this).find('.toggle-arrow');
			$list.slideToggle(200);
			$arrow.css('transform', $list.is(':visible') ? 'rotate(90deg)' : 'rotate(0deg)');
		});

		updateSyncButton();
		updateStaleAlert();
		renderManualKnowledgeSection();
	}

	function renderManualKnowledgeSection() {
		var $sections = $('#knowledge-content-sections');

		// Remove existing manual section before re-rendering.
		$('#sitestaffr-manual-knowledge-section').remove();

		$.ajax({
			url: sitestaffr_knowledge.rest_url + 'knowledge/chunks?post_id=0',
			method: 'GET',
			beforeSend: function(xhr) {
				xhr.setRequestHeader('X-WP-Nonce', sitestaffr_knowledge.rest_nonce);
			},
			success: function(response) {
				var chunks = (response.success && response.chunks) ? response.chunks : [];
				var $section = $('<div class="sitestaffr-knowledge-section" id="sitestaffr-manual-knowledge-section">');
				var $header = $('<h2 class="sitestaffr-knowledge-section-toggle">');
				$header.html(
					'<span class="toggle-arrow">&#9654;</span>' +
					'Manual Knowledge <span class="sitestaffr-knowledge-section-count">(' + chunks.length + ')</span>'
				);
				var $list = $('<div class="content-list" style="display: none;">');

				if (chunks.length === 0) {
					$list.html('<p class="empty">No manual knowledge entries yet. Use the Add Knowledge button above.</p>');
				} else {
					chunks.forEach(function(chunk) {
						var $item = $('<div class="sitestaffr-manual-chunk-item content-item" data-chunk-id="' + chunk.id + '">');
						var $row = $('<div class="sitestaffr-manual-chunk-row">');
						var hitBadge = chunk.hit_count > 0
							? ' <span class="sitestaffr-chunk-badge sitestaffr-chunk-hits" title="Search hits">' + chunk.hit_count + ' hit' + (chunk.hit_count !== 1 ? 's' : '') + '</span>'
							: '';
						var $title = $('<span class="title">').html(
							$('<span>').text(chunk.post_title).html() +
							' <span class="sitestaffr-chunk-badge sitestaffr-chunk-manual">Manual</span>' + hitBadge
						);
						var $del = $('<button type="button" class="button-link sitestaffr-delete-manual-chunk">Delete</button>').data('chunk-id', chunk.id);
						$row.append($title).append($del);
						var $body = $('<div class="sitestaffr-manual-chunk-body">').text(chunk.content);
						$item.append($row).append($body);
						$list.append($item);
					});
				}

				$header.on('click', function() {
					var $arrow = $(this).find('.toggle-arrow');
					$list.slideToggle(200);
					$arrow.css('transform', $list.is(':visible') ? 'rotate(90deg)' : 'rotate(0deg)');
				});

				$section.append($header).append($list);
				$sections.append($section);
			}
		});
	}

	var STATUS_LABELS = { synced: 'Synced', stale: 'Changed since sync', unsynced: 'Not synced' };

	function renderGroup(containerId, items) {
		var $container = $('#' + containerId);
		$container.empty();

		if (items.length === 0) {
			$container.html('<p class="empty">No published content found.</p>');
			return;
		}

		items.forEach(function(item) {
			// Server sends a preformatted Eastern Time date string.
			var modified = item.modified || '';
			var viewLink = item.status === 'synced' ? ' <a href="#" class="view-chunks-link" data-id="' + item.id + '">View sections</a>' : '';
			var staleBadge = item.status === 'stale' ? ' <span class="sitestaffr-stale-badge">' + STATUS_LABELS.stale + '</span>' : '';
			var statusLabel = STATUS_LABELS[item.status] || item.status;
			var html = '<div class="content-item" data-id="' + item.id + '" data-status="' + item.status + '">' +
				'<label>' +
				'<input type="checkbox" value="' + item.id + '">' +
				'<span class="sitestaffr-sync-dot ' + item.status + '" title="' + statusLabel + '"></span>' +
				'<span class="title">' + $('<span>').text(item.title || '(no title)').html() + viewLink + staleBadge + '</span>' +
				'</label>' +
				'<span class="modified">' + modified + '</span>' +
				'<div class="chunk-preview" data-id="' + item.id + '" style="display:none;"></div>' +
				'</div>';
			$container.append(html);
		});
	}

	function updateStats(stats) {
		$('#stat-chunks').text(stats.total_chunks || 0);
		$('#stat-posts').text(stats.total_posts || 0);
		// Server sends a preformatted Eastern Time date string.
		$('#stat-last-sync').text(stats.last_synced ? stats.last_synced : 'Never');
	}

	// Surface pages that were edited after their last sync (status 'stale').
	function updateStaleAlert() {
		var staleCount = $('.content-item[data-status="stale"]').length;
		var $alert = $('#knowledge-stale-alert');
		if (staleCount > 0) {
			$('#knowledge-stale-text').text(
				staleCount + ' synced ' + (staleCount === 1 ? 'page has' : 'pages have') +
				' changed since their last sync. Re-sync so the AI answers from the latest content.'
			);
			$alert.show();
		} else {
			$alert.hide();
		}
		$('#resync-changed-btn').prop('disabled', staleCount === 0 || isSyncing);
	}

	// One-click: select only the changed (stale) pages and run the normal sync.
	function resyncChanged() {
		if (isSyncing) return;
		$('.content-item input[type="checkbox"]').prop('checked', false);
		$('.select-all-group').prop('checked', false);
		$('.content-item[data-status="stale"] input[type="checkbox"]').prop('checked', true);
		updateSyncButton();
		if (getCheckedItems().length === 0) return;
		startSync();
	}

	function updateSyncButton() {
		var checked = getCheckedItems();
		var $btn = $('#sync-knowledge-btn');
		var $unsyncBtn = $('#unsync-knowledge-btn');
		$btn.prop('disabled', checked.length === 0 || isSyncing);
		if (checked.length > 0 && !isSyncing) {
			$btn.text('Sync Knowledge (' + checked.length + ')');
		} else if (!isSyncing) {
			$btn.text('Sync Knowledge');
		}

		// Unsync button: only enabled when checked items include synced ones.
		var syncedChecked = 0;
		$('.content-item input[type="checkbox"]:checked').each(function() {
			if ($(this).closest('.content-item').attr('data-status') === 'synced') {
				syncedChecked++;
			}
		});
		$unsyncBtn.prop('disabled', syncedChecked === 0 || isSyncing);
		if (syncedChecked > 0 && !isSyncing) {
			$unsyncBtn.text('Unsync Selected (' + syncedChecked + ')');
		} else {
			$unsyncBtn.text('Unsync Selected');
		}
	}

	function getCheckedItems() {
		var ids = [];
		$('.content-item input[type="checkbox"]:checked').each(function() {
			ids.push(parseInt($(this).val(), 10));
		});
		return ids;
	}

	// --- Unsync ---

	function startUnsync() {
		var syncedIds = [];
		$('.content-item input[type="checkbox"]:checked').each(function() {
			var $item = $(this).closest('.content-item');
			if ($item.attr('data-status') === 'synced') {
				syncedIds.push(parseInt($(this).val(), 10));
			}
		});

		if (syncedIds.length === 0 || isSyncing) return;

		window.SiteStaffrModal.confirm({
			message: 'Remove synced knowledge for ' + syncedIds.length + ' item(s)? This cannot be undone.',
			danger: true
		}).then(function(ok) {
			if (!ok || isSyncing) return;

			$('#sync-status').text('Removing...');

			$.ajax({
				url: sitestaffr_knowledge.rest_url + 'knowledge/unsync',
				method: 'POST',
				contentType: 'application/json',
				data: JSON.stringify({ post_ids: syncedIds }),
				beforeSend: function(xhr) {
					xhr.setRequestHeader('X-WP-Nonce', sitestaffr_knowledge.rest_nonce);
				},
				success: function(response) {
					if (response.success) {
						$('#sync-status').text('Removed ' + (response.removed || syncedIds.length) + ' item(s).');
						loadContentList();
					} else {
						$('#sync-status').html('<span style="color: #991b1b;">' + (response.message || 'Unsync failed.') + '</span>');
					}
				},
				error: function() {
					$('#sync-status').html('<span style="color: #991b1b;">Unsync request failed.</span>');
				}
			});
		});
	}

	// --- Sync orchestration ---

	/**
	 * Two-phase sync:
	 * 1. PHP extracts text (strip_tags) + chunks it (lightweight, no WP hooks)
	 * 2. JS sends each chunk to PHP for embedding + DB save
	 */
	function startSync() {
		var ids = getCheckedItems();
		if (ids.length === 0 || isSyncing) return;

		isSyncing = true;
		var $btn = $('#sync-knowledge-btn');
		$btn.prop('disabled', true).text('Syncing...');
		$('#sync-progress').show();
		$('#sync-status').text('');
		$('#progress-fill').css('width', '0%');

		var totalPosts = ids.length;
		var postsDone = 0;
		var totalChunks = 0;
		var errors = [];

		function syncNextPost() {
			if (postsDone >= totalPosts) {
				finishSync(totalChunks, errors);
				return;
			}

			var postId = ids[postsDone];
			updateProgress('Preparing ' + (postsDone + 1) + ' of ' + totalPosts + '...');

			// Phase 1: PHP extracts text + chunks it (strip_tags, no WP hooks).
			$.ajax({
				url: sitestaffr_knowledge.rest_url + 'knowledge/prepare',
				method: 'POST',
				contentType: 'application/json',
				data: JSON.stringify({ post_id: postId }),
				beforeSend: function(xhr) {
					xhr.setRequestHeader('X-WP-Nonce', sitestaffr_knowledge.rest_nonce);
				},
				success: function(response) {
					if (!response.success) {
						errors.push(postId + ': ' + (response.message || 'No content'));
						postsDone++;
						syncNextPost();
						return;
					}

					var chunkTotal = response.total;
					var chunksDone = 0;
					var chunksSucceeded = 0;
					var BATCH_SIZE = 10;
					var BATCH_DELAY = 500;

					// Phase 2: Embed chunks in batches.
					function embedNextBatch() {
						if (chunksDone >= chunkTotal) {
							totalChunks += chunksSucceeded;
							var pct = Math.round(((postsDone + 1) / totalPosts) * 100);
							$('#progress-fill').css('width', pct + '%');
							var $doneItem = $('.content-item[data-id="' + postId + '"]');
							$doneItem.attr('data-status', 'synced');
							$doneItem.find('.sitestaffr-sync-dot').removeClass('stale unsynced').addClass('synced');
							$doneItem.find('.sitestaffr-stale-badge').remove();
							updateStaleAlert();
							postsDone++;
							syncNextPost();
							return;
						}

						var batchEnd = Math.min(chunksDone + BATCH_SIZE, chunkTotal);
						var indices = [];
						for (var i = chunksDone; i < batchEnd; i++) {
							indices.push(i);
						}
						var isLast = (batchEnd >= chunkTotal);

						updateProgress(
							'Post ' + (postsDone + 1) + '/' + totalPosts +
							' \u2014 sections ' + (chunksDone + 1) + '-' + batchEnd + '/' + chunkTotal
						);

						$.ajax({
							url: sitestaffr_knowledge.rest_url + 'knowledge/embed-batch',
							method: 'POST',
							contentType: 'application/json',
							timeout: 90000,
							data: JSON.stringify({
								post_id: postId,
								chunk_indices: indices,
								is_last: isLast
							}),
							beforeSend: function(xhr) {
								xhr.setRequestHeader('X-WP-Nonce', sitestaffr_knowledge.rest_nonce);
							},
							success: function(embedResponse) {
								if (embedResponse.success) {
									chunksSucceeded += embedResponse.saved || indices.length;
								} else {
									errors.push(postId + ' batch ' + chunksDone + '-' + batchEnd + ': ' + (embedResponse.message || 'Embed failed'));
								}
								chunksDone = batchEnd;
								setTimeout(embedNextBatch, BATCH_DELAY);
							},
							error: function(xhr) {
								var msg = 'Request failed';
								var delay = BATCH_DELAY;
								try { msg = JSON.parse(xhr.responseText).message || msg; } catch(e) {}
								// Back off on rate limit or WAF errors.
								if (xhr.status === 429 || xhr.status === 503) {
									delay = 5000;
									msg = 'Rate limited, retrying...';
								} else {
									errors.push(postId + ' batch ' + chunksDone + '-' + batchEnd + ': ' + msg);
									chunksDone = batchEnd;
								}
								setTimeout(embedNextBatch, delay);
							}
						});
					}

					embedNextBatch();
				},
				error: function(xhr) {
					var msg = 'Prepare request failed';
					try { msg = JSON.parse(xhr.responseText).message || msg; } catch(e) {}
					errors.push(postId + ': ' + msg);
					postsDone++;
					syncNextPost();
				}
			});
		}

		syncNextPost();
	}

	function updateProgress(text) {
		$('#progress-text').text(text);
	}

	function finishSync(totalChunks, errors) {
		isSyncing = false;
		$('#progress-fill').css('width', '100%');

		if (errors.length > 0) {
			$('#sync-status').html('<span style="color: #991b1b;">' + errors.length + ' error(s). ' + totalChunks + ' sections indexed.</span>');
		} else {
			$('#sync-status').text('Done! ' + totalChunks + ' sections indexed.');
		}

		$('#sync-knowledge-btn').text('Sync Knowledge');
		updateSyncButton();

		// Reload stats
		loadContentList();
	}

	function showError(msg) {
		$('#sync-status').html('<span style="color: #991b1b;">' + $('<span>').text(msg).html() + '</span>');
	}

	$(document).ready(init);

})(jQuery);
