<?php
/**
 * Livada SEO — Bulk Editor
 *
 * Provides an admin screen for editing SEO post meta (title, description,
 * focus keyword, noindex) across many posts at once. Each row is saved
 * individually via AJAX so a half-finished session does not lose work.
 *
 * @package Livada_SEO
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Livada_SEO_Bulk_Editor {

	const PER_PAGE = 50;

	// ── Bootstrap ─────────────────────────────────────────────────────────────

	public static function init(): void {
		// Sub-menu page.
		add_action( 'admin_menu', [ self::class, 'register_menu' ], 20 );

		// AJAX save handler.
		add_action( 'wp_ajax_livada_seo_bulk_save',         [ self::class, 'ajax_save_row'     ] );
		add_action( 'wp_ajax_livada_seo_bulk_ai_fill',      [ self::class, 'ajax_ai_fill'      ] );
		add_action( 'wp_ajax_livada_seo_bulk_set_schema',   [ self::class, 'ajax_set_schema'   ] );
	}

	public static function register_menu(): void {
		add_submenu_page(
			'livada-seo',
			__( 'Bulk Editor — Livada SEO', 'livada-seo' ),
			__( 'Bulk Editor', 'livada-seo' ),
			'manage_options',
			'livada-seo-bulk',
			[ self::class, 'render_page' ]
		);
	}

	// ── Page render ───────────────────────────────────────────────────────────

	public static function render_page(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Insufficient permissions.', 'livada-seo' ) );
		}

		$post_type = isset( $_GET['post_type'] ) ? sanitize_key( $_GET['post_type'] ) : 'post'; // phpcs:ignore
		$paged     = isset( $_GET['paged'] )     ? max( 1, (int) $_GET['paged'] )    : 1;       // phpcs:ignore
		$search    = isset( $_GET['s'] )         ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : ''; // phpcs:ignore

		// Allowed post types: every public post type except attachment.
		$post_types = get_post_types( [ 'public' => true ], 'objects' );
		unset( $post_types['attachment'] );

		if ( ! isset( $post_types[ $post_type ] ) ) {
			$post_type = 'post';
		}

		$query = new WP_Query( [
			'post_type'      => $post_type,
			'post_status'    => [ 'publish', 'draft', 'pending', 'private', 'future' ],
			'posts_per_page' => self::PER_PAGE,
			'paged'          => $paged,
			's'              => $search,
			'orderby'        => 'modified',
			'order'          => 'DESC',
		] );

		$total_pages = (int) $query->max_num_pages;
		?>
		<?php
		$has_ai_key = class_exists( 'Livada_SEO_Image_Bulk' )
			? '' !== Livada_SEO_Image_Bulk::get_anthropic_key()
			: false;
		?>
		<div class="wrap livada-seo-wrap">
			<h1><?php esc_html_e( 'Bulk Editor', 'livada-seo' ); ?></h1>
			<p class="description">
				<?php esc_html_e( 'Edit SEO meta for many posts at once. Changes save automatically when you click outside a field.', 'livada-seo' ); ?>
				<?php if ( $has_ai_key ) : ?>
					<?php esc_html_e( 'Use the AI Fill toolbar below to generate suggestions for empty fields across the visible posts in one shot.', 'livada-seo' ); ?>
				<?php endif; ?>
			</p>

			<?php if ( $has_ai_key ) : ?>
			<div class="livada-bulk-ai-toolbar" style="background:#f0f6fc; border:1px solid #c3c4c7; padding:10px 14px; margin: 12px 0; border-radius:4px; display:flex; flex-wrap:wrap; gap:10px; align-items:center;">
				<strong>✨ <?php esc_html_e( 'AI Fill missing fields', 'livada-seo' ); ?></strong>
				<select id="livada-bulk-ai-field">
					<option value="description"><?php esc_html_e( 'Meta descriptions', 'livada-seo' ); ?></option>
					<option value="title"><?php esc_html_e( 'SEO titles', 'livada-seo' ); ?></option>
					<option value="focus_keyword"><?php esc_html_e( 'Focus keywords', 'livada-seo' ); ?></option>
				</select>
				<label style="display:inline-flex; align-items:center; gap:4px; font-size:12px;">
					<input type="checkbox" id="livada-bulk-ai-force">
					<?php esc_html_e( 'overwrite existing values', 'livada-seo' ); ?>
				</label>
				<button type="button" id="livada-bulk-ai-run" class="button button-primary">
					<?php esc_html_e( 'Run on this page', 'livada-seo' ); ?>
				</button>
				<span id="livada-bulk-ai-status" class="description" style="margin-left:auto;"></span>
			</div>
			<?php endif; ?>

			<form method="get" style="margin: 16px 0;">
				<input type="hidden" name="page" value="livada-seo-bulk" />

				<label for="livada-bulk-post-type"><strong><?php esc_html_e( 'Post type:', 'livada-seo' ); ?></strong></label>
				<select id="livada-bulk-post-type" name="post_type" onchange="this.form.submit()">
					<?php foreach ( $post_types as $pt ) : ?>
						<option value="<?php echo esc_attr( $pt->name ); ?>" <?php selected( $post_type, $pt->name ); ?>>
							<?php echo esc_html( $pt->labels->name ); ?>
						</option>
					<?php endforeach; ?>
				</select>

				<label for="livada-bulk-search" style="margin-left: 16px;"><strong><?php esc_html_e( 'Search:', 'livada-seo' ); ?></strong></label>
				<input type="search" id="livada-bulk-search" name="s" value="<?php echo esc_attr( $search ); ?>" />
				<button type="submit" class="button"><?php esc_html_e( 'Filter', 'livada-seo' ); ?></button>
			</form>

			<div class="livada-bulk-schema-toolbar" style="display:flex; gap:8px; align-items:center; margin: 8px 0 12px;">
				<label style="display:inline-flex; align-items:center; gap:4px; font-size:12px;">
					<input type="checkbox" id="livada-bulk-schema-cb-all">
					<?php esc_html_e( 'Select all', 'livada-seo' ); ?>
				</label>
				<select id="livada-bulk-schema-type">
					<option value="—"><?php esc_html_e( 'Apply schema type…', 'livada-seo' ); ?></option>
					<option value=""><?php esc_html_e( '(clear)', 'livada-seo' ); ?></option>
					<option value="HowTo">HowTo</option>
					<option value="Product">Product</option>
					<option value="Event">Event</option>
					<option value="Recipe">Recipe</option>
					<option value="Review">Review</option>
					<option value="Offer">Offer</option>
				</select>
				<button type="button" id="livada-bulk-schema-apply" class="button" disabled>
					<?php esc_html_e( 'Apply to selection', 'livada-seo' ); ?>
				</button>
				<span id="livada-bulk-schema-status" class="description"></span>
			</div>

			<table class="wp-list-table widefat fixed striped livada-bulk-table">
				<thead>
					<tr>
						<th style="width: 32px;"><input type="checkbox" id="livada-bulk-cb-head"></th>
						<th style="width: 20%;"><?php esc_html_e( 'Post', 'livada-seo' ); ?></th>
						<th style="width: 20%;"><?php esc_html_e( 'SEO Title', 'livada-seo' ); ?></th>
						<th style="width: 28%;"><?php esc_html_e( 'Meta Description', 'livada-seo' ); ?></th>
						<th style="width: 14%;"><?php esc_html_e( 'Focus Keyword', 'livada-seo' ); ?></th>
						<th style="width: 6%;"><?php esc_html_e( 'Noindex', 'livada-seo' ); ?></th>
						<th style="width: 6%;"><?php esc_html_e( 'Score', 'livada-seo' ); ?></th>
					</tr>
				</thead>
				<tbody>
					<?php if ( $query->have_posts() ) : ?>
						<?php while ( $query->have_posts() ) : $query->the_post(); $pid = get_the_ID(); ?>
							<?php
							$title    = (string) get_post_meta( $pid, '_livada_seo_title',         true );
							$desc     = (string) get_post_meta( $pid, '_livada_seo_description',   true );
							$keyword  = (string) get_post_meta( $pid, '_livada_seo_focus_keyword', true );
							$noindex  = (bool)   get_post_meta( $pid, '_livada_seo_noindex',       true );
							$score    = get_post_meta( $pid, '_livada_seo_score', true );
							$score    = $score === '' ? '—' : (int) $score;
							?>
							<tr data-post-id="<?php echo (int) $pid; ?>">
								<td>
									<input type="checkbox" class="livada-bulk-cb" value="<?php echo (int) $pid; ?>">
								</td>
								<td>
									<strong><?php echo esc_html( get_the_title() ); ?></strong><br>
									<small>
										<a href="<?php echo esc_url( get_edit_post_link( $pid ) ); ?>"><?php esc_html_e( 'Edit', 'livada-seo' ); ?></a>
										&nbsp;·&nbsp;
										<a href="<?php echo esc_url( get_permalink( $pid ) ); ?>" target="_blank" rel="noopener"><?php esc_html_e( 'View', 'livada-seo' ); ?></a>
									</small>
								</td>
								<td>
									<input type="text"
										class="livada-bulk-input"
										data-field="title"
										value="<?php echo esc_attr( $title ); ?>"
										placeholder="<?php echo esc_attr( get_the_title() ); ?>"
										style="width: 100%;" />
								</td>
								<td>
									<textarea
										class="livada-bulk-input"
										data-field="description"
										rows="2"
										style="width: 100%;"><?php echo esc_textarea( $desc ); ?></textarea>
								</td>
								<td>
									<input type="text"
										class="livada-bulk-input"
										data-field="focus_keyword"
										value="<?php echo esc_attr( $keyword ); ?>"
										style="width: 100%;" />
								</td>
								<td style="text-align: center;">
									<input type="checkbox"
										class="livada-bulk-input"
										data-field="noindex"
										<?php checked( $noindex, true ); ?> />
								</td>
								<td style="text-align: center;">
									<span class="livada-bulk-score"><?php echo esc_html( (string) $score ); ?></span>
								</td>
							</tr>
						<?php endwhile; ?>
					<?php else : ?>
						<tr><td colspan="7"><?php esc_html_e( 'No posts found.', 'livada-seo' ); ?></td></tr>
					<?php endif; ?>
				</tbody>
			</table>

			<?php if ( $total_pages > 1 ) : ?>
				<div class="tablenav" style="margin-top: 16px;">
					<div class="tablenav-pages">
						<?php
						$base_url = add_query_arg( [ 'page' => 'livada-seo-bulk', 'post_type' => $post_type, 's' => $search ], admin_url( 'admin.php' ) );
						echo wp_kses_post( paginate_links( [
							'base'    => add_query_arg( 'paged', '%#%', $base_url ),
							'format'  => '',
							'current' => $paged,
							'total'   => $total_pages,
						] ) );
						?>
					</div>
				</div>
			<?php endif; ?>

			<?php wp_reset_postdata(); ?>
		</div>

		<script>
		(function () {
			'use strict';

			var ajaxUrl = (window.livadaSEO && window.livadaSEO.ajaxUrl) || '<?php echo esc_js( admin_url( 'admin-ajax.php' ) ); ?>';
			var nonce   = (window.livadaSEO && window.livadaSEO.nonce)   || '<?php echo esc_js( wp_create_nonce( 'livada_seo_admin_nonce' ) ); ?>';

			function saveField(input) {
				var row     = input.closest('tr');
				if (!row) return;
				var postId  = row.getAttribute('data-post-id');
				var field   = input.getAttribute('data-field');
				if (!postId || !field) return;

				var value = input.type === 'checkbox' ? (input.checked ? '1' : '0') : input.value;

				var body = new URLSearchParams({
					action:  'livada_seo_bulk_save',
					nonce:   nonce,
					post_id: postId,
					field:   field,
					value:   value
				});

				input.style.borderColor = '#dba617';

				fetch(ajaxUrl, {
					method:      'POST',
					credentials: 'same-origin',
					headers:     { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
					body:        body.toString()
				}).then(function (r) { return r.json(); })
				  .then(function (res) {
					input.style.borderColor = res && res.success ? '#00a32a' : '#d63638';
					if (res && res.success && res.data && typeof res.data.score !== 'undefined') {
						var scoreEl = row.querySelector('.livada-bulk-score');
						if (scoreEl) { scoreEl.textContent = res.data.score; }
					}
					setTimeout(function () { input.style.borderColor = ''; }, 1200);
				  })
				  .catch(function () {
					input.style.borderColor = '#d63638';
				  });
			}

			document.querySelectorAll('.livada-bulk-input').forEach(function (input) {
				if (input.type === 'checkbox') {
					input.addEventListener('change', function () { saveField(input); });
				} else {
					input.addEventListener('blur', function () { saveField(input); });
				}
			});

			// ── Bulk schema-type assigner ──────────────────────────────────
			var schemaCbAll  = document.getElementById('livada-bulk-cb-head');
			var schemaCbAll2 = document.getElementById('livada-bulk-schema-cb-all');
			var schemaSel    = document.getElementById('livada-bulk-schema-type');
			var schemaBtn    = document.getElementById('livada-bulk-schema-apply');
			var schemaSt     = document.getElementById('livada-bulk-schema-status');

			function selectedIds() {
				return Array.prototype.slice
					.call(document.querySelectorAll('.livada-bulk-cb:checked'))
					.map(function (cb) { return parseInt(cb.value, 10); });
			}

			function refreshSchemaBtn() {
				var n = selectedIds().length;
				var v = schemaSel.value;
				schemaBtn.disabled = (n === 0 || v === '—');
				schemaBtn.textContent = n > 0
					? '<?php echo esc_js( __( 'Apply to selection', 'livada-seo' ) ); ?>' + ' (' + n + ')'
					: '<?php echo esc_js( __( 'Apply to selection', 'livada-seo' ) ); ?>';
			}

			[schemaCbAll, schemaCbAll2].forEach(function (cb) {
				if (!cb) return;
				cb.addEventListener('change', function () {
					document.querySelectorAll('.livada-bulk-cb').forEach(function (c) { c.checked = cb.checked; });
					if (schemaCbAll)  schemaCbAll.checked  = cb.checked;
					if (schemaCbAll2) schemaCbAll2.checked = cb.checked;
					refreshSchemaBtn();
				});
			});

			document.addEventListener('change', function (e) {
				if (e.target && e.target.classList && e.target.classList.contains('livada-bulk-cb')) {
					refreshSchemaBtn();
				}
			});
			schemaSel.addEventListener('change', refreshSchemaBtn);

			schemaBtn.addEventListener('click', function () {
				var ids = selectedIds();
				if (!ids.length || schemaSel.value === '—') return;

				schemaBtn.disabled = true;
				schemaSt.textContent = '…';

				var body = new URLSearchParams();
				body.append('action', 'livada_seo_bulk_set_schema');
				body.append('nonce',  nonce);
				body.append('schema_type', schemaSel.value);
				ids.forEach(function (id) { body.append('ids[]', id); });

				fetch(ajaxUrl, {
					method:      'POST',
					credentials: 'same-origin',
					headers:     { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
					body:        body.toString(),
				})
					.then(function (r) { return r.json(); })
					.then(function (res) {
						if (res && res.success && res.data) {
							schemaSt.textContent = res.data.updated + ' updated';
						} else {
							schemaSt.textContent = (res && res.data && res.data.message) || 'Failed';
						}
						schemaBtn.disabled = false;
						refreshSchemaBtn();
					})
					.catch(function () {
						schemaSt.textContent = 'Failed';
						schemaBtn.disabled = false;
					});
			});

			// ── AI Fill toolbar ─────────────────────────────────────────────
			var aiBtn   = document.getElementById('livada-bulk-ai-run');
			var aiSel   = document.getElementById('livada-bulk-ai-field');
			var aiForce = document.getElementById('livada-bulk-ai-force');
			var aiSt    = document.getElementById('livada-bulk-ai-status');

			if (aiBtn) {
				aiBtn.addEventListener('click', function () {
					var field = aiSel.value;
					var force = aiForce.checked ? '1' : '';
					var rows  = Array.prototype.slice.call(document.querySelectorAll('tr[data-post-id]'));

					if (!rows.length) {
						aiSt.textContent = '<?php echo esc_js( __( 'Nothing to fill.', 'livada-seo' ) ); ?>';
						return;
					}

					var total      = rows.length;
					var done       = 0;
					var filled     = 0;
					var skipped    = 0;
					var failed     = 0;
					aiBtn.disabled = true;

					function step(i) {
						if (i >= rows.length) {
							aiBtn.disabled = false;
							aiSt.textContent = filled + ' filled, ' + skipped + ' skipped, ' + failed + ' failed';
							return;
						}

						var row    = rows[i];
						var postId = row.getAttribute('data-post-id');
						aiSt.textContent = '<?php echo esc_js( __( 'Generating', 'livada-seo' ) ); ?>… ' + (++done) + '/' + total;

						var body = new URLSearchParams({
							action:  'livada_seo_bulk_ai_fill',
							nonce:   nonce,
							post_id: postId,
							field:   field,
						});
						if (force) { body.append('force', '1'); }

						fetch(ajaxUrl, {
							method:      'POST',
							credentials: 'same-origin',
							headers:     { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
							body:        body.toString(),
						})
							.then(function (r) { return r.json(); })
							.then(function (res) {
								if (res && res.success && res.data) {
									if (res.data.skipped) {
										skipped++;
									} else {
										filled++;
										// Reflect new value + score in the row UI.
										var input = row.querySelector('[data-field="' + field + '"]');
										if (input) { input.value = res.data.value; }
										var sc = row.querySelector('.livada-bulk-score');
										if (sc && typeof res.data.score !== 'undefined') {
											sc.textContent = res.data.score;
										}
									}
								} else {
									failed++;
								}
							})
							.catch(function () { failed++; })
							.then(function () {
								// 250 ms throttle between calls to be polite to the API.
								setTimeout(function () { step(i + 1); }, 250);
							});
					}

					step(0);
				});
			}
		})();
		</script>
		<?php
	}

	// ── AJAX bulk schema-type assigner ────────────────────────────────────────

	/**
	 * Assigns or clears `_livada_seo_schema_type` on a list of post IDs.
	 * Body: ids[]=N&schema_type=Article|Product|… or empty to clear.
	 */
	public static function ajax_set_schema(): void {
		check_ajax_referer( 'livada_seo_admin_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'livada-seo' ) ], 403 );
		}

		$ids  = isset( $_POST['ids'] ) ? (array) $_POST['ids'] : [];
		$ids  = array_values( array_filter( array_map( 'absint', $ids ) ) );
		$type = isset( $_POST['schema_type'] ) ? sanitize_text_field( wp_unslash( (string) $_POST['schema_type'] ) ) : '';

		if ( empty( $ids ) ) {
			wp_send_json_error( [ 'message' => __( 'No posts selected.', 'livada-seo' ) ], 400 );
		}

		$allowed = [ '', 'HowTo', 'Product', 'Event', 'Recipe', 'Review', 'Offer' ];
		if ( ! in_array( $type, $allowed, true ) ) {
			wp_send_json_error( [ 'message' => __( 'Unsupported schema type.', 'livada-seo' ) ], 400 );
		}

		$updated = 0;
		foreach ( $ids as $id ) {
			if ( ! current_user_can( 'edit_post', $id ) ) {
				continue;
			}
			if ( '' === $type ) {
				delete_post_meta( $id, '_livada_seo_schema_type' );
			} else {
				update_post_meta( $id, '_livada_seo_schema_type', $type );
			}
			$updated++;
		}

		wp_send_json_success( [ 'updated' => $updated, 'schema_type' => $type ] );
	}

	// ── AJAX bulk AI fill ─────────────────────────────────────────────────────

	/**
	 * Generates AI suggestions for the missing field on a single post and
	 * persists them. Body params:
	 *   post_id (int)
	 *   field   (title|description|focus_keyword)
	 *   force   (bool, optional) — overwrite even when the field is already filled
	 *
	 * Returns the post's updated score for live UI feedback.
	 */
	public static function ajax_ai_fill(): void {
		check_ajax_referer( 'livada_seo_admin_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'livada-seo' ) ], 403 );
		}

		if ( ! class_exists( 'Livada_SEO_AI' ) ) {
			wp_send_json_error( [ 'message' => __( 'AI module is not active.', 'livada-seo' ) ], 503 );
		}

		$post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
		$field   = isset( $_POST['field'] )   ? sanitize_key( (string) $_POST['field'] ) : '';
		$force   = ! empty( $_POST['force'] );

		if ( $post_id <= 0 || ! current_user_can( 'edit_post', $post_id ) ) {
			wp_send_json_error( [ 'message' => __( 'Invalid post or permissions.', 'livada-seo' ) ], 403 );
		}

		// Map bulk-editor field → AI type + post meta key.
		$map = [
			'title'         => [ 'title',       '_livada_seo_title',         'sanitize_text_field' ],
			'description'   => [ 'description', '_livada_seo_description',   'sanitize_textarea_field' ],
			'focus_keyword' => [ 'keyword',     '_livada_seo_focus_keyword', 'sanitize_text_field' ],
		];

		if ( ! isset( $map[ $field ] ) ) {
			wp_send_json_error( [ 'message' => __( 'Unsupported field.', 'livada-seo' ) ], 400 );
		}

		[ $ai_type, $meta_key, $sanitizer ] = $map[ $field ];

		// Skip when already filled and `force` is not set.
		$current = (string) get_post_meta( $post_id, $meta_key, true );
		if ( '' !== $current && ! $force ) {
			wp_send_json_success( [
				'post_id' => $post_id,
				'skipped' => true,
				'reason'  => 'already_filled',
				'value'   => $current,
			] );
		}

		$result = Livada_SEO_AI::suggest( $post_id, $ai_type );

		if ( is_wp_error( $result ) ) {
			$status = (int) ( $result->get_error_data()['status'] ?? 500 );
			wp_send_json_error( [ 'message' => $result->get_error_message() ], $status );
		}

		$value = $sanitizer( (string) $result );
		update_post_meta( $post_id, $meta_key, $value );

		// Re-run the analyzer so the new score is available immediately.
		if ( class_exists( 'Livada_SEO_Analysis' ) ) {
			Livada_SEO_Analysis::analyze( $post_id );
		}

		$score = get_post_meta( $post_id, '_livada_seo_score', true );

		wp_send_json_success( [
			'post_id' => $post_id,
			'field'   => $field,
			'value'   => $value,
			'skipped' => false,
			'score'   => '' === $score ? '—' : (int) $score,
		] );
	}

	// ── AJAX save ─────────────────────────────────────────────────────────────

	public static function ajax_save_row(): void {
		check_ajax_referer( 'livada_seo_admin_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'livada-seo' ) ], 403 );
		}

		$post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0;
		$field   = isset( $_POST['field'] )   ? sanitize_key( $_POST['field'] ) : '';
		$value   = isset( $_POST['value'] )   ? wp_unslash( $_POST['value'] ) : '';

		if ( $post_id <= 0 || ! current_user_can( 'edit_post', $post_id ) ) {
			wp_send_json_error( [ 'message' => __( 'Invalid post or permissions.', 'livada-seo' ) ], 403 );
		}

		$field_map = [
			'title'         => [ '_livada_seo_title',         'sanitize_text_field'     ],
			'description'   => [ '_livada_seo_description',   'sanitize_textarea_field' ],
			'focus_keyword' => [ '_livada_seo_focus_keyword', 'sanitize_text_field'     ],
		];

		if ( isset( $field_map[ $field ] ) ) {
			[ $meta_key, $sanitizer ] = $field_map[ $field ];
			$clean = $sanitizer( (string) $value );

			if ( '' === $clean ) {
				delete_post_meta( $post_id, $meta_key );
			} else {
				update_post_meta( $post_id, $meta_key, $clean );
			}
		} elseif ( 'noindex' === $field ) {
			if ( '1' === (string) $value ) {
				update_post_meta( $post_id, '_livada_seo_noindex', '1' );
			} else {
				delete_post_meta( $post_id, '_livada_seo_noindex' );
			}
		} else {
			wp_send_json_error( [ 'message' => __( 'Unknown field.', 'livada-seo' ) ], 400 );
		}

		// Re-run analysis so the score reflects the change immediately.
		if ( class_exists( 'Livada_SEO_Analysis' ) ) {
			Livada_SEO_Analysis::analyze( $post_id );
		}

		$score = get_post_meta( $post_id, '_livada_seo_score', true );

		wp_send_json_success( [
			'score' => $score === '' ? '—' : (int) $score,
		] );
	}
}
