<?php
/**
 * Database Upgrader
 *
 * Handles data transformations during upgrades.
 * Contains Migration 5 & 7 for existing installations.
 *
 * @package Wisewand
 * @since 1.0.2
 * @license GPL-2.0-or-later
 */

namespace Wisewand\Database;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_error_log, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- error_log() only used within WP_DEBUG conditionals; direct database calls and schema changes required for upgrades

/**
 * Database upgrade manager
 *
 * Handles data migrations for existing installations.
 * Only contains migrations that transform existing data.
 *
 * @since 1.0.2
 */
class Database_Upgrader {

	/**
	 * Run Migration 5: Add imported status sub-statuses
	 *
	 * Replaces 'draft' and 'published' with 'imported_draft' and 'imported_published'
	 * for entries that have wordpress_post_id set.
	 *
	 * Migration only runs if table already exists (upgrade scenario).
	 * For new installations, the base schema already has the correct ENUM.
	 *
	 * @since 1.0.2
	 * @global wpdb $wpdb WordPress database abstraction object.
	 * @return bool True if migration ran successfully or already completed.
	 */
	public static function run_migration_5() {
		global $wpdb;

		$table_name = $wpdb->prefix . 'wisewand_editorial_calendar';

		// Check if table exists (upgrade scenario only)
		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		$table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) );

		if ( ! $table_exists ) {
			// Table doesn't exist yet - skip migration (fresh install)
			return true;
		}

		// Check current ENUM values
		$check_query = $wpdb->prepare(
			"SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
			WHERE TABLE_SCHEMA = %s
			AND TABLE_NAME = %s
			AND COLUMN_NAME = 'wordpress_status'",
			DB_NAME,
			$table_name
		);

		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query already prepared above
		$current_enum = $wpdb->get_var( $check_query );

		// Check if migration already completed
		if ( $current_enum && strpos( $current_enum, 'imported_draft' ) !== false ) {
			if ( WP_DEBUG ) {
				error_log( 'Wisewand: Migration 5 already completed (imported_draft found in ENUM)' );
			}
			return true;
		}

		// Migration needed
		if ( WP_DEBUG ) {
			error_log( 'Wisewand: Starting Migration 5 - Adding imported status sub-statuses' );
			error_log( 'Wisewand: Current ENUM: ' . $current_enum );
		}

		// Step 1: Count existing entries for logging
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$draft_count = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT(*) FROM `{$table_name}`
				WHERE wordpress_status = %s
				AND wordpress_post_id IS NOT NULL
				AND wordpress_post_id > 0",
				'draft'
			)
		);

		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$published_count = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT COUNT(*) FROM `{$table_name}`
				WHERE wordpress_status = %s
				AND wordpress_post_id IS NOT NULL
				AND wordpress_post_id > 0",
				'published'
			)
		);
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( WP_DEBUG ) {
			error_log( 'Wisewand: Found ' . $draft_count . ' draft entries to migrate' );
			error_log( 'Wisewand: Found ' . $published_count . ' published entries to migrate' );
		}

		// Step 2: Migrate existing 'draft' to 'imported_draft'
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$wpdb->query(
			$wpdb->prepare(
				"UPDATE `{$table_name}`
				SET wordpress_status = %s
				WHERE wordpress_status = %s
				AND wordpress_post_id IS NOT NULL
				AND wordpress_post_id > 0",
				'imported_draft',
				'draft'
			)
		);
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( WP_DEBUG && ! $wpdb->last_error ) {
			error_log( 'Wisewand: Migrated ' . $wpdb->rows_affected . ' draft entries to imported_draft' );
		}

		// Step 3: Migrate existing 'published' to 'imported_published'
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$wpdb->query(
			$wpdb->prepare(
				"UPDATE `{$table_name}`
				SET wordpress_status = %s
				WHERE wordpress_status = %s
				AND wordpress_post_id IS NOT NULL
				AND wordpress_post_id > 0",
				'imported_published',
				'published'
			)
		);
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( WP_DEBUG && ! $wpdb->last_error ) {
			error_log( 'Wisewand: Migrated ' . $wpdb->rows_affected . ' published entries to imported_published' );
		}

		// Step 4: ALTER TABLE to update ENUM definition (schema already handled by Database_Schema)
		// This step is now redundant as Database_Schema creates table with correct ENUM
		// But we keep it for backward compatibility with existing installations

		if ( WP_DEBUG ) {
			if ( $wpdb->last_error ) {
				error_log( 'Wisewand: Migration 5 error: ' . $wpdb->last_error );
				return false;
			} else {
				error_log( 'Wisewand: Migration 5 completed successfully' );
				update_option( 'wisewand_migration_5_completed', current_time( 'mysql' ) );
			}
		}

		return true;
	}

	/**
	 * Run Migration 7: Add sync_status and migrate from enabled_for_site
	 *
	 * Adds sync_status column and migrates existing enabled_for_site values.
	 * Migration only runs if table already exists (upgrade scenario).
	 *
	 * @since 1.0.2
	 * @global wpdb $wpdb WordPress database abstraction object.
	 * @return bool True if migration ran successfully or already completed.
	 */
	public static function run_migration_7() {
		global $wpdb;

		$table_name = $wpdb->prefix . 'wisewand_rss_feeds';

		// Check if table exists (upgrade scenario only)
		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		$table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) );

		if ( ! $table_exists ) {
			// Table doesn't exist yet - skip migration (fresh install)
			return true;
		}

		// Check if sync_status column already exists
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$sync_status_exists = $wpdb->get_results(
			$wpdb->prepare( "SHOW COLUMNS FROM `{$table_name}` LIKE %s", 'sync_status' )
		);
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( ! empty( $sync_status_exists ) ) {
			if ( WP_DEBUG ) {
				error_log( 'Wisewand: Migration 7 already completed (sync_status column exists)' );
			}
			return true;
		}

		// Migration needed
		if ( WP_DEBUG ) {
			error_log( 'Wisewand: Starting Migration 7 - Adding RSS sync_status column' );
		}

		// Check if enabled_for_site exists to migrate data
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$enabled_for_site_exists = $wpdb->get_results(
			$wpdb->prepare( "SHOW COLUMNS FROM `{$table_name}` LIKE %s", 'enabled_for_site' )
		);
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( ! empty( $enabled_for_site_exists ) ) {
			// Migrate existing enabled_for_site values to sync_status
			// Note: sync_status column is already added by Database_Schema
			// We just need to migrate the data
			// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
			// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
			$wpdb->query(
				"UPDATE `{$table_name}`
				SET sync_status = CASE
					WHEN enabled_for_site = 1 THEN 'enabled'
					ELSE 'disabled'
				END
				WHERE sync_status IS NULL OR sync_status = ''"
			);
			// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

			if ( WP_DEBUG && ! $wpdb->last_error ) {
				error_log( 'Wisewand: Migrated enabled_for_site values to sync_status' );
			}
		}

		if ( WP_DEBUG ) {
			if ( $wpdb->last_error ) {
				error_log( 'Wisewand: Migration 7 error: ' . $wpdb->last_error );
				return false;
			} else {
				error_log( 'Wisewand: Migration 7 completed successfully - RSS sync_status ready' );
				update_option( 'wisewand_migration_7_completed', current_time( 'mysql' ) );
			}
		}

		return true;
	}

	/**
	 * Run Migration 9: Add last_output_id column to wisewand_rss_articles
	 *
	 * Adds last_output_id column for caching discoverarticle output IDs.
	 * This eliminates redundant API calls during import, cutting API usage in half.
	 *
	 * Migration only runs if table already exists (upgrade scenario).
	 * For new installations, the base schema already has the column.
	 *
	 * @since 1.2.0
	 * @global wpdb $wpdb WordPress database abstraction object.
	 * @return bool True if migration ran successfully or already completed.
	 */
	public static function run_migration_9() {
		global $wpdb;

		$table_name = $wpdb->prefix . 'wisewand_rss_articles';

		// Check if table exists (upgrade scenario only)
		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		$table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) );

		if ( ! $table_exists ) {
			// Table doesn't exist yet - skip migration (fresh install)
			return true;
		}

		// Check if last_output_id column already exists
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$column_exists = $wpdb->get_results(
			$wpdb->prepare( "SHOW COLUMNS FROM `{$table_name}` LIKE %s", 'last_output_id' )
		);
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( ! empty( $column_exists ) ) {
			if ( WP_DEBUG ) {
				error_log( 'Wisewand: Migration 9 already completed (last_output_id column exists)' );
			}
			return true;
		}

		// Migration needed
		if ( WP_DEBUG ) {
			error_log( 'Wisewand: Starting Migration 9 - Adding last_output_id column for API optimization' );
		}

		// Add last_output_id column after has_cover_image
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$result = $wpdb->query(
			"ALTER TABLE `{$table_name}`
			ADD COLUMN last_output_id varchar(100) DEFAULT NULL COMMENT 'Cached output ID from discovery (eliminates redundant API calls)'
			AFTER has_cover_image"
		);
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( WP_DEBUG ) {
			if ( $wpdb->last_error ) {
				error_log( 'Wisewand: Migration 9 error: ' . $wpdb->last_error );
				return false;
			} else {
				error_log( 'Wisewand: Migration 9 completed successfully - last_output_id column added' );
				error_log( 'Wisewand: API optimization active - discoverarticle imports will now use cached output IDs' );
				update_option( 'wisewand_migration_9_completed', current_time( 'mysql' ) );
			}
		}

		return $result !== false;
	}

	/**
	 * Run Migration 10: Update UNIQUE constraint to include language_code
	 *
	 * Updates the UNIQUE KEY from (keyword) to (keyword, language_code, location_code)
	 * This allows same keyword text in different languages without conflicts.
	 *
	 * Migration only runs if table already exists (upgrade scenario).
	 * For new installations, the base schema already has the correct constraint.
	 *
	 * @since 1.3.0
	 * @global wpdb $wpdb WordPress database abstraction object.
	 * @return bool True if migration ran successfully or already completed.
	 */
	public static function run_migration_10() {
		global $wpdb;

		$table_name = $wpdb->prefix . 'wisewand_saved_keywords';

		// Check if table exists (upgrade scenario only)
		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		$table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) );

		if ( ! $table_exists ) {
			// Table doesn't exist yet - skip migration (fresh install)
			return true;
		}

		// Check if new UNIQUE constraint already exists
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		$check_query = $wpdb->prepare(
			"SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
			WHERE TABLE_SCHEMA = %s
			AND TABLE_NAME = %s
			AND INDEX_NAME = 'keyword_language'",
			DB_NAME,
			$table_name
		);
		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query already prepared above
		$new_constraint_exists = (int) $wpdb->get_var( $check_query );
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( $new_constraint_exists > 0 ) {
			if ( WP_DEBUG ) {
				error_log( 'Wisewand: Migration 10 already completed (keyword_language constraint exists)' );
			}
			return true;
		}

		// Migration needed
		if ( WP_DEBUG ) {
			error_log( 'Wisewand: Starting Migration 10 - Updating UNIQUE constraint to include language_code' );
		}

		// Step 1: Check if old constraint exists
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		$old_constraint_check = $wpdb->prepare(
			"SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
			WHERE TABLE_SCHEMA = %s
			AND TABLE_NAME = %s
			AND INDEX_NAME = 'keyword'
			AND NON_UNIQUE = 0",
			DB_NAME,
			$table_name
		);
		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query already prepared above
		$old_constraint_exists = (int) $wpdb->get_var( $old_constraint_check );

		// Step 2: Drop old UNIQUE constraint if it exists
		if ( $old_constraint_exists > 0 ) {
			// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
			$wpdb->query( "ALTER TABLE `{$table_name}` DROP INDEX keyword" );
			// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

			if ( WP_DEBUG ) {
				if ( $wpdb->last_error ) {
					error_log( 'Wisewand: Error dropping old constraint: ' . $wpdb->last_error );
				} else {
					error_log( 'Wisewand: Dropped old UNIQUE constraint on keyword' );
				}
			}
		}

		// Step 3: Add new UNIQUE constraint (keyword, language_code, location_code)
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name from $wpdb->prefix is safe
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name from $wpdb->prefix is safe
		$result = $wpdb->query(
			"ALTER TABLE `{$table_name}`
			ADD UNIQUE KEY keyword_language (keyword, language_code, location_code)"
		);
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( WP_DEBUG ) {
			if ( $wpdb->last_error ) {
				error_log( 'Wisewand: Migration 10 error: ' . $wpdb->last_error );
				return false;
			} else {
				error_log( 'Wisewand: Migration 10 completed successfully - UNIQUE constraint now includes language_code' );
				error_log( 'Wisewand: Multilingual keywords are now supported (e.g., "cat" in EN and FR)' );
				update_option( 'wisewand_migration_10_completed', current_time( 'mysql' ) );
			}
		}

		return $result !== false;
	}

	/**
	 * Run Migration 11: Add publish_mode column to wisewand_rss_feeds
	 *
	 * Adds publish_mode column for controlling publication behavior per feed.
	 * Supports three modes: schedule (future), publish (immediate), draft (review).
	 *
	 * Migration only runs if table already exists (upgrade scenario).
	 * For new installations, the base schema already has the column.
	 *
	 * @since 1.4.0
	 * @global wpdb $wpdb WordPress database abstraction object.
	 * @return bool True if migration ran successfully or already completed.
	 */
	public static function run_migration_11() {
		// Load migration class.
		if ( ! class_exists( 'Wisewand\\Database\\Migrations\\Migration_011_Add_Publish_Mode' ) ) {
			require_once WISEWAND_PLUGIN_DIR . 'includes/Database/migrations/Migration_011_Add_Publish_Mode.php';
		}

		return \Wisewand\Database\Migrations\Migration_011_Add_Publish_Mode::up();
	}

	/**
	 * Run Migration 12: Add embedding column to saved_keywords
	 *
	 * Adds embedding column for AI Semantic Deduplication.
	 * Stores 256-dimensional vectors as binary data (mediumblob).
	 *
	 * @since 1.6.16
	 * @global wpdb $wpdb WordPress database abstraction object.
	 * @return bool True if migration ran successfully or already completed.
	 */
	public static function run_migration_12() {
		global $wpdb;

		$table_name = $wpdb->prefix . 'wisewand_saved_keywords';

		// Check if table exists (upgrade scenario only)
		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$table_exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table_name ) );

		if ( ! $table_exists ) {
			return true;
		}

		// Check if embedding column already exists
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
		$column_exists = $wpdb->get_results(
			$wpdb->prepare( "SHOW COLUMNS FROM `{$table_name}` LIKE %s", 'embedding' )
		);
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( ! empty( $column_exists ) ) {
			if ( WP_DEBUG ) {
				error_log( 'Wisewand: Migration 12 already completed (embedding column exists)' );
			}
			return true;
		}

		// Migration needed
		if ( WP_DEBUG ) {
			error_log( 'Wisewand: Starting Migration 12 - Adding embedding column for AI Semantic Deduplication' );
		}

		// Add embedding column
		// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		// phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
		$result = $wpdb->query(
			"ALTER TABLE `{$table_name}`
			ADD COLUMN embedding mediumblob DEFAULT NULL COMMENT 'Binary storage of 256-float vector'"
		);
		// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

		if ( WP_DEBUG ) {
			if ( $wpdb->last_error ) {
				error_log( 'Wisewand: Migration 12 error: ' . $wpdb->last_error );
				return false;
			} else {
				error_log( 'Wisewand: Migration 12 completed successfully - embedding column added' );
				update_option( 'wisewand_migration_12_completed', current_time( 'mysql' ) );
			}
		}

		return $result !== false;
	}

	/**
	 * Run all data migrations
	 *
	 * Executes all data transformation migrations in order.
	 * Safe to run multiple times - migrations check if already completed.
	 *
	 * @since 1.0.2
	 * @return bool True if all migrations completed successfully.
	 */
	public static function run_all_migrations() {
		$migration_5_success  = self::run_migration_5();
		$migration_7_success  = self::run_migration_7();
		$migration_9_success  = self::run_migration_9();
		$migration_10_success = self::run_migration_10();
		$migration_11_success = self::run_migration_11();
		$migration_12_success = self::run_migration_12();

		return $migration_5_success && $migration_7_success && $migration_9_success && $migration_10_success && $migration_11_success && $migration_12_success;
	}

	/**
	 * Check if migrations are needed
	 *
	 * @since 1.0.2
	 * @return bool True if any migration needs to run.
	 */
	public static function needs_migration() {
		// Check if migration tracking options exist
		$migration_5_done  = get_option( 'wisewand_migration_5_completed' );
		$migration_7_done  = get_option( 'wisewand_migration_7_completed' );
		$migration_9_done  = get_option( 'wisewand_migration_9_completed' );
		$migration_10_done = get_option( 'wisewand_migration_10_completed' );
		$migration_11_done = get_option( 'wisewand_migration_11_completed' );
		$migration_12_done = get_option( 'wisewand_migration_12_completed' );

		// If any migration hasn't completed, we need to run migrations
		return ! $migration_5_done || ! $migration_7_done || ! $migration_9_done || ! $migration_10_done || ! $migration_11_done || ! $migration_12_done;
	}

	/**
	 * Get migration status
	 *
	 * Returns array with status of each migration.
	 *
	 * @since 1.0.2
	 * @return array Migration status for each migration.
	 */
	public static function get_migration_status() {
		return array(
			'migration_5'  => array(
				'completed'    => (bool) get_option( 'wisewand_migration_5_completed' ),
				'completed_at' => get_option( 'wisewand_migration_5_completed' ),
				'description'  => 'Add imported status sub-statuses (imported_draft, imported_published)',
			),
			'migration_7'  => array(
				'completed'    => (bool) get_option( 'wisewand_migration_7_completed' ),
				'completed_at' => get_option( 'wisewand_migration_7_completed' ),
				'description'  => 'Add sync_status column and migrate from enabled_for_site',
			),
			'migration_9'  => array(
				'completed'    => (bool) get_option( 'wisewand_migration_9_completed' ),
				'completed_at' => get_option( 'wisewand_migration_9_completed' ),
				'description'  => 'Change auto_import_enabled default from 0 to 1 (WordPress.org ready)',
			),
			'migration_10' => array(
				'completed'    => (bool) get_option( 'wisewand_migration_10_completed' ),
				'completed_at' => get_option( 'wisewand_migration_10_completed' ),
				'description'  => 'Update UNIQUE constraint to include language_code for multilingual support',
			),
			'migration_11' => array(
				'completed'    => (bool) get_option( 'wisewand_migration_11_completed' ),
				'completed_at' => get_option( 'wisewand_migration_11_completed' ),
				'description'  => 'Add publish_mode column for RSS feeds publication control',
			),
			'migration_12' => array(
				'completed'    => (bool) get_option( 'wisewand_migration_12_completed' ),
				'completed_at' => get_option( 'wisewand_migration_12_completed' ),
				'description'  => 'Add embedding column for AI Semantic Deduplication',
			),
		);
	}
}
