<?php
/**
 * SEO Fury Migration Wizard
 *
 * Detects existing SEO plugins (Yoast, Rank Math, AIOSEO, SEOPress)
 * and offers to migrate their data into SEO Fury on first activation.
 */

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

class SEO_Fury_Migration_Wizard {

    /**
     * Mapping of plugin slug => display info
     */
    private $supported_plugins = array();

    /**
     * Post meta mapping: plugin_slug => array of [ source_key => target_key ]
     */
    private $meta_map = array();

    /**
     * Plugin file paths for deactivation after migration
     */
    private $plugin_files = array(
        'yoast'    => 'wordpress-seo/wp-seo.php',
        'rankmath' => 'seo-by-rank-math/rank-math.php',
        'aioseo'   => 'all-in-one-seo-pack/all_in_one_seo_pack.php',
        'seopress' => 'wp-seopress/seopress.php',
    );

    /**
     * Alternative plugin file paths (premium versions)
     */
    private $plugin_files_premium = array(
        'yoast'    => 'wordpress-seo-premium/wp-seo-premium.php',
        'rankmath' => 'seo-by-rank-math-pro/rank-math-pro.php',
        'aioseo'   => 'all-in-one-seo-pack-pro/all_in_one_seo_pack.php',
        'seopress' => 'wp-seopress-pro/seopress-pro.php',
    );

    public function __construct() {
        $this->setup_plugin_definitions();
        $this->setup_meta_maps();

        add_action('wp_ajax_seo_fury_wizard_detect', array($this, 'ajax_detect'));
        add_action('wp_ajax_seo_fury_wizard_migrate_batch', array($this, 'ajax_migrate_batch'));
        add_action('wp_ajax_seo_fury_wizard_migrate_settings', array($this, 'ajax_migrate_settings'));
        add_action('wp_ajax_seo_fury_wizard_dismiss', array($this, 'ajax_dismiss'));
        add_action('wp_ajax_seo_fury_wizard_deactivate_plugin', array($this, 'ajax_deactivate_plugin'));

        // Show notice on first activation
        if (is_admin()) {
            add_action('admin_notices', array($this, 'render_admin_notice'));
        }
    }

    /**
     * Define supported SEO plugins
     */
    private function setup_plugin_definitions() {
        $this->supported_plugins = array(
            'yoast' => array(
                'name'   => 'Yoast SEO',
                'icon'   => '🟢',
                'detect' => array(
                    'meta_key' => '_yoast_wpseo_title',
                    'option'   => 'wpseo_titles',
                ),
            ),
            'rankmath' => array(
                'name'   => 'Rank Math',
                'icon'   => '🟣',
                'detect' => array(
                    'meta_key' => 'rank_math_title',
                    'option'   => 'rank-math-options-titles',
                ),
            ),
            'aioseo' => array(
                'name'   => 'All in One SEO',
                'icon'   => '🔵',
                'detect' => array(
                    'meta_key' => '_aioseop_title',
                    'option'   => 'aioseo_options',
                    'table'    => 'aioseo_posts',
                ),
            ),
            'seopress' => array(
                'name'   => 'SEOPress',
                'icon'   => '🟠',
                'detect' => array(
                    'meta_key' => '_seopress_titles_title',
                    'option'   => 'seopress_titles_option_name',
                ),
            ),
        );
    }

    /**
     * Define meta key mappings for each plugin
     */
    private function setup_meta_maps() {
        $this->meta_map = array(
            'yoast' => array(
                // Title & Description
                '_yoast_wpseo_title'                 => '_seo_fury_title',
                '_yoast_wpseo_metadesc'              => '_seo_fury_description',
                '_yoast_wpseo_focuskw'               => '_seo_fury_focus_keyword',
                '_yoast_wpseo_canonical'              => '_seo_fury_canonical',
                // Robots
                '_yoast_wpseo_meta-robots-noindex'    => '_seo_fury_page_robots_noindex',
                '_yoast_wpseo_meta-robots-nofollow'   => '_seo_fury_page_robots_nofollow',
                '_yoast_wpseo_meta-robots-adv'        => '_seo_fury_page_robots_advanced', // noimageindex,noarchive,nosnippet
                // Social
                '_yoast_wpseo_opengraph-title'        => '_seo_fury_og_title',
                '_yoast_wpseo_opengraph-description'  => '_seo_fury_og_description',
                '_yoast_wpseo_opengraph-image'        => '_seo_fury_og_image',
                '_yoast_wpseo_twitter-title'          => '_seo_fury_twitter_title',
                '_yoast_wpseo_twitter-description'    => '_seo_fury_twitter_description',
                '_yoast_wpseo_twitter-image'          => '_seo_fury_twitter_image',
                // Taxonomy & Structure
                '_yoast_wpseo_primary_category'       => '_seo_fury_primary_category',
                '_yoast_wpseo_is_cornerstone'         => '_seo_fury_cornerstone',
                // Schema
                '_yoast_wpseo_schema_page_type'       => '_seo_fury_schema_page_type',
                '_yoast_wpseo_schema_article_type'    => '_seo_fury_schema_article_type',
            ),
            'rankmath' => array(
                // Title & Description
                'rank_math_title'                => '_seo_fury_title',
                'rank_math_description'          => '_seo_fury_description',
                'rank_math_focus_keyword'        => '_seo_fury_focus_keyword',
                'rank_math_canonical_url'        => '_seo_fury_canonical',
                // Social
                'rank_math_facebook_title'       => '_seo_fury_og_title',
                'rank_math_facebook_description' => '_seo_fury_og_description',
                'rank_math_facebook_image'       => '_seo_fury_og_image',
                'rank_math_twitter_title'        => '_seo_fury_twitter_title',
                'rank_math_twitter_description'  => '_seo_fury_twitter_description',
                'rank_math_twitter_image'        => '_seo_fury_twitter_image',
                'rank_math_twitter_use_facebook' => '_seo_fury_twitter_use_og',
                // Taxonomy & Structure
                'rank_math_primary_category'     => '_seo_fury_primary_category',
                'rank_math_pillar_content'       => '_seo_fury_cornerstone',
                'rank_math_breadcrumb_title'     => '_seo_fury_breadcrumb_title',
                // rank_math_robots handled separately (array → individual keys)
            ),
            'aioseo_v3' => array(
                '_aioseop_title'       => '_seo_fury_title',
                '_aioseop_description' => '_seo_fury_description',
                '_aioseop_keywords'    => '_seo_fury_focus_keyword',
                '_aioseop_canonical'   => '_seo_fury_canonical',
                '_aioseop_noindex'     => '_seo_fury_page_robots_noindex',
                '_aioseop_nofollow'    => '_seo_fury_page_robots_nofollow',
                '_aioseop_opengraph_settings' => '_seo_fury_aioseo_og_raw', // JSON, parsed in convert_value
            ),
            'seopress' => array(
                // Title & Description
                '_seopress_titles_title'           => '_seo_fury_title',
                '_seopress_titles_desc'            => '_seo_fury_description',
                '_seopress_analysis_target_kw'     => '_seo_fury_focus_keyword',
                '_seopress_robots_canonical'       => '_seo_fury_canonical',
                // Robots
                '_seopress_robots_index'           => '_seo_fury_page_robots_noindex',
                '_seopress_robots_follow'          => '_seo_fury_page_robots_nofollow',
                '_seopress_robots_archive'         => '_seo_fury_page_robots_noarchive',
                '_seopress_robots_imageindex'      => '_seo_fury_page_robots_noimageindex',
                '_seopress_robots_snippet'         => '_seo_fury_page_robots_nosnippet',
                // Social
                '_seopress_social_fb_title'        => '_seo_fury_og_title',
                '_seopress_social_fb_desc'         => '_seo_fury_og_description',
                '_seopress_social_fb_img'          => '_seo_fury_og_image',
                '_seopress_social_twitter_title'   => '_seo_fury_twitter_title',
                '_seopress_social_twitter_desc'    => '_seo_fury_twitter_description',
                '_seopress_social_twitter_img'     => '_seo_fury_twitter_image',
                // Structure
                '_seopress_robots_breadcrumbs'     => '_seo_fury_breadcrumb_title',
                '_seopress_robots_primary_cat'     => '_seo_fury_primary_category',
            ),
        );
    }

    /**
     * Detect which SEO plugins have data in the database.
     *
     * Counts posts using ALL source meta keys (not just title), so posts
     * with only description, keyword, robots, canonical, or social meta
     * are properly detected and will be migrated.
     */
    public function detect_plugins() {
        global $wpdb;
        $detected = array();

        foreach ($this->supported_plugins as $slug => $info) {
            $count = 0;

            // Count posts with ANY of the source meta keys (not just title)
            $count = $this->get_total_count($slug);

            // Also check options as secondary signal
            $has_settings = !empty($info['detect']['option']) && get_option($info['detect']['option'], null) !== null;

            if ($count > 0 || $has_settings) {
                $detected[$slug] = array(
                    'name'         => $info['name'],
                    'icon'         => $info['icon'],
                    'post_count'   => $count,
                    'has_settings' => $has_settings,
                    'is_active'    => $this->is_source_plugin_active($slug),
                );
            }
        }

        return $detected;
    }

    /**
     * Migrate a batch of posts for a given plugin
     *
     * @param string $plugin  Plugin slug (yoast, rankmath, aioseo, seopress)
     * @param int    $offset  Starting offset
     * @param int    $batch   Batch size
     * @return array  Migration result with counts
     */
    public function migrate_batch($plugin, $offset = 0, $batch = 50) {
        global $wpdb;

        $migrated = 0;
        $skipped  = 0;
        $errors   = 0;

        // Get post IDs that have source data
        $post_ids = $this->get_source_post_ids($plugin, $offset, $batch);

        if (empty($post_ids)) {
            return array(
                'migrated' => 0,
                'skipped'  => 0,
                'errors'   => 0,
                'done'     => true,
            );
        }

        foreach ($post_ids as $post_id) {
            $result = $this->migrate_post_meta($post_id, $plugin);
            if ($result === 'migrated') {
                $migrated++;
            } elseif ($result === 'skipped') {
                $skipped++;
            } else {
                $errors++;
            }
        }

        return array(
            'migrated' => $migrated,
            'skipped'  => $skipped,
            'errors'   => $errors,
            'done'     => count($post_ids) < $batch,
        );
    }

    /**
     * Get post IDs that have data from a given source plugin
     */
    private function get_source_post_ids($plugin, $offset, $batch) {
        global $wpdb;

        $meta_key = '';

        switch ($plugin) {
            case 'yoast':
                $meta_key = '_yoast_wpseo_title';
                break;
            case 'rankmath':
                $meta_key = 'rank_math_title';
                break;
            case 'aioseo':
                // Try v4 table first
                return $this->get_aioseo_post_ids($offset, $batch);
            case 'seopress':
                $meta_key = '_seopress_titles_title';
                break;
            default:
                return array();
        }

        // Get posts that have any source meta (using title as representative key)
        // But also include posts that have description, even without title
        $map = $this->get_meta_map_for_plugin($plugin);
        $source_keys = array_keys($map);

        // Mirror get_total_count(): rank_math_robots is handled separately
        // (array → individual keys) but a post may carry ONLY robots directives,
        // so it must be selected too — otherwise such posts are counted but
        // never migrated, leaving the progress bar short of the total.
        if ($plugin === 'rankmath') {
            $source_keys[] = 'rank_math_robots';
        }

        if (empty($source_keys)) {
            return array();
        }

        $placeholders = implode(',', array_fill(0, count($source_keys), '%s'));

        return $wpdb->get_col($wpdb->prepare(
            "SELECT DISTINCT post_id FROM {$wpdb->postmeta}
             WHERE meta_key IN ({$placeholders}) AND meta_value != ''
             ORDER BY post_id ASC
             LIMIT %d OFFSET %d",
            array_merge($source_keys, array($batch, $offset))
        ));
    }

    /**
     * Get post IDs from AIOSEO (try v4 table first, fall back to v3 meta)
     */
    private function get_aioseo_post_ids($offset, $batch) {
        global $wpdb;

        $table = $wpdb->prefix . 'aioseo_posts';
        $table_exists = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = %s AND table_name = %s",
            DB_NAME,
            $table
        ));

        if ($table_exists) {
            return $wpdb->get_col($wpdb->prepare(
                "SELECT post_id FROM {$table}
                 WHERE (title IS NOT NULL AND title != '') OR (description IS NOT NULL AND description != '')
                 ORDER BY post_id ASC
                 LIMIT %d OFFSET %d",
                $batch,
                $offset
            ));
        }

        // Fallback to v3 meta keys
        $v3_keys = array_keys($this->meta_map['aioseo_v3']);
        $placeholders = implode(',', array_fill(0, count($v3_keys), '%s'));

        return $wpdb->get_col($wpdb->prepare(
            "SELECT DISTINCT post_id FROM {$wpdb->postmeta}
             WHERE meta_key IN ({$placeholders}) AND meta_value != ''
             ORDER BY post_id ASC
             LIMIT %d OFFSET %d",
            array_merge($v3_keys, array($batch, $offset))
        ));
    }

    /**
     * Migrate meta for a single post
     *
     * @param int    $post_id
     * @param string $plugin
     * @return string  'migrated', 'skipped', or 'error'
     */
    private function migrate_post_meta($post_id, $plugin) {
        $map = $this->get_meta_map_for_plugin($plugin);

        if (empty($map)) {
            return 'error';
        }

        $did_migrate = false;

        // Special handling for AIOSEO v4
        if ($plugin === 'aioseo' && $this->has_aioseo_v4_table()) {
            $did_migrate = $this->migrate_aioseo_v4_post($post_id);
        }

        // Standard meta-to-meta migration
        foreach ($map as $source_key => $target_key) {
            // Skip if we already have data in the target
            $existing = get_post_meta($post_id, $target_key, true);
            if (!empty($existing)) {
                continue;
            }

            $source_value = get_post_meta($post_id, $source_key, true);
            if (empty($source_value)) {
                continue;
            }

            // Convert value based on plugin specifics
            $converted = $this->convert_value($source_value, $source_key, $target_key, $plugin);

            if ($converted !== null && $converted !== '') {
                update_post_meta($post_id, $target_key, $converted);
                $did_migrate = true;
            }
        }

        // Rank Math special: robots array → individual keys
        if ($plugin === 'rankmath') {
            if ($this->migrate_rankmath_robots($post_id)) {
                $did_migrate = true;
            }
        }

        // Yoast special: advanced robots (comma-separated "noimageindex,noarchive,nosnippet")
        if ($plugin === 'yoast') {
            if ($this->migrate_yoast_advanced_robots($post_id)) {
                $did_migrate = true;
            }
        }

        // AIOSEO v3 special: OG settings from JSON blob
        if ($plugin === 'aioseo') {
            if ($this->migrate_aioseo_v3_og($post_id)) {
                $did_migrate = true;
            }
        }

        return $did_migrate ? 'migrated' : 'skipped';
    }

    /**
     * Get the appropriate meta map for a plugin
     */
    private function get_meta_map_for_plugin($plugin) {
        if ($plugin === 'aioseo') {
            // If v4 table exists, we handle it separately; use v3 meta as fallback
            if ($this->has_aioseo_v4_table()) {
                return $this->meta_map['aioseo_v3']; // v3 as fallback for posts not in v4
            }
            return $this->meta_map['aioseo_v3'];
        }

        return isset($this->meta_map[$plugin]) ? $this->meta_map[$plugin] : array();
    }

    /**
     * Check if AIOSEO v4 table exists
     */
    private function has_aioseo_v4_table() {
        global $wpdb;
        static $exists = null;

        if ($exists === null) {
            $table = $wpdb->prefix . 'aioseo_posts';
            $exists = (bool) $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = %s AND table_name = %s",
                DB_NAME,
                $table
            ));
        }

        return $exists;
    }

    /**
     * Migrate data from AIOSEO v4 table for a single post
     */
    private function migrate_aioseo_v4_post($post_id) {
        global $wpdb;

        $table = $wpdb->prefix . 'aioseo_posts';
        $row = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$table} WHERE post_id = %d",
            $post_id
        ), ARRAY_A);

        if (!$row) {
            return false;
        }

        $did_migrate = false;
        $v4_map = array(
            'title'             => '_seo_fury_title',
            'description'       => '_seo_fury_description',
            'canonical_url'     => '_seo_fury_canonical',
            'og_title'          => '_seo_fury_og_title',
            'og_description'    => '_seo_fury_og_description',
            'og_image_url'      => '_seo_fury_og_image',
            'twitter_title'     => '_seo_fury_twitter_title',
            'twitter_description' => '_seo_fury_twitter_description',
            'twitter_image_url' => '_seo_fury_twitter_image',
            'primary_term'      => '_seo_fury_primary_category',
        );

        foreach ($v4_map as $col => $target_key) {
            if (empty($row[$col])) {
                continue;
            }

            $existing = get_post_meta($post_id, $target_key, true);
            if (!empty($existing)) {
                continue;
            }

            // Convert AIOSEO template tags
            $value = $this->convert_aioseo_tags($row[$col]);
            update_post_meta($post_id, $target_key, $value);
            $did_migrate = true;
        }

        // Noindex/Nofollow from v4
        if (!empty($row['robots_noindex']) && $row['robots_noindex'] == 1) {
            $existing = get_post_meta($post_id, '_seo_fury_page_robots_noindex', true);
            if (empty($existing)) {
                update_post_meta($post_id, '_seo_fury_page_robots_noindex', 'on');
                $did_migrate = true;
            }
        }

        if (!empty($row['robots_nofollow']) && $row['robots_nofollow'] == 1) {
            $existing = get_post_meta($post_id, '_seo_fury_page_robots_nofollow', true);
            if (empty($existing)) {
                update_post_meta($post_id, '_seo_fury_page_robots_nofollow', 'on');
                $did_migrate = true;
            }
        }

        // Keyphrases (JSON in AIOSEO v4)
        if (!empty($row['keyphrases'])) {
            $existing = get_post_meta($post_id, '_seo_fury_focus_keyword', true);
            if (empty($existing)) {
                $keyphrases = json_decode($row['keyphrases'], true);
                if (is_array($keyphrases) && !empty($keyphrases['focus']) && !empty($keyphrases['focus']['keyphrase'])) {
                    update_post_meta($post_id, '_seo_fury_focus_keyword', sanitize_text_field($keyphrases['focus']['keyphrase']));
                    $did_migrate = true;
                }
            }
        }

        return $did_migrate;
    }

    /**
     * Convert value based on source plugin format
     */
    private function convert_value($value, $source_key, $target_key, $plugin) {
        // Yoast
        if ($plugin === 'yoast') {
            // noindex/nofollow → 1 means yes
            if ($source_key === '_yoast_wpseo_meta-robots-noindex' && $value == '1') {
                return 'on';
            }
            if ($source_key === '_yoast_wpseo_meta-robots-nofollow' && $value == '1') {
                return 'on';
            }

            // Advanced robots: comma-separated directives like "noimageindex,noarchive,nosnippet"
            // We handle these by setting individual keys directly in migrate_post_meta
            if ($source_key === '_yoast_wpseo_meta-robots-adv') {
                return null; // Skip standard migration; handled in migrate_yoast_advanced_robots()
            }

            // Convert Yoast template vars → our format
            return $this->convert_yoast_tags($value);
        }

        // Rank Math: convert template vars
        if ($plugin === 'rankmath') {
            return $this->convert_rankmath_tags($value);
        }

        // SEOPress: robots directives → "yes" means yes
        if ($plugin === 'seopress') {
            $seopress_robots_keys = array(
                '_seopress_robots_index',
                '_seopress_robots_follow',
                '_seopress_robots_archive',
                '_seopress_robots_imageindex',
                '_seopress_robots_snippet',
            );
            if (in_array($source_key, $seopress_robots_keys, true)) {
                return $value === 'yes' ? 'on' : '';
            }

            return $this->convert_seopress_tags($value);
        }

        // AIOSEO v3: "on" for noindex/nofollow
        if (in_array($source_key, array('_aioseop_noindex', '_aioseop_nofollow'), true)) {
            return $value === 'on' ? 'on' : '';
        }

        // AIOSEO v3: OG settings (JSON blob) — skip standard migration
        if ($source_key === '_aioseop_opengraph_settings') {
            return null;
        }

        return $value;
    }

    /**
     * Migrate Rank Math robots array → individual robot directive keys.
     *
     * Rank Math stores robots as an array: ['index', 'nofollow', 'noarchive', ...]
     * We convert each directive to individual SEO Fury meta keys.
     */
    private function migrate_rankmath_robots($post_id) {
        $robots = get_post_meta($post_id, 'rank_math_robots', true);
        if (!is_array($robots)) {
            return;
        }

        $directives = array(
            'noindex'      => '_seo_fury_page_robots_noindex',
            'nofollow'     => '_seo_fury_page_robots_nofollow',
            'noarchive'    => '_seo_fury_page_robots_noarchive',
            'noimageindex' => '_seo_fury_page_robots_noimageindex',
            'nosnippet'    => '_seo_fury_page_robots_nosnippet',
        );

        $did = false;
        foreach ($directives as $directive => $target_key) {
            if (in_array($directive, $robots, true)) {
                $existing = get_post_meta($post_id, $target_key, true);
                if (empty($existing)) {
                    update_post_meta($post_id, $target_key, 'on');
                    $did = true;
                }
            }
        }
        return $did;
    }

    /**
     * Migrate Yoast advanced robots meta-robots-adv field.
     *
     * Yoast stores advanced directives as comma-separated string:
     * "noimageindex,noarchive,nosnippet"
     */
    private function migrate_yoast_advanced_robots($post_id) {
        $adv = get_post_meta($post_id, '_yoast_wpseo_meta-robots-adv', true);
        if (empty($adv) || $adv === 'none') {
            return false;
        }

        $directives = array_map('trim', explode(',', $adv));
        $map = array(
            'noarchive'    => '_seo_fury_page_robots_noarchive',
            'noimageindex' => '_seo_fury_page_robots_noimageindex',
            'nosnippet'    => '_seo_fury_page_robots_nosnippet',
        );

        $did = false;
        foreach ($map as $directive => $target_key) {
            if (in_array($directive, $directives, true)) {
                $existing = get_post_meta($post_id, $target_key, true);
                if (empty($existing)) {
                    update_post_meta($post_id, $target_key, 'on');
                    $did = true;
                }
            }
        }

        return $did;
    }

    /**
     * Migrate AIOSEO v3 OG settings from JSON blob.
     *
     * AIOSEO v3 stores social settings as serialized/JSON in _aioseop_opengraph_settings.
     */
    private function migrate_aioseo_v3_og($post_id) {
        $og_raw = get_post_meta($post_id, '_aioseop_opengraph_settings', true);
        if (empty($og_raw)) {
            return false;
        }

        $og = is_array($og_raw) ? $og_raw : maybe_unserialize($og_raw);
        if (!is_array($og)) {
            return false;
        }

        $map = array(
            'aioseop_opengraph_settings_title'       => '_seo_fury_og_title',
            'aioseop_opengraph_settings_desc'        => '_seo_fury_og_description',
            'aioseop_opengraph_settings_image'       => '_seo_fury_og_image',
            'aioseop_opengraph_settings_customimg'    => '_seo_fury_og_image',
        );

        $did = false;
        foreach ($map as $og_key => $target_key) {
            if (!empty($og[$og_key])) {
                $existing = get_post_meta($post_id, $target_key, true);
                if (empty($existing)) {
                    update_post_meta($post_id, $target_key, sanitize_text_field($og[$og_key]));
                    $did = true;
                }
            }
        }

        return $did;
    }

    /**
     * Convert Yoast template tags to SEO Fury format
     * Yoast uses %%title%%, %%sitename%%, etc.
     */
    private function convert_yoast_tags($value) {
        if (!is_string($value)) {
            return $value;
        }

        $replacements = array(
            '%%title%%'           => '%title%',
            '%%sitename%%'        => '%sitename%',
            '%%sep%%'             => '%sep%',
            '%%sitedesc%%'        => '%tagline%',
            '%%page%%'            => '%page%',
            '%%excerpt%%'         => '%excerpt%',
            '%%date%%'            => '%date%',
            '%%category%%'        => '%category%',
            '%%tag%%'             => '%tag%',
            '%%term_title%%'      => '%term_title%',
            '%%term_description%%' => '%term_description%',
            '%%searchphrase%%'    => '%search_query%',
            '%%primary_category%%' => '%category%',
            '%%currentyear%%'     => '%currentyear%',
            '%%currentmonth%%'    => '%currentmonth%',
            '%%currentday%%'      => '%currentday%',
            '%%pt_single%%'       => '%pt_single%',
            '%%pt_plural%%'       => '%pt_plural%',
        );

        return str_replace(array_keys($replacements), array_values($replacements), $value);
    }

    /**
     * Convert AIOSEO template tags
     * AIOSEO v4 uses #post_title, #site_title, #separator, etc.
     */
    private function convert_aioseo_tags($value) {
        if (!is_string($value)) {
            return $value;
        }

        $replacements = array(
            '#post_title'          => '%title%',
            '#site_title'          => '%sitename%',
            '#separator_sa'        => '%sep%',
            '#tagline'             => '%tagline%',
            '#post_excerpt'        => '%excerpt%',
            '#post_date'           => '%date%',
            '#taxonomy_title'      => '%term_title%',
            '#taxonomy_description' => '%term_description%',
            '#current_year'        => '%currentyear%',
            '#current_month'       => '%currentmonth%',
            '#current_day'         => '%currentday%',
        );

        return str_replace(array_keys($replacements), array_values($replacements), $value);
    }

    /**
     * Migrate global settings from a source plugin
     */
    public function migrate_global_settings($plugin) {
        $migrated = array();

        switch ($plugin) {
            case 'yoast':
                $migrated = $this->migrate_yoast_settings();
                break;
            case 'rankmath':
                $migrated = $this->migrate_rankmath_settings();
                break;
            case 'seopress':
                $migrated = $this->migrate_seopress_settings();
                break;
            case 'aioseo':
                $migrated = $this->migrate_aioseo_settings();
                break;
        }

        return $migrated;
    }

    /**
     * Migrate Yoast global settings
     */
    private function migrate_yoast_settings() {
        $migrated = array();
        $titles = get_option('wpseo_titles', array());

        if (!is_array($titles)) {
            $titles = array();
        }

        // Title separator
        if (!empty($titles['separator'])) {
            $sep_map = array(
                'sc-dash'   => '-',
                'sc-ndash'  => '–',
                'sc-mdash'  => '—',
                'sc-pipe'   => '|',
                'sc-bull'   => '•',
                'sc-star'   => '*',
                'sc-laquo'  => '«',
                'sc-raquo'  => '»',
                'sc-gt'     => '>',
                'sc-lt'     => '<',
            );

            $sep = isset($sep_map[$titles['separator']]) ? $sep_map[$titles['separator']] : $titles['separator'];

            if (empty(get_option('seo_fury_title_separator', ''))) {
                update_option('seo_fury_title_separator', $sep);
                $migrated[] = __('Title separator', 'seo-fury');
            }
        }

        // Homepage title/description
        if (!empty($titles['title-home-wpseo']) && empty(get_option('seo_fury_title_template_home', ''))) {
            update_option('seo_fury_title_template_home', $this->convert_yoast_tags($titles['title-home-wpseo']));
            $migrated[] = __('Homepage title template', 'seo-fury');
        }
        if (!empty($titles['metadesc-home-wpseo']) && empty(get_option('seo_fury_description_template_home', ''))) {
            update_option('seo_fury_description_template_home', $this->convert_yoast_tags($titles['metadesc-home-wpseo']));
            $migrated[] = __('Homepage description template', 'seo-fury');
        }

        // Per post-type title/description templates
        $public_types = get_post_types(array('public' => true), 'names');
        foreach ($public_types as $pt) {
            if (!empty($titles['title-' . $pt]) && empty(get_option('seo_fury_title_template_' . $pt, ''))) {
                update_option('seo_fury_title_template_' . $pt, $this->convert_yoast_tags($titles['title-' . $pt]));
                /* translators: %s: post type name */
                $migrated[] = sprintf(__('%s title template', 'seo-fury'), $pt);
            }
            if (!empty($titles['metadesc-' . $pt]) && empty(get_option('seo_fury_description_template_' . $pt, ''))) {
                update_option('seo_fury_description_template_' . $pt, $this->convert_yoast_tags($titles['metadesc-' . $pt]));
                /* translators: %s: post type name */
                $migrated[] = sprintf(__('%s description template', 'seo-fury'), $pt);
            }
        }

        // Webmaster verification codes
        $wpseo = get_option('wpseo', array());
        if (is_array($wpseo)) {
            if (!empty($wpseo['googleverify']) && empty(get_option('seo_fury_google_verify', ''))) {
                update_option('seo_fury_google_verify', sanitize_text_field($wpseo['googleverify']));
                $migrated[] = __('Google verification code', 'seo-fury');
            }
            if (!empty($wpseo['msverify']) && empty(get_option('seo_fury_bing_verify', ''))) {
                update_option('seo_fury_bing_verify', sanitize_text_field($wpseo['msverify']));
                $migrated[] = __('Bing verification code', 'seo-fury');
            }
            if (!empty($wpseo['pinterestverify']) && empty(get_option('seo_fury_pinterest_verify', ''))) {
                update_option('seo_fury_pinterest_verify', sanitize_text_field($wpseo['pinterestverify']));
                $migrated[] = __('Pinterest verification code', 'seo-fury');
            }
        }

        // Redirects from Yoast Premium
        $yoast_redirects = get_option('wpseo-premium-redirects-export-plain', get_option('wpseo-premium-redirects', array()));
        if (!empty($yoast_redirects) && is_array($yoast_redirects)) {
            $count = $this->migrate_redirects_array($yoast_redirects, 'yoast');
            if ($count > 0) {
                /* translators: %d: number of redirects migrated */
                $migrated[] = sprintf(__('%d redirects', 'seo-fury'), $count);
            }
        }

        // Sitemap settings from Yoast
        $sitemap_migrated = $this->migrate_yoast_sitemap($titles);
        $migrated = array_merge($migrated, $sitemap_migrated);

        // Social settings from Yoast
        $social = get_option('wpseo_social', array());
        if (is_array($social)) {
            $social_migrated = $this->migrate_yoast_social($social);
            $migrated = array_merge($migrated, $social_migrated);
        }

        // Noindex archives from Yoast
        $noindex_migrated = $this->migrate_yoast_noindex_archives($titles);
        $migrated = array_merge($migrated, $noindex_migrated);

        // Breadcrumbs from Yoast
        $breadcrumbs_migrated = $this->migrate_yoast_breadcrumbs();
        $migrated = array_merge($migrated, $breadcrumbs_migrated);

        // Local SEO from Yoast
        $local_migrated = $this->migrate_yoast_local_seo();
        $migrated = array_merge($migrated, $local_migrated);

        // Robots.txt — Yoast doesn't store content, try physical file as fallback
        $robots_migrated = $this->migrate_robots_from_physical_file();
        $migrated = array_merge($migrated, $robots_migrated);

        // Taxonomy term meta from Yoast
        $tax_migrated = $this->migrate_yoast_taxonomy_meta();
        $migrated = array_merge($migrated, $tax_migrated);

        return $migrated;
    }

    /**
     * Migrate Rank Math global settings
     */
    private function migrate_rankmath_settings() {
        $migrated = array();
        $titles = get_option('rank-math-options-titles', array());

        if (!is_array($titles)) {
            $titles = array();
        }

        // Title separator
        if (!empty($titles['title_separator'])) {
            if (empty(get_option('seo_fury_title_separator', ''))) {
                update_option('seo_fury_title_separator', $titles['title_separator']);
                $migrated[] = __('Title separator', 'seo-fury');
            }
        }

        // Homepage title/description
        if (!empty($titles['homepage_title']) && empty(get_option('seo_fury_title_template_home', ''))) {
            update_option('seo_fury_title_template_home', $this->convert_rankmath_tags($titles['homepage_title']));
            $migrated[] = __('Homepage title template', 'seo-fury');
        }
        if (!empty($titles['homepage_description']) && empty(get_option('seo_fury_description_template_home', ''))) {
            update_option('seo_fury_description_template_home', $this->convert_rankmath_tags($titles['homepage_description']));
            $migrated[] = __('Homepage description template', 'seo-fury');
        }

        // Per post-type title/description templates
        $public_types = get_post_types(array('public' => true), 'names');
        foreach ($public_types as $pt) {
            if (!empty($titles['pt_' . $pt . '_title']) && empty(get_option('seo_fury_title_template_' . $pt, ''))) {
                update_option('seo_fury_title_template_' . $pt, $this->convert_rankmath_tags($titles['pt_' . $pt . '_title']));
                /* translators: %s: post type name */
                $migrated[] = sprintf(__('%s title template', 'seo-fury'), $pt);
            }
            if (!empty($titles['pt_' . $pt . '_description']) && empty(get_option('seo_fury_description_template_' . $pt, ''))) {
                update_option('seo_fury_description_template_' . $pt, $this->convert_rankmath_tags($titles['pt_' . $pt . '_description']));
                /* translators: %s: post type name */
                $migrated[] = sprintf(__('%s description template', 'seo-fury'), $pt);
            }
        }

        // Webmaster verification codes
        $general = get_option('rank-math-options-general', array());
        if (is_array($general)) {
            if (!empty($general['google_verify']) && empty(get_option('seo_fury_google_verify', ''))) {
                update_option('seo_fury_google_verify', sanitize_text_field($general['google_verify']));
                $migrated[] = __('Google verification code', 'seo-fury');
            }
            if (!empty($general['bing_verify']) && empty(get_option('seo_fury_bing_verify', ''))) {
                update_option('seo_fury_bing_verify', sanitize_text_field($general['bing_verify']));
                $migrated[] = __('Bing verification code', 'seo-fury');
            }
            if (!empty($general['pinterest_verify']) && empty(get_option('seo_fury_pinterest_verify', ''))) {
                update_option('seo_fury_pinterest_verify', sanitize_text_field($general['pinterest_verify']));
                $migrated[] = __('Pinterest verification code', 'seo-fury');
            }
        }

        // Redirects from Rank Math
        $count = $this->migrate_rankmath_redirects();
        if ($count > 0) {
            /* translators: %d: number of redirects migrated */
            $migrated[] = sprintf(__('%d redirects', 'seo-fury'), $count);
        }

        // Robots.txt content from Rank Math
        // Rank Math stores it inside the rank-math-options-general array
        $rm_robots = '';
        if (is_array($general) && !empty($general['robots_txt_content'])) {
            $rm_robots = $general['robots_txt_content'];
        }
        // Fallback: standalone option (older Rank Math versions)
        if (empty($rm_robots)) {
            $rm_robots = get_option('rank_math_robots_txt_content', '');
        }
        // Fallback: read physical robots.txt file
        if (empty($rm_robots) && file_exists(ABSPATH . 'robots.txt')) {
            $physical = @file_get_contents(ABSPATH . 'robots.txt');
            if (!empty($physical)) {
                $rm_robots = $physical;
            }
        }
        if (!empty($rm_robots)) {
            update_option('seo_fury_robots_content', sanitize_textarea_field($rm_robots));
            update_option('seo_fury_robots_enabled', 1);
            $migrated[] = __('Robots.txt content', 'seo-fury');
        }

        // Sitemap settings from Rank Math
        $sitemap_migrated = $this->migrate_rankmath_sitemap($general, $titles);
        $migrated = array_merge($migrated, $sitemap_migrated);

        // Social settings from Rank Math
        $social_migrated = $this->migrate_rankmath_social($general, $titles);
        $migrated = array_merge($migrated, $social_migrated);

        // Noindex archives from Rank Math
        $noindex_migrated = $this->migrate_rankmath_noindex_archives($titles);
        $migrated = array_merge($migrated, $noindex_migrated);

        // Breadcrumbs from Rank Math
        $breadcrumbs_migrated = $this->migrate_rankmath_breadcrumbs($general);
        $migrated = array_merge($migrated, $breadcrumbs_migrated);

        // Local SEO from Rank Math
        $local_migrated = $this->migrate_rankmath_local_seo($titles);
        $migrated = array_merge($migrated, $local_migrated);

        // Physical robots.txt fallback (if Rank Math robots was empty)
        if (empty($rm_robots)) {
            $robots_migrated = $this->migrate_robots_from_physical_file();
            $migrated = array_merge($migrated, $robots_migrated);
        }

        // Taxonomy term meta from Rank Math
        $tax_migrated = $this->migrate_rankmath_taxonomy_meta();
        $migrated = array_merge($migrated, $tax_migrated);

        return $migrated;
    }

    /**
     * Migrate SEOPress global settings
     */
    private function migrate_seopress_settings() {
        $migrated = array();
        $titles = get_option('seopress_titles_option_name', array());

        if (!is_array($titles)) {
            $titles = array();
        }

        // Title separator
        if (!empty($titles['seopress_titles_sep'])) {
            if (empty(get_option('seo_fury_title_separator', ''))) {
                update_option('seo_fury_title_separator', $titles['seopress_titles_sep']);
                $migrated[] = __('Title separator', 'seo-fury');
            }
        }

        // Homepage title/description
        if (!empty($titles['seopress_titles_home_site_title']) && empty(get_option('seo_fury_title_template_home', ''))) {
            update_option('seo_fury_title_template_home', $this->convert_seopress_tags($titles['seopress_titles_home_site_title']));
            $migrated[] = __('Homepage title template', 'seo-fury');
        }
        if (!empty($titles['seopress_titles_home_site_desc']) && empty(get_option('seo_fury_description_template_home', ''))) {
            update_option('seo_fury_description_template_home', $this->convert_seopress_tags($titles['seopress_titles_home_site_desc']));
            $migrated[] = __('Homepage description template', 'seo-fury');
        }

        // Per post-type title/description templates
        if (!empty($titles['seopress_titles_single_titles']) && is_array($titles['seopress_titles_single_titles'])) {
            foreach ($titles['seopress_titles_single_titles'] as $pt => $data) {
                if (!empty($data['title']) && empty(get_option('seo_fury_title_template_' . $pt, ''))) {
                    update_option('seo_fury_title_template_' . $pt, $this->convert_seopress_tags($data['title']));
                    /* translators: %s: post type name */
                    $migrated[] = sprintf(__('%s title template', 'seo-fury'), $pt);
                }
                if (!empty($data['description']) && empty(get_option('seo_fury_description_template_' . $pt, ''))) {
                    update_option('seo_fury_description_template_' . $pt, $this->convert_seopress_tags($data['description']));
                    /* translators: %s: post type name */
                    $migrated[] = sprintf(__('%s description template', 'seo-fury'), $pt);
                }
            }
        }

        // Webmaster verification codes
        $advanced = get_option('seopress_advanced_option_name', array());
        if (is_array($advanced)) {
            if (!empty($advanced['seopress_advanced_advanced_google']) && empty(get_option('seo_fury_google_verify', ''))) {
                update_option('seo_fury_google_verify', sanitize_text_field($advanced['seopress_advanced_advanced_google']));
                $migrated[] = __('Google verification code', 'seo-fury');
            }
            if (!empty($advanced['seopress_advanced_advanced_bing']) && empty(get_option('seo_fury_bing_verify', ''))) {
                update_option('seo_fury_bing_verify', sanitize_text_field($advanced['seopress_advanced_advanced_bing']));
                $migrated[] = __('Bing verification code', 'seo-fury');
            }
            if (!empty($advanced['seopress_advanced_advanced_pinterest']) && empty(get_option('seo_fury_pinterest_verify', ''))) {
                update_option('seo_fury_pinterest_verify', sanitize_text_field($advanced['seopress_advanced_advanced_pinterest']));
                $migrated[] = __('Pinterest verification code', 'seo-fury');
            }
        }

        // Redirects from SEOPress (stored as CPT seopress_404)
        $count = $this->migrate_seopress_redirects();
        if ($count > 0) {
            /* translators: %d: number of redirects migrated */
            $migrated[] = sprintf(__('%d redirects', 'seo-fury'), $count);
        }

        // Robots.txt content from SEOPress (always overwrite — user chose to migrate)
        $sp_robots_option = get_option('seopress_pro_option_name', array());
        if (is_array($sp_robots_option) && !empty($sp_robots_option['seopress_robots_file'])) {
            update_option('seo_fury_robots_content', sanitize_textarea_field($sp_robots_option['seopress_robots_file']));
            update_option('seo_fury_robots_enabled', 1);
            $migrated[] = __('Robots.txt content', 'seo-fury');
        }

        // Sitemap settings from SEOPress
        $sitemap_migrated = $this->migrate_seopress_sitemap();
        $migrated = array_merge($migrated, $sitemap_migrated);

        // Social settings from SEOPress
        $social_migrated = $this->migrate_seopress_social();
        $migrated = array_merge($migrated, $social_migrated);

        // Noindex archives from SEOPress
        $noindex_migrated = $this->migrate_seopress_noindex_archives($titles);
        $migrated = array_merge($migrated, $noindex_migrated);

        // Local SEO from SEOPress
        $local_migrated = $this->migrate_seopress_local_seo();
        $migrated = array_merge($migrated, $local_migrated);

        // Physical robots.txt fallback (if SEOPress robots was empty)
        if (empty($sp_robots_option['seopress_robots_file'])) {
            $robots_migrated = $this->migrate_robots_from_physical_file();
            $migrated = array_merge($migrated, $robots_migrated);
        }

        // Taxonomy term meta from SEOPress
        $tax_migrated = $this->migrate_seopress_taxonomy_meta();
        $migrated = array_merge($migrated, $tax_migrated);

        return $migrated;
    }

    /**
     * Migrate AIOSEO global settings
     */
    private function migrate_aioseo_settings() {
        $migrated = array();
        $options = get_option('aioseo_options', '');

        if (is_string($options)) {
            $options = json_decode($options, true);
        }

        if (!is_array($options)) {
            $options = array();
        }

        // Title separator
        if (!empty($options['searchAppearance']['global']['separator'])) {
            if (empty(get_option('seo_fury_title_separator', ''))) {
                update_option('seo_fury_title_separator', $options['searchAppearance']['global']['separator']);
                $migrated[] = __('Title separator', 'seo-fury');
            }
        }

        // Homepage title/description
        $home_title = $options['searchAppearance']['global']['siteTitle'] ?? '';
        $home_desc = $options['searchAppearance']['global']['metaDescription'] ?? '';
        if (!empty($home_title) && empty(get_option('seo_fury_title_template_home', ''))) {
            update_option('seo_fury_title_template_home', $this->convert_aioseo_tags($home_title));
            $migrated[] = __('Homepage title template', 'seo-fury');
        }
        if (!empty($home_desc) && empty(get_option('seo_fury_description_template_home', ''))) {
            update_option('seo_fury_description_template_home', $this->convert_aioseo_tags($home_desc));
            $migrated[] = __('Homepage description template', 'seo-fury');
        }

        // Per post-type title/description templates
        $post_types = $options['searchAppearance']['postTypes'] ?? array();
        if (is_array($post_types)) {
            foreach ($post_types as $pt => $data) {
                if (!is_array($data)) continue;
                if (!empty($data['title']) && empty(get_option('seo_fury_title_template_' . $pt, ''))) {
                    update_option('seo_fury_title_template_' . $pt, $this->convert_aioseo_tags($data['title']));
                    /* translators: %s: post type name */
                    $migrated[] = sprintf(__('%s title template', 'seo-fury'), $pt);
                }
                if (!empty($data['metaDescription']) && empty(get_option('seo_fury_description_template_' . $pt, ''))) {
                    update_option('seo_fury_description_template_' . $pt, $this->convert_aioseo_tags($data['metaDescription']));
                    /* translators: %s: post type name */
                    $migrated[] = sprintf(__('%s description template', 'seo-fury'), $pt);
                }
            }
        }

        // Webmaster verification codes
        $tools = $options['webmasterTools'] ?? array();
        if (is_array($tools)) {
            if (!empty($tools['google']) && empty(get_option('seo_fury_google_verify', ''))) {
                update_option('seo_fury_google_verify', sanitize_text_field($tools['google']));
                $migrated[] = __('Google verification code', 'seo-fury');
            }
            if (!empty($tools['bing']) && empty(get_option('seo_fury_bing_verify', ''))) {
                update_option('seo_fury_bing_verify', sanitize_text_field($tools['bing']));
                $migrated[] = __('Bing verification code', 'seo-fury');
            }
            if (!empty($tools['pinterest']) && empty(get_option('seo_fury_pinterest_verify', ''))) {
                update_option('seo_fury_pinterest_verify', sanitize_text_field($tools['pinterest']));
                $migrated[] = __('Pinterest verification code', 'seo-fury');
            }
        }

        // Redirects from AIOSEO
        $count = $this->migrate_aioseo_redirects();
        if ($count > 0) {
            /* translators: %d: number of redirects migrated */
            $migrated[] = sprintf(__('%d redirects', 'seo-fury'), $count);
        }

        // Robots.txt content from AIOSEO (always overwrite — user chose to migrate)
        if (is_array($options) && !empty($options['tools']['robots']['rules'])) {
            $robots_lines = array();
            foreach ($options['tools']['robots']['rules'] as $rule) {
                if (!empty($rule['directive']) && !empty($rule['fieldValue'])) {
                    $robots_lines[] = sanitize_text_field($rule['directive']) . ': ' . sanitize_text_field($rule['fieldValue']);
                }
            }
            if (!empty($robots_lines)) {
                update_option('seo_fury_robots_content', implode("\n", $robots_lines));
                update_option('seo_fury_robots_enabled', 1);
                $migrated[] = __('Robots.txt content', 'seo-fury');
            }
        }

        // Sitemap settings from AIOSEO
        $sitemap_migrated = $this->migrate_aioseo_sitemap($options);
        $migrated = array_merge($migrated, $sitemap_migrated);

        // Social settings from AIOSEO
        $social_migrated = $this->migrate_aioseo_social($options);
        $migrated = array_merge($migrated, $social_migrated);

        // Noindex archives from AIOSEO
        $noindex_migrated = $this->migrate_aioseo_noindex_archives($options);
        $migrated = array_merge($migrated, $noindex_migrated);

        // Local SEO from AIOSEO
        $local_migrated = $this->migrate_aioseo_local_seo($options);
        $migrated = array_merge($migrated, $local_migrated);

        // Physical robots.txt fallback (if AIOSEO robots was empty)
        if (empty($options['tools']['robots']['rules'])) {
            $robots_migrated = $this->migrate_robots_from_physical_file();
            $migrated = array_merge($migrated, $robots_migrated);
        }

        // Taxonomy term meta from AIOSEO
        $tax_migrated = $this->migrate_aioseo_taxonomy_meta($options);
        $migrated = array_merge($migrated, $tax_migrated);

        return $migrated;
    }

    /**
     * Migrate Yoast sitemap settings
     */
    private function migrate_yoast_sitemap($titles) {
        $migrated = array();

        // Yoast stores sitemap on/off in wpseo option
        $wpseo = get_option('wpseo', array());
        $sitemap_enabled = !empty($wpseo['enable_xml_sitemap']);

        if ($sitemap_enabled) {
            update_option('seo_fury_sitemap_enabled', 1);

            // Collect enabled post types from Yoast titles options
            // Yoast uses noindex-{post_type}-wpseo: true means noindex (excluded from sitemap)
            $post_types = get_post_types(array('public' => true), 'names');
            $enabled_types = array();
            foreach ($post_types as $pt) {
                if ($pt === 'attachment') continue;
                $noindex = !empty($titles['noindex-' . $pt . '-wpseo']);
                if (!$noindex) {
                    $enabled_types[] = $pt;
                }
            }
            if (!empty($enabled_types)) {
                update_option('seo_fury_sitemap_post_types', $enabled_types);
            }

            // Collect enabled taxonomies
            $taxonomies = get_taxonomies(array('public' => true), 'names');
            $enabled_taxes = array();
            foreach ($taxonomies as $tax) {
                $noindex = !empty($titles['noindex-tax-' . $tax]);
                if (!$noindex) {
                    $enabled_taxes[] = $tax;
                }
            }
            if (!empty($enabled_taxes)) {
                update_option('seo_fury_sitemap_taxonomies', $enabled_taxes);
            }

            $migrated[] = __('Sitemap settings', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate Rank Math sitemap settings
     */
    private function migrate_rankmath_sitemap($general, $titles) {
        $migrated = array();
        $sitemap = get_option('rank-math-options-sitemap', array());

        if (!is_array($sitemap)) {
            $sitemap = array();
        }

        // Rank Math: items_per_page, include_images, pt_{type}_sitemap (on/off)
        $sitemap_enabled = !empty($sitemap['sitemap_enable']) || !empty($general['sitemap_enable']);

        // If Rank Math was active, it always has sitemaps on by default
        if (!empty($sitemap)) {
            update_option('seo_fury_sitemap_enabled', 1);

            // Post types
            $post_types = get_post_types(array('public' => true), 'names');
            $enabled_types = array();
            foreach ($post_types as $pt) {
                if ($pt === 'attachment') continue;
                // Rank Math: pt_{type}_sitemap = 'on'/'off', default 'on' for post/page
                $key = 'pt_' . $pt . '_sitemap';
                $is_on = isset($sitemap[$key]) ? ($sitemap[$key] === 'on') : in_array($pt, array('post', 'page'), true);
                if ($is_on) {
                    $enabled_types[] = $pt;
                }
            }
            if (!empty($enabled_types)) {
                update_option('seo_fury_sitemap_post_types', $enabled_types);
            }

            // Taxonomies
            $taxonomies = get_taxonomies(array('public' => true), 'names');
            $enabled_taxes = array();
            foreach ($taxonomies as $tax) {
                $key = 'tax_' . $tax . '_sitemap';
                $is_on = isset($sitemap[$key]) ? ($sitemap[$key] === 'on') : in_array($tax, array('category', 'post_tag'), true);
                if ($is_on) {
                    $enabled_taxes[] = $tax;
                }
            }
            if (!empty($enabled_taxes)) {
                update_option('seo_fury_sitemap_taxonomies', $enabled_taxes);
            }

            // Include images
            if (isset($sitemap['include_images'])) {
                update_option('seo_fury_sitemap_include_images', $sitemap['include_images'] === 'on' ? 1 : 0);
            }

            // Excluded posts
            $exclude_posts = array();
            foreach ($post_types as $pt) {
                $key = 'pt_' . $pt . '_sitemap_exclude';
                if (!empty($sitemap[$key])) {
                    $exclude_posts[] = sanitize_textarea_field($sitemap[$key]);
                }
            }

            $migrated[] = __('Sitemap settings', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate SEOPress sitemap settings
     */
    private function migrate_seopress_sitemap() {
        $migrated = array();
        $xml_options = get_option('seopress_xml_sitemap_option_name', array());

        if (!is_array($xml_options)) {
            $xml_options = array();
        }

        $sitemap_enabled = !empty($xml_options['seopress_xml_sitemap_general_enable']);

        if ($sitemap_enabled) {
            update_option('seo_fury_sitemap_enabled', 1);

            // Post types — SEOPress: seopress_xml_sitemap_post_types_list[post_type][include] = '1'
            $pt_list = isset($xml_options['seopress_xml_sitemap_post_types_list']) ? $xml_options['seopress_xml_sitemap_post_types_list'] : array();
            if (is_array($pt_list)) {
                $enabled_types = array();
                foreach ($pt_list as $pt => $data) {
                    if ($pt === 'attachment') continue;
                    if (!empty($data['include'])) {
                        $enabled_types[] = $pt;
                    }
                }
                if (!empty($enabled_types)) {
                    update_option('seo_fury_sitemap_post_types', $enabled_types);
                }
            }

            // Taxonomies — SEOPress: seopress_xml_sitemap_taxonomies_list[taxonomy][include] = '1'
            $tax_list = isset($xml_options['seopress_xml_sitemap_taxonomies_list']) ? $xml_options['seopress_xml_sitemap_taxonomies_list'] : array();
            if (is_array($tax_list)) {
                $enabled_taxes = array();
                foreach ($tax_list as $tax => $data) {
                    if (!empty($data['include'])) {
                        $enabled_taxes[] = $tax;
                    }
                }
                if (!empty($enabled_taxes)) {
                    update_option('seo_fury_sitemap_taxonomies', $enabled_taxes);
                }
            }

            // Images in sitemap
            if (!empty($xml_options['seopress_xml_sitemap_img_enable'])) {
                update_option('seo_fury_sitemap_include_images', 1);
            }

            $migrated[] = __('Sitemap settings', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate AIOSEO sitemap settings
     */
    private function migrate_aioseo_sitemap($options) {
        $migrated = array();

        if (!is_array($options)) {
            return $migrated;
        }

        $sitemap = $options['sitemap'] ?? array();
        $general = $sitemap['general'] ?? array();

        $sitemap_enabled = !empty($general['enable']);

        if ($sitemap_enabled) {
            update_option('seo_fury_sitemap_enabled', 1);

            // Post types — AIOSEO: sitemap.general.postTypes.included or postTypes.all = true
            $pt_config = $general['postTypes'] ?? array();
            $all_types = !empty($pt_config['all']);
            if ($all_types) {
                $post_types = get_post_types(array('public' => true), 'names');
                $enabled_types = array_values(array_diff($post_types, array('attachment')));
            } elseif (!empty($pt_config['included']) && is_array($pt_config['included'])) {
                $enabled_types = array_map('sanitize_text_field', $pt_config['included']);
            } else {
                $enabled_types = array('post', 'page');
            }
            if (!empty($enabled_types)) {
                update_option('seo_fury_sitemap_post_types', $enabled_types);
            }

            // Taxonomies — AIOSEO: sitemap.general.taxonomies.included or all = true
            $tax_config = $general['taxonomies'] ?? array();
            $all_taxes = !empty($tax_config['all']);
            if ($all_taxes) {
                $taxonomies = get_taxonomies(array('public' => true), 'names');
                $enabled_taxes = array_values($taxonomies);
            } elseif (!empty($tax_config['included']) && is_array($tax_config['included'])) {
                $enabled_taxes = array_map('sanitize_text_field', $tax_config['included']);
            } else {
                $enabled_taxes = array('category', 'post_tag');
            }
            if (!empty($enabled_taxes)) {
                update_option('seo_fury_sitemap_taxonomies', $enabled_taxes);
            }

            $migrated[] = __('Sitemap settings', 'seo-fury');
        }

        return $migrated;
    }

    // =========================================================================
    // Social Settings Migration
    // =========================================================================

    /**
     * Migrate Yoast social settings
     */
    private function migrate_yoast_social($social) {
        $migrated = array();

        // Default OG image
        if (!empty($social['og_default_image']) && empty(get_option('seo_fury_default_og_image', ''))) {
            update_option('seo_fury_default_og_image', esc_url_raw($social['og_default_image']));
            $migrated[] = __('Default Open Graph image', 'seo-fury');
        }

        // Twitter site handle
        if (!empty($social['twitter_site']) && empty(get_option('seo_fury_twitter_site_handle', ''))) {
            $handle = ltrim($social['twitter_site'], '@');
            update_option('seo_fury_twitter_site_handle', sanitize_text_field('@' . $handle));
            $migrated[] = __('Twitter site handle', 'seo-fury');
        }

        // Twitter card type
        if (!empty($social['twitter_card_type']) && empty(get_option('seo_fury_twitter_card_type', ''))) {
            update_option('seo_fury_twitter_card_type', sanitize_text_field($social['twitter_card_type']));
            $migrated[] = __('Twitter card type', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate Rank Math social settings
     */
    private function migrate_rankmath_social($general, $titles) {
        $migrated = array();

        // Default OG image from knowledge graph logo
        if (!empty($general['knowledgegraph_logo']) && empty(get_option('seo_fury_default_og_image', ''))) {
            update_option('seo_fury_default_og_image', esc_url_raw($general['knowledgegraph_logo']));
            $migrated[] = __('Default Open Graph image', 'seo-fury');
        }

        // Twitter handle from social URL
        if (!empty($general['social_url_twitter']) && empty(get_option('seo_fury_twitter_site_handle', ''))) {
            $tw_url = $general['social_url_twitter'];
            $handle = basename(rtrim($tw_url, '/'));
            if (!empty($handle)) {
                update_option('seo_fury_twitter_site_handle', sanitize_text_field('@' . $handle));
                $migrated[] = __('Twitter site handle', 'seo-fury');
            }
        }

        // Twitter card type
        if (!empty($titles['twitter_card_type']) && empty(get_option('seo_fury_twitter_card_type', ''))) {
            update_option('seo_fury_twitter_card_type', sanitize_text_field($titles['twitter_card_type']));
            $migrated[] = __('Twitter card type', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate SEOPress social settings
     */
    private function migrate_seopress_social() {
        $migrated = array();
        $social = get_option('seopress_social_option_name', array());

        if (!is_array($social)) {
            return $migrated;
        }

        // Default OG image
        if (!empty($social['seopress_social_facebook_og_default_image']) && empty(get_option('seo_fury_default_og_image', ''))) {
            update_option('seo_fury_default_og_image', esc_url_raw($social['seopress_social_facebook_og_default_image']));
            $migrated[] = __('Default Open Graph image', 'seo-fury');
        }

        // Twitter handle
        if (!empty($social['seopress_social_accounts_twitter']) && empty(get_option('seo_fury_twitter_site_handle', ''))) {
            $tw = $social['seopress_social_accounts_twitter'];
            // Could be URL or @handle
            if (strpos($tw, 'twitter.com') !== false || strpos($tw, 'x.com') !== false) {
                $tw = basename(rtrim($tw, '/'));
            }
            $handle = ltrim($tw, '@');
            if (!empty($handle)) {
                update_option('seo_fury_twitter_site_handle', sanitize_text_field('@' . $handle));
                $migrated[] = __('Twitter site handle', 'seo-fury');
            }
        }

        // Twitter card type
        if (!empty($social['seopress_social_twitter_card_og']) && empty(get_option('seo_fury_twitter_card_type', ''))) {
            update_option('seo_fury_twitter_card_type', sanitize_text_field($social['seopress_social_twitter_card_og']));
            $migrated[] = __('Twitter card type', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate AIOSEO social settings
     */
    private function migrate_aioseo_social($options) {
        $migrated = array();

        if (!is_array($options)) {
            return $migrated;
        }

        $social = $options['social'] ?? array();

        // Default OG image
        $og_image = $social['facebook']['general']['defaultImagePosts'] ?? '';
        if (!empty($og_image) && empty(get_option('seo_fury_default_og_image', ''))) {
            update_option('seo_fury_default_og_image', esc_url_raw($og_image));
            $migrated[] = __('Default Open Graph image', 'seo-fury');
        }

        // Twitter card type
        $card_type = $social['twitter']['general']['defaultCardType'] ?? '';
        if (!empty($card_type) && empty(get_option('seo_fury_twitter_card_type', ''))) {
            update_option('seo_fury_twitter_card_type', sanitize_text_field($card_type));
            $migrated[] = __('Twitter card type', 'seo-fury');
        }

        // Twitter handle from profiles
        $twitter_url = $social['profiles']['urls']['twitterUrl'] ?? '';
        if (!empty($twitter_url) && empty(get_option('seo_fury_twitter_site_handle', ''))) {
            $handle = basename(rtrim($twitter_url, '/'));
            if (!empty($handle)) {
                update_option('seo_fury_twitter_site_handle', sanitize_text_field('@' . $handle));
                $migrated[] = __('Twitter site handle', 'seo-fury');
            }
        }

        return $migrated;
    }

    // =========================================================================
    // Noindex Archives Migration
    // =========================================================================

    /**
     * Migrate Yoast noindex archive settings
     */
    private function migrate_yoast_noindex_archives($titles) {
        $migrated = array();
        $any_migrated = false;

        // Per-taxonomy noindex: Yoast uses noindex-tax-{taxonomy} = true
        $taxonomies = get_taxonomies(array('public' => true), 'names');
        foreach ($taxonomies as $tax) {
            if (!empty($titles['noindex-tax-' . $tax])) {
                update_option('seo_fury_tax_robots_enabled_' . $tax, 1);
                update_option('seo_fury_tax_robots_noindex_' . $tax, 1);
                $any_migrated = true;
            }
        }

        // Per-post-type archive noindex: Yoast uses noindex-ptarchive-{post_type}
        $post_types = get_post_types(array('public' => true, 'has_archive' => true), 'names');
        foreach ($post_types as $pt) {
            if (!empty($titles['noindex-ptarchive-' . $pt])) {
                update_option('seo_fury_pt_robots_noindex_' . $pt, 1);
                $any_migrated = true;
            }
        }

        if ($any_migrated) {
            $migrated[] = __('Noindex archive settings', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate Rank Math noindex archive settings
     */
    private function migrate_rankmath_noindex_archives($titles) {
        $migrated = array();
        $any_migrated = false;

        // Per-taxonomy noindex: Rank Math uses tax_{tax}_custom_robots = 'on', tax_{tax}_robots = array('noindex', ...)
        $taxonomies = get_taxonomies(array('public' => true), 'names');
        foreach ($taxonomies as $tax) {
            $custom = !empty($titles['tax_' . $tax . '_custom_robots']) && $titles['tax_' . $tax . '_custom_robots'] === 'on';
            if ($custom) {
                $robots = isset($titles['tax_' . $tax . '_robots']) ? (array) $titles['tax_' . $tax . '_robots'] : array();
                if (in_array('noindex', $robots, true)) {
                    update_option('seo_fury_tax_robots_enabled_' . $tax, 1);
                    update_option('seo_fury_tax_robots_noindex_' . $tax, 1);
                    $any_migrated = true;
                }
                if (in_array('nofollow', $robots, true)) {
                    update_option('seo_fury_tax_robots_enabled_' . $tax, 1);
                    update_option('seo_fury_tax_robots_nofollow_' . $tax, 1);
                    $any_migrated = true;
                }
            }
        }

        // Per-post-type archive noindex
        $post_types = get_post_types(array('public' => true), 'names');
        foreach ($post_types as $pt) {
            $custom = !empty($titles['pt_' . $pt . '_custom_robots']) && $titles['pt_' . $pt . '_custom_robots'] === 'on';
            if ($custom) {
                $robots = isset($titles['pt_' . $pt . '_robots']) ? (array) $titles['pt_' . $pt . '_robots'] : array();
                if (in_array('noindex', $robots, true)) {
                    update_option('seo_fury_pt_robots_noindex_' . $pt, 1);
                    $any_migrated = true;
                }
            }
        }

        if ($any_migrated) {
            $migrated[] = __('Noindex archive settings', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate SEOPress noindex archive settings
     */
    private function migrate_seopress_noindex_archives($titles) {
        $migrated = array();
        $any_migrated = false;

        // Per-taxonomy noindex from SEOPress titles
        if (!empty($titles['seopress_titles_tax_titles']) && is_array($titles['seopress_titles_tax_titles'])) {
            foreach ($titles['seopress_titles_tax_titles'] as $tax => $data) {
                if (!empty($data['noindex'])) {
                    update_option('seo_fury_tax_robots_enabled_' . $tax, 1);
                    update_option('seo_fury_tax_robots_noindex_' . $tax, 1);
                    $any_migrated = true;
                }
                if (!empty($data['nofollow'])) {
                    update_option('seo_fury_tax_robots_enabled_' . $tax, 1);
                    update_option('seo_fury_tax_robots_nofollow_' . $tax, 1);
                    $any_migrated = true;
                }
            }
        }

        // Noindex empty categories
        if (!empty($titles['seopress_titles_noindex_empty_cat'])) {
            update_option('seo_fury_noindex_empty_archives', 1);
            $any_migrated = true;
        }

        if ($any_migrated) {
            $migrated[] = __('Noindex archive settings', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate AIOSEO noindex archive settings
     */
    private function migrate_aioseo_noindex_archives($options) {
        $migrated = array();

        if (!is_array($options)) {
            return $migrated;
        }

        $any_migrated = false;
        $taxonomies = $options['searchAppearance']['taxonomies'] ?? array();

        if (is_array($taxonomies)) {
            foreach ($taxonomies as $tax => $data) {
                if (!is_array($data)) continue;
                $noindex = $data['advanced']['robotsMeta']['noindex'] ?? false;
                if ($noindex) {
                    update_option('seo_fury_tax_robots_enabled_' . $tax, 1);
                    update_option('seo_fury_tax_robots_noindex_' . $tax, 1);
                    $any_migrated = true;
                }
            }
        }

        // Post type archives
        $archives = $options['searchAppearance']['archives'] ?? array();
        if (is_array($archives)) {
            foreach ($archives as $pt => $data) {
                if (!is_array($data)) continue;
                $noindex = $data['advanced']['robotsMeta']['noindex'] ?? false;
                if ($noindex) {
                    update_option('seo_fury_pt_robots_noindex_' . $pt, 1);
                    $any_migrated = true;
                }
            }
        }

        if ($any_migrated) {
            $migrated[] = __('Noindex archive settings', 'seo-fury');
        }

        return $migrated;
    }

    // =========================================================================
    // Breadcrumbs Migration
    // =========================================================================

    /**
     * Migrate Yoast breadcrumb settings
     */
    private function migrate_yoast_breadcrumbs() {
        $migrated = array();
        $titles = get_option('wpseo_titles', array());

        if (!is_array($titles)) {
            return $migrated;
        }

        $enabled = !empty($titles['breadcrumbs-enable']);
        if (!$enabled) {
            return $migrated;
        }

        update_option('seo_fury_breadcrumbs_enabled', 1);

        if (!empty($titles['breadcrumbs-sep'])) {
            update_option('seo_fury_breadcrumbs_separator', 'custom');
            update_option('seo_fury_breadcrumbs_separator_custom', sanitize_text_field($titles['breadcrumbs-sep']));
        }

        if (!empty($titles['breadcrumbs-home'])) {
            update_option('seo_fury_breadcrumbs_home_label', sanitize_text_field($titles['breadcrumbs-home']));
            update_option('seo_fury_breadcrumbs_show_home', 1);
        }

        if (!empty($titles['breadcrumbs-prefix'])) {
            update_option('seo_fury_breadcrumbs_prefix', sanitize_text_field($titles['breadcrumbs-prefix']));
        }

        if (!empty($titles['breadcrumbs-searchprefix'])) {
            update_option('seo_fury_breadcrumbs_search_format', sanitize_text_field($titles['breadcrumbs-searchprefix'] . ' %s'));
        }

        if (!empty($titles['breadcrumbs-404crumb'])) {
            update_option('seo_fury_breadcrumbs_404_label', sanitize_text_field($titles['breadcrumbs-404crumb']));
        }

        $migrated[] = __('Breadcrumb settings', 'seo-fury');
        return $migrated;
    }

    /**
     * Migrate Rank Math breadcrumb settings
     */
    private function migrate_rankmath_breadcrumbs($general) {
        $migrated = array();

        if (!is_array($general)) {
            return $migrated;
        }

        $enabled = !empty($general['breadcrumbs']) && $general['breadcrumbs'] === 'on';
        if (!$enabled) {
            return $migrated;
        }

        update_option('seo_fury_breadcrumbs_enabled', 1);

        if (!empty($general['breadcrumbs_separator'])) {
            update_option('seo_fury_breadcrumbs_separator', 'custom');
            update_option('seo_fury_breadcrumbs_separator_custom', sanitize_text_field($general['breadcrumbs_separator']));
        }

        if (!empty($general['breadcrumbs_home_label'])) {
            update_option('seo_fury_breadcrumbs_home_label', sanitize_text_field($general['breadcrumbs_home_label']));
        }

        $show_home = !empty($general['breadcrumbs_home']) && $general['breadcrumbs_home'] === 'on';
        update_option('seo_fury_breadcrumbs_show_home', $show_home ? 1 : 0);

        if (!empty($general['breadcrumbs_prefix'])) {
            update_option('seo_fury_breadcrumbs_prefix', sanitize_text_field($general['breadcrumbs_prefix']));
        }

        if (!empty($general['breadcrumbs_archive_format'])) {
            update_option('seo_fury_breadcrumbs_archive_format', sanitize_text_field($general['breadcrumbs_archive_format']));
        }

        if (!empty($general['breadcrumbs_search_format'])) {
            update_option('seo_fury_breadcrumbs_search_format', sanitize_text_field($general['breadcrumbs_search_format']));
        }

        if (!empty($general['breadcrumbs_404_label'])) {
            update_option('seo_fury_breadcrumbs_404_label', sanitize_text_field($general['breadcrumbs_404_label']));
        }

        $migrated[] = __('Breadcrumb settings', 'seo-fury');
        return $migrated;
    }

    // =========================================================================
    // Local SEO Migration
    // =========================================================================

    /**
     * Migrate Rank Math knowledge graph / local SEO settings
     */
    private function migrate_rankmath_local_seo($titles) {
        $migrated = array();

        if (!is_array($titles)) {
            return $migrated;
        }

        $has_data = false;

        // Business/Organization name
        if (!empty($titles['knowledgegraph_name']) && empty(get_option('seo_fury_local_name', ''))) {
            update_option('seo_fury_local_name', sanitize_text_field($titles['knowledgegraph_name']));
            $has_data = true;
        }

        // Logo
        if (!empty($titles['knowledgegraph_logo']) && empty(get_option('seo_fury_local_logo', ''))) {
            update_option('seo_fury_local_logo', esc_url_raw($titles['knowledgegraph_logo']));
            $has_data = true;
        }

        // URL
        if (!empty($titles['knowledgegraph_url']) && empty(get_option('seo_fury_local_url', ''))) {
            update_option('seo_fury_local_url', esc_url_raw($titles['knowledgegraph_url']));
            $has_data = true;
        }

        // Phone
        if (!empty($titles['knowledgegraph_phone']) && empty(get_option('seo_fury_local_phone', ''))) {
            update_option('seo_fury_local_phone', sanitize_text_field($titles['knowledgegraph_phone']));
            $has_data = true;
        }

        // Email
        if (!empty($titles['knowledgegraph_email']) && empty(get_option('seo_fury_local_email', ''))) {
            update_option('seo_fury_local_email', sanitize_email($titles['knowledgegraph_email']));
            $has_data = true;
        }

        // Business type mapping
        if (!empty($titles['knowledgegraph_type']) && $titles['knowledgegraph_type'] === 'company') {
            if (empty(get_option('seo_fury_local_type', ''))) {
                update_option('seo_fury_local_type', 'Organization');
            }
        }

        // Local business address (from Rank Math Local if available)
        $local = get_option('rank-math-options-general', array());
        if (is_array($local)) {
            if (!empty($local['local_address_street']) && empty(get_option('seo_fury_local_street', ''))) {
                update_option('seo_fury_local_street', sanitize_text_field($local['local_address_street']));
                $has_data = true;
            }
            if (!empty($local['local_address_locality']) && empty(get_option('seo_fury_local_city', ''))) {
                update_option('seo_fury_local_city', sanitize_text_field($local['local_address_locality']));
                $has_data = true;
            }
            if (!empty($local['local_address_region']) && empty(get_option('seo_fury_local_region', ''))) {
                update_option('seo_fury_local_region', sanitize_text_field($local['local_address_region']));
                $has_data = true;
            }
            if (!empty($local['local_address_postalcode']) && empty(get_option('seo_fury_local_postal', ''))) {
                update_option('seo_fury_local_postal', sanitize_text_field($local['local_address_postalcode']));
                $has_data = true;
            }
            if (!empty($local['local_address_country']) && empty(get_option('seo_fury_local_country', ''))) {
                update_option('seo_fury_local_country', sanitize_text_field($local['local_address_country']));
                $has_data = true;
            }
        }

        if ($has_data) {
            update_option('seo_fury_local_enabled', 1);
            $migrated[] = __('Local SEO / Organization settings', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate AIOSEO local business settings
     */
    private function migrate_aioseo_local_seo($options) {
        $migrated = array();

        if (!is_array($options)) {
            return $migrated;
        }

        $has_data = false;

        // AIOSEO stores organization info in searchAppearance.global.schema
        $schema = $options['searchAppearance']['global']['schema'] ?? array();

        if (!empty($schema['organizationName']) && empty(get_option('seo_fury_local_name', ''))) {
            update_option('seo_fury_local_name', sanitize_text_field($schema['organizationName']));
            $has_data = true;
        }

        if (!empty($schema['organizationLogo']) && empty(get_option('seo_fury_local_logo', ''))) {
            update_option('seo_fury_local_logo', esc_url_raw($schema['organizationLogo']));
            $has_data = true;
        }

        if (!empty($schema['phone']) && empty(get_option('seo_fury_local_phone', ''))) {
            update_option('seo_fury_local_phone', sanitize_text_field($schema['phone']));
            $has_data = true;
        }

        // Local Business from AIOSEO Local plugin
        $local = $options['localBusiness'] ?? array();
        if (is_array($local) && !empty($local['locations'])) {
            $location = is_array($local['locations']) ? reset($local['locations']) : array();
            $biz = $location['business'] ?? array();

            if (!empty($biz['name']) && empty(get_option('seo_fury_local_name', ''))) {
                update_option('seo_fury_local_name', sanitize_text_field($biz['name']));
                $has_data = true;
            }
            if (!empty($biz['phone']) && empty(get_option('seo_fury_local_phone', ''))) {
                update_option('seo_fury_local_phone', sanitize_text_field($biz['phone']));
                $has_data = true;
            }
            if (!empty($biz['email']) && empty(get_option('seo_fury_local_email', ''))) {
                update_option('seo_fury_local_email', sanitize_email($biz['email']));
                $has_data = true;
            }
            if (!empty($biz['url']) && empty(get_option('seo_fury_local_url', ''))) {
                update_option('seo_fury_local_url', esc_url_raw($biz['url']));
                $has_data = true;
            }
            if (!empty($biz['businessType']) && empty(get_option('seo_fury_local_type', ''))) {
                update_option('seo_fury_local_type', sanitize_text_field($biz['businessType']));
                $has_data = true;
            }

            $address = $biz['address'] ?? array();
            if (!empty($address['streetAddress']) && empty(get_option('seo_fury_local_street', ''))) {
                update_option('seo_fury_local_street', sanitize_text_field($address['streetAddress']));
                $has_data = true;
            }
            if (!empty($address['city']) && empty(get_option('seo_fury_local_city', ''))) {
                update_option('seo_fury_local_city', sanitize_text_field($address['city']));
                $has_data = true;
            }
            if (!empty($address['state']) && empty(get_option('seo_fury_local_region', ''))) {
                update_option('seo_fury_local_region', sanitize_text_field($address['state']));
                $has_data = true;
            }
            if (!empty($address['zipCode']) && empty(get_option('seo_fury_local_postal', ''))) {
                update_option('seo_fury_local_postal', sanitize_text_field($address['zipCode']));
                $has_data = true;
            }
            if (!empty($address['country']) && empty(get_option('seo_fury_local_country', ''))) {
                update_option('seo_fury_local_country', sanitize_text_field($address['country']));
                $has_data = true;
            }
        }

        if ($has_data) {
            update_option('seo_fury_local_enabled', 1);
            $migrated[] = __('Local SEO / Organization settings', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate Rank Math template tags to SEO Fury format
     */
    private function convert_rankmath_tags($value) {
        $replacements = array(
            '%title%'       => '%title%',
            '%sitename%'    => '%sitename%',
            '%sep%'         => '%sep%',
            '%excerpt%'     => '%excerpt%',
            '%date%'        => '%date%',
            '%category%'    => '%category%',
            '%tag%'         => '%tag%',
            '%name%'        => '%name%',
            '%page%'        => '%page%',
            '%currentyear%' => '%currentyear%',
            '%currentdate%' => '%currentdate%',
            '%sitedesc%'    => '%sitedesc%',
            '%pt_single%'   => '%pt_single%',
            '%search_query%' => '%search_query%',
        );
        return str_replace(array_keys($replacements), array_values($replacements), $value);
    }

    /**
     * Migrate SEOPress template tags to SEO Fury format
     */
    private function convert_seopress_tags($value) {
        $replacements = array(
            '%%sitetitle%%'   => '%sitename%',
            '%%tagline%%'     => '%sitedesc%',
            '%%post_title%%'  => '%title%',
            '%%post_excerpt%%' => '%excerpt%',
            '%%post_date%%'   => '%date%',
            '%%post_author%%' => '%name%',
            '%%sep%%'         => '%sep%',
            '%%page%%'        => '%page%',
            '%%currentyear%%' => '%currentyear%',
            '%%currentdate%%' => '%currentdate%',
            '%%term_title%%'  => '%term%',
            '%%_category_title%%' => '%category%',
            '%%tag_title%%'   => '%tag%',
            '%%search_keywords%%' => '%searchquery%',
        );
        return str_replace(array_keys($replacements), array_values($replacements), $value);
    }

    /**
     * Import Yoast Premium redirects
     */
    private function migrate_redirects_array($redirects, $source) {
        global $wpdb;
        $core = SEO_Fury_Core::get_instance();
        $table = $wpdb->prefix . 'seo_redirects';

        // Check if table exists
        if (!$wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table))) {
            return 0;
        }

        $count = 0;
        foreach ($redirects as $redirect) {
            $source_url = '';
            $target_url = '';
            $type = 301;

            if ($source === 'yoast') {
                $source_url = !empty($redirect['origin']) ? $redirect['origin'] : (!empty($redirect['url']) ? $redirect['url'] : '');
                $target_url = !empty($redirect['url']) ? $redirect['url'] : (!empty($redirect['target']) ? $redirect['target'] : '');
                $type = !empty($redirect['type']) ? intval($redirect['type']) : 301;
                // Yoast Premium format: origin = source, url = target
                if (!empty($redirect['origin'])) {
                    $source_url = $redirect['origin'];
                    $target_url = $redirect['url'];
                }
            }

            if (empty($source_url) || empty($target_url)) {
                continue;
            }

            // Check for duplicate
            $exists = $wpdb->get_var($wpdb->prepare(
                "SELECT id FROM {$table} WHERE source_url = %s",
                $source_url
            ));
            if ($exists) {
                continue;
            }

            $wpdb->insert($table, array(
                'source_url'    => sanitize_text_field($source_url),
                'target_url'    => sanitize_text_field($target_url),
                'redirect_type' => in_array($type, array(301, 302, 307, 410), true) ? $type : 301,
                'active'        => 1,
                'hits'          => 0,
            ), array('%s', '%s', '%d', '%d', '%d'));

            if ($wpdb->insert_id) {
                $count++;
            }
        }

        return $count;
    }

    /**
     * Migrate Rank Math redirects from their DB table
     */
    private function migrate_rankmath_redirects() {
        global $wpdb;
        $rm_table = $wpdb->prefix . 'rank_math_redirections';
        $sf_table = $wpdb->prefix . 'seo_redirects';

        // Check if both tables exist
        if (!$wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $rm_table))) {
            return 0;
        }
        if (!$wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $sf_table))) {
            return 0;
        }

        $redirects = $wpdb->get_results("SELECT * FROM {$rm_table} WHERE status = 'active'");
        if (empty($redirects)) {
            return 0;
        }

        $count = 0;
        foreach ($redirects as $redirect) {
            $sources = maybe_unserialize($redirect->sources);
            if (!is_array($sources) || empty($sources)) {
                continue;
            }

            $source_url = $sources[0]['pattern'] ?? '';
            $target_url = $redirect->url_to ?? '';
            $type = !empty($redirect->header_code) ? intval($redirect->header_code) : 301;

            if (empty($source_url) || empty($target_url)) {
                continue;
            }

            // Check for duplicate
            $exists = $wpdb->get_var($wpdb->prepare(
                "SELECT id FROM {$sf_table} WHERE source_url = %s",
                $source_url
            ));
            if ($exists) {
                continue;
            }

            $wpdb->insert($sf_table, array(
                'source_url'    => sanitize_text_field($source_url),
                'target_url'    => sanitize_text_field($target_url),
                'redirect_type' => in_array($type, array(301, 302, 307, 410), true) ? $type : 301,
                'active'        => 1,
                'hits'          => intval($redirect->hits ?? 0),
            ), array('%s', '%s', '%d', '%d', '%d'));

            if ($wpdb->insert_id) {
                $count++;
            }
        }

        return $count;
    }

    /**
     * Migrate AIOSEO redirects from their DB table
     */
    private function migrate_aioseo_redirects() {
        global $wpdb;
        $aio_table = $wpdb->prefix . 'aioseo_redirects';
        $sf_table = $wpdb->prefix . 'seo_redirects';

        if (!$wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $aio_table))) {
            return 0;
        }
        if (!$wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $sf_table))) {
            return 0;
        }

        $redirects = $wpdb->get_results("SELECT * FROM {$aio_table} WHERE enabled = 1");
        if (empty($redirects)) {
            return 0;
        }

        $count = 0;
        foreach ($redirects as $redirect) {
            $source_url = $redirect->source_url ?? '';
            $target_url = $redirect->target_url ?? '';
            $type = !empty($redirect->type) ? intval($redirect->type) : 301;

            if (empty($source_url) || empty($target_url)) {
                continue;
            }

            $exists = $wpdb->get_var($wpdb->prepare(
                "SELECT id FROM {$sf_table} WHERE source_url = %s",
                $source_url
            ));
            if ($exists) {
                continue;
            }

            $wpdb->insert($sf_table, array(
                'source_url'    => sanitize_text_field($source_url),
                'target_url'    => sanitize_text_field($target_url),
                'redirect_type' => in_array($type, array(301, 302, 307, 410), true) ? $type : 301,
                'active'        => 1,
                'hits'          => intval($redirect->hits ?? 0),
            ), array('%s', '%s', '%d', '%d', '%d'));

            if ($wpdb->insert_id) {
                $count++;
            }
        }

        return $count;
    }

    /**
     * Migrate SEOPress redirects from their CPT
     */
    private function migrate_seopress_redirects() {
        global $wpdb;
        $sf_table = $wpdb->prefix . 'seo_redirects';

        if (!$wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $sf_table))) {
            return 0;
        }

        $redirect_posts = get_posts(array(
            'post_type'      => 'seopress_404',
            'post_status'    => 'publish',
            'posts_per_page' => -1,
            'meta_query'     => array(
                array(
                    'key'     => '_seopress_redirections_enabled',
                    'value'   => 'yes',
                    'compare' => '=',
                ),
            ),
        ));

        if (empty($redirect_posts)) {
            return 0;
        }

        $count = 0;
        foreach ($redirect_posts as $rp) {
            $source_url = $rp->post_title;
            $target_url = get_post_meta($rp->ID, '_seopress_redirections_value', true);
            $type = get_post_meta($rp->ID, '_seopress_redirections_type', true);
            $type = !empty($type) ? intval($type) : 301;

            if (empty($source_url) || empty($target_url)) {
                continue;
            }

            $exists = $wpdb->get_var($wpdb->prepare(
                "SELECT id FROM {$sf_table} WHERE source_url = %s",
                $source_url
            ));
            if ($exists) {
                continue;
            }

            $wpdb->insert($sf_table, array(
                'source_url'    => sanitize_text_field($source_url),
                'target_url'    => sanitize_text_field($target_url),
                'redirect_type' => in_array($type, array(301, 302, 307, 410), true) ? $type : 301,
                'active'        => 1,
                'hits'          => 0,
            ), array('%s', '%s', '%d', '%d', '%d'));

            if ($wpdb->insert_id) {
                $count++;
            }
        }

        return $count;
    }

    // =========================================================================
    // AJAX Handlers
    // =========================================================================

    /**
     * AJAX: Detect available SEO plugins
     */
    public function ajax_detect() {
        check_ajax_referer('seo_fury_migration_wizard', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Unauthorized'));
        }

        $detected = $this->detect_plugins();
        wp_send_json_success(array('plugins' => $detected));
    }

    /**
     * AJAX: Migrate a batch of posts
     */
    public function ajax_migrate_batch() {
        check_ajax_referer('seo_fury_migration_wizard', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Unauthorized'));
        }

        $plugin = isset($_POST['plugin']) ? sanitize_text_field($_POST['plugin']) : '';
        $offset = isset($_POST['offset']) ? absint($_POST['offset']) : 0;
        $batch  = isset($_POST['batch']) ? absint($_POST['batch']) : 50;

        if (!isset($this->supported_plugins[$plugin])) {
            wp_send_json_error(array('message' => 'Invalid plugin'));
        }

        $result = $this->migrate_batch($plugin, $offset, $batch);
        wp_send_json_success($result);
    }

    /**
     * AJAX: Migrate global settings
     */
    public function ajax_migrate_settings() {
        check_ajax_referer('seo_fury_migration_wizard', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Unauthorized'));
        }

        $plugin = isset($_POST['plugin']) ? sanitize_text_field($_POST['plugin']) : '';

        if (!isset($this->supported_plugins[$plugin])) {
            wp_send_json_error(array('message' => 'Invalid plugin'));
        }

        $migrated = $this->migrate_global_settings($plugin);

        // Track this plugin as migration-completed
        $completed = get_option('seo_fury_migration_completed', array());
        if (!is_array($completed)) {
            $completed = array();
        }
        if (!in_array($plugin, $completed, true)) {
            $completed[] = $plugin;
            update_option('seo_fury_migration_completed', $completed);
        }

        wp_send_json_success(array('migrated' => $migrated));
    }

    /**
     * AJAX: Dismiss the migration wizard notice
     */
    public function ajax_dismiss() {
        check_ajax_referer('seo_fury_migration_wizard', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(array('message' => 'Unauthorized'));
        }

        update_option('seo_fury_migration_wizard_dismissed', 1);
        wp_send_json_success();
    }

    // =========================================================================
    // Admin Notice
    // =========================================================================

    /**
     * Show admin notice when migration data is detected
     */
    public function render_admin_notice() {
        // Don't show if dismissed
        if (get_option('seo_fury_migration_wizard_dismissed', 0)) {
            return;
        }

        // Only show if this is a fresh activation (flag set in seo-fury.php)
        if (!get_option('seo_fury_show_migration_wizard', 0)) {
            return;
        }

        // Only show on our plugin pages or the dashboard
        $screen = get_current_screen();
        if (!$screen) {
            return;
        }

        $allowed_screens = array('dashboard', 'plugins', 'toplevel_page_seo-fury');
        if (!in_array($screen->id, $allowed_screens, true)) {
            return;
        }

        // Detect if there's anything to migrate
        $detected = $this->detect_plugins();
        if (empty($detected)) {
            // Nothing to migrate — dismiss automatically
            update_option('seo_fury_migration_wizard_dismissed', 1);
            return;
        }

        // Separate active vs inactive plugins
        $active_plugins = array_filter($detected, function($d) { return !empty($d['is_active']); });
        $inactive_plugins = array_filter($detected, function($d) { return empty($d['is_active']); });

        // If only inactive plugins remain, check if all were already imported
        if (empty($active_plugins) && !empty($inactive_plugins)) {
            $already_imported = get_option('seo_fury_migration_completed', array());
            if (!is_array($already_imported)) {
                $already_imported = array();
            }
            $all_imported = true;
            foreach (array_keys($inactive_plugins) as $slug) {
                if (!in_array($slug, $already_imported, true)) {
                    $all_imported = false;
                    break;
                }
            }
            if ($all_imported) {
                update_option('seo_fury_migration_wizard_dismissed', 1);
                return;
            }
        }

        $brand = function_exists('seo_fury_get_brand_name') ? seo_fury_get_brand_name() : 'SEO Fury';

        // Detect active SSL plugins
        if (!function_exists('is_plugin_active')) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        $ssl_plugins = array(
            'really-simple-ssl/rlrsssl-really-simple-ssl.php'  => 'Really Simple SSL',
            'really-simple-ssl-pro/really-simple-ssl-pro.php'  => 'Really Simple SSL Pro',
            'wp-force-ssl/wp-force-ssl.php'                    => 'WP Force SSL',
            'ssl-insecure-content-fixer/ssl-insecure-content-fixer.php' => 'SSL Insecure Content Fixer',
            'one-click-ssl/flavor.php'                         => 'One Click SSL',
        );
        $active_ssl_names = array();
        foreach ($ssl_plugins as $ssl_file => $ssl_name) {
            if (is_plugin_active($ssl_file)) {
                $active_ssl_names[] = $ssl_name;
            }
        }

        // Determine notice style based on active/inactive
        $has_active = !empty($active_plugins);
        $notice_class = $has_active ? 'notice-warning' : 'notice-info';
        $notice_icon = $has_active ? '⚠️' : '🔄';
        $border_color = $has_active ? '#F59E0B' : '#6366F1';

        if ($has_active) {
            $active_names = wp_list_pluck($active_plugins, 'name');
            $notice_text = sprintf(
                /* translators: %s: comma-separated list of active plugin names wrapped in <strong> tags */
                __('SEO plugin conflict detected: %s is still active. Running two SEO plugins simultaneously can cause conflicts and duplicate meta tags. Import your data and deactivate the other plugin.', 'seo-fury'),
                '<strong>' . esc_html(implode(', ', $active_names)) . '</strong>'
            );
        } else {
            $inactive_names = wp_list_pluck($inactive_plugins, 'name');
            $notice_text = sprintf(
                /* translators: %s: comma-separated list of detected plugin names wrapped in <strong> tags */
                __('We found leftover SEO data from %s in your database. Would you like to import it?', 'seo-fury'),
                '<strong>' . esc_html(implode(', ', $inactive_names)) . '</strong>'
            );
        }
        ?>
        <div class="notice <?php echo esc_attr($notice_class); ?> seo-fury-migration-notice" style="padding: 12px 15px; border-left-color: <?php echo esc_attr($border_color); ?>;">
            <div style="display: flex; align-items: center; gap: 12px;">
                <span style="font-size: 28px;"><?php echo wp_kses_post( $notice_icon ); ?></span>
                <div style="flex: 1;">
                    <p style="margin: 0 0 4px; font-size: 14px;">
                        <strong><?php echo esc_html($brand); ?>:</strong>
                        <?php echo wp_kses_post( $notice_text ); ?>
                    </p>
                    <?php if (!empty($active_ssl_names)) : ?>
                    <p style="margin: 2px 0 4px; font-size: 13px; color: var(--sf-gray-700, #374151);">
                        <?php
                        echo wp_kses_post( sprintf(
                            /* translators: %1$s: SSL plugin name(s) wrapped in <strong> tags, %2$s: brand name */
                            __('You can also deactivate %1$s — %2$s already includes SSL/HTTPS redirect functionality.', 'seo-fury'),
                            '<strong>' . esc_html(implode(', ', $active_ssl_names)) . '</strong>',
                            esc_html($brand)
                        ) );
                        ?>
                    </p>
                    <?php endif; ?>
                    <p style="margin: 0; color: var(--sf-gray-500, #64748b); font-size: 12px;">
                        <?php esc_html_e('Your existing SEO Fury data will not be overwritten.', 'seo-fury'); ?>
                    </p>
                </div>
                <div style="display: flex; gap: 8px; flex-shrink: 0;">
                    <a href="<?php echo esc_url(admin_url('admin.php?page=seo-fury&tab=general&wizard=1')); ?>" class="button button-primary" style="background: #6366F1; border-color: #6366F1;">
                        <?php esc_html_e('Import SEO Data', 'seo-fury'); ?>
                    </a>
                    <button type="button" class="button seo-fury-dismiss-wizard">
                        <?php esc_html_e('Dismiss', 'seo-fury'); ?>
                    </button>
                </div>
            </div>
        </div>
        <script>
        jQuery(function($) {
            $('.seo-fury-dismiss-wizard').on('click', function() {
                var $notice = $(this).closest('.seo-fury-migration-notice');
                $.post(ajaxurl, {
                    action: 'seo_fury_wizard_dismiss',
                    nonce: '<?php echo esc_attr( wp_create_nonce('seo_fury_migration_wizard') ); ?>'
                });
                $notice.fadeOut();
            });
        });
        </script>
        <?php
    }

    /**
     * AJAX: Deactivate the source SEO plugin after migration
     */
    public function ajax_deactivate_plugin() {
        check_ajax_referer('seo_fury_migration_wizard', 'nonce');

        if (!current_user_can('activate_plugins')) {
            wp_send_json_error(array('message' => 'Unauthorized'));
        }

        $plugin = isset($_POST['plugin']) ? sanitize_text_field($_POST['plugin']) : '';

        if (!isset($this->supported_plugins[$plugin])) {
            wp_send_json_error(array('message' => 'Invalid plugin'));
        }

        // Include plugin.php if not loaded (needed for deactivate_plugins)
        if (!function_exists('deactivate_plugins')) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }

        $deactivated = array();

        // Try free version
        if (isset($this->plugin_files[$plugin])) {
            $file = $this->plugin_files[$plugin];
            if (is_plugin_active($file)) {
                deactivate_plugins($file);
                $deactivated[] = $file;
            }
        }

        // Try premium version
        if (isset($this->plugin_files_premium[$plugin])) {
            $file = $this->plugin_files_premium[$plugin];
            if (is_plugin_active($file)) {
                deactivate_plugins($file);
                $deactivated[] = $file;
            }
        }

        if (!empty($deactivated)) {
            wp_send_json_success(array(
                'message'     => sprintf(
                    /* translators: %s: plugin name */
                    __('%s has been deactivated.', 'seo-fury'),
                    $this->supported_plugins[$plugin]['name']
                ),
                'deactivated' => $deactivated,
            ));
        } else {
            wp_send_json_success(array(
                'message'     => sprintf(
                    /* translators: %s: plugin name */
                    __('%s was not active.', 'seo-fury'),
                    $this->supported_plugins[$plugin]['name']
                ),
                'deactivated' => array(),
            ));
        }
    }

    /**
     * Check if a source SEO plugin is currently active
     *
     * @param string $plugin_slug  Plugin slug (yoast, rankmath, aioseo, seopress)
     * @return bool
     */
    public function is_source_plugin_active($plugin_slug) {
        if (!function_exists('is_plugin_active')) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }

        // Check free version
        if (isset($this->plugin_files[$plugin_slug])) {
            if (is_plugin_active($this->plugin_files[$plugin_slug])) {
                return true;
            }
        }

        // Check premium version
        if (isset($this->plugin_files_premium[$plugin_slug])) {
            if (is_plugin_active($this->plugin_files_premium[$plugin_slug])) {
                return true;
            }
        }

        return false;
    }

    // =========================================================================
    // Robots.txt from Physical File
    // =========================================================================

    /**
     * Import robots.txt from the physical file at ABSPATH/robots.txt
     * Used as fallback when the source plugin doesn't store robots.txt content
     */
    private function migrate_robots_from_physical_file() {
        $migrated = array();

        // Don't overwrite if we already have robots content
        $existing = get_option('seo_fury_robots_content', '');
        if (!empty($existing)) {
            return $migrated;
        }

        $robots_file = ABSPATH . 'robots.txt';
        if (!file_exists($robots_file) || !is_readable($robots_file)) {
            return $migrated;
        }

        $content = file_get_contents($robots_file);
        if (empty(trim($content))) {
            return $migrated;
        }

        // Skip WordPress default virtual robots.txt (very basic content)
        $lines = array_filter(array_map('trim', explode("\n", $content)));
        $non_empty = count($lines);
        if ($non_empty <= 2) {
            // Likely just "User-agent: *\nDisallow:" — WordPress default
            return $migrated;
        }

        update_option('seo_fury_robots_content', sanitize_textarea_field($content));
        update_option('seo_fury_robots_enabled', 1);
        $migrated[] = __('Robots.txt content (from file)', 'seo-fury');

        return $migrated;
    }

    // =========================================================================
    // Local SEO: Yoast & SEOPress
    // =========================================================================

    /**
     * Migrate Yoast Local SEO / Organization settings
     */
    private function migrate_yoast_local_seo() {
        $migrated = array();
        $has_data = false;

        // Yoast stores organization data in wpseo_social option
        $social = get_option('wpseo_social', array());
        if (!is_array($social)) {
            $social = array();
        }

        // Company name
        if (!empty($social['company_name']) && empty(get_option('seo_fury_local_name', ''))) {
            update_option('seo_fury_local_name', sanitize_text_field($social['company_name']));
            $has_data = true;
        }

        // Company logo
        if (!empty($social['company_logo']) && empty(get_option('seo_fury_local_logo', ''))) {
            update_option('seo_fury_local_logo', esc_url_raw($social['company_logo']));
            $has_data = true;
        }

        // Organization type
        if (!empty($social['company_or_person']) && $social['company_or_person'] === 'company') {
            if (empty(get_option('seo_fury_local_type', ''))) {
                update_option('seo_fury_local_type', 'Organization');
            }
        }

        // Yoast Local SEO Premium add-on (wpseo_local option)
        $local = get_option('wpseo_local', array());
        if (is_array($local)) {
            if (!empty($local['location_name']) && empty(get_option('seo_fury_local_name', ''))) {
                update_option('seo_fury_local_name', sanitize_text_field($local['location_name']));
                $has_data = true;
            }
            if (!empty($local['location_phone']) && empty(get_option('seo_fury_local_phone', ''))) {
                update_option('seo_fury_local_phone', sanitize_text_field($local['location_phone']));
                $has_data = true;
            }
            if (!empty($local['location_email']) && empty(get_option('seo_fury_local_email', ''))) {
                update_option('seo_fury_local_email', sanitize_email($local['location_email']));
                $has_data = true;
            }
            if (!empty($local['location_url']) && empty(get_option('seo_fury_local_url', ''))) {
                update_option('seo_fury_local_url', esc_url_raw($local['location_url']));
                $has_data = true;
            }
            if (!empty($local['location_address']) && empty(get_option('seo_fury_local_street', ''))) {
                update_option('seo_fury_local_street', sanitize_text_field($local['location_address']));
                $has_data = true;
            }
            if (!empty($local['location_city']) && empty(get_option('seo_fury_local_city', ''))) {
                update_option('seo_fury_local_city', sanitize_text_field($local['location_city']));
                $has_data = true;
            }
            if (!empty($local['location_state']) && empty(get_option('seo_fury_local_region', ''))) {
                update_option('seo_fury_local_region', sanitize_text_field($local['location_state']));
                $has_data = true;
            }
            if (!empty($local['location_zipcode']) && empty(get_option('seo_fury_local_postal', ''))) {
                update_option('seo_fury_local_postal', sanitize_text_field($local['location_zipcode']));
                $has_data = true;
            }
            if (!empty($local['location_country']) && empty(get_option('seo_fury_local_country', ''))) {
                update_option('seo_fury_local_country', sanitize_text_field($local['location_country']));
                $has_data = true;
            }
            if (!empty($local['business_type']) && empty(get_option('seo_fury_local_type', ''))) {
                update_option('seo_fury_local_type', sanitize_text_field($local['business_type']));
                $has_data = true;
            }
        }

        if ($has_data) {
            update_option('seo_fury_local_enabled', 1);
            $migrated[] = __('Local SEO / Organization settings', 'seo-fury');
        }

        return $migrated;
    }

    /**
     * Migrate SEOPress Local SEO settings
     */
    private function migrate_seopress_local_seo() {
        $migrated = array();
        $has_data = false;

        $pro = get_option('seopress_pro_option_name', array());
        if (!is_array($pro)) {
            return $migrated;
        }

        // SEOPress stores local business data with seopress_local_business_ prefix
        $local_map = array(
            'seopress_local_business_type'          => 'seo_fury_local_type',
            'seopress_local_business_name'          => 'seo_fury_local_name',
            'seopress_local_business_url'           => 'seo_fury_local_url',
            'seopress_local_business_img'           => 'seo_fury_local_logo',
            'seopress_local_business_phone'         => 'seo_fury_local_phone',
            'seopress_local_business_email'         => 'seo_fury_local_email',
            'seopress_local_business_street_address' => 'seo_fury_local_street',
            'seopress_local_business_city'          => 'seo_fury_local_city',
            'seopress_local_business_state'         => 'seo_fury_local_region',
            'seopress_local_business_postal_code'   => 'seo_fury_local_postal',
            'seopress_local_business_country'       => 'seo_fury_local_country',
            'seopress_local_business_lat'           => 'seo_fury_local_latitude',
            'seopress_local_business_lon'           => 'seo_fury_local_longitude',
        );

        foreach ($local_map as $source_key => $target_key) {
            if (!empty($pro[$source_key]) && empty(get_option($target_key, ''))) {
                $value = $pro[$source_key];
                if (strpos($target_key, '_url') !== false || strpos($target_key, '_logo') !== false) {
                    $value = esc_url_raw($value);
                } elseif (strpos($target_key, '_email') !== false) {
                    $value = sanitize_email($value);
                } else {
                    $value = sanitize_text_field($value);
                }
                update_option($target_key, $value);
                $has_data = true;
            }
        }

        if ($has_data) {
            update_option('seo_fury_local_enabled', 1);
            $migrated[] = __('Local SEO / Organization settings', 'seo-fury');
        }

        return $migrated;
    }

    // =========================================================================
    // Taxonomy Term Meta Migration
    // =========================================================================

    /**
     * Migrate Yoast taxonomy term meta (titles, descriptions, OG, etc.)
     *
     * Yoast stores all taxonomy meta in a single option: wpseo_taxonomy_meta
     * Format: array[ taxonomy ][ term_id ][ wpseo_title, wpseo_desc, wpseo_canonical, etc. ]
     */
    private function migrate_yoast_taxonomy_meta() {
        $migrated = array();
        $tax_meta = get_option('wpseo_taxonomy_meta', array());

        if (!is_array($tax_meta) || empty($tax_meta)) {
            return $migrated;
        }

        $count = 0;
        foreach ($tax_meta as $taxonomy => $terms) {
            if (!is_array($terms)) {
                continue;
            }
            foreach ($terms as $term_id => $meta) {
                if (!is_array($meta) || !is_numeric($term_id)) {
                    continue;
                }

                $term_id = intval($term_id);
                $map = array(
                    'wpseo_title'                 => '_seo_fury_title',
                    'wpseo_desc'                  => '_seo_fury_description',
                    'wpseo_canonical'             => '_seo_fury_canonical',
                    'wpseo_focuskw'               => '_seo_fury_focus_keyword',
                    'wpseo_opengraph-title'       => '_seo_fury_og_title',
                    'wpseo_opengraph-description' => '_seo_fury_og_description',
                    'wpseo_opengraph-image'       => '_seo_fury_og_image',
                    'wpseo_twitter-title'         => '_seo_fury_twitter_title',
                    'wpseo_twitter-description'   => '_seo_fury_twitter_description',
                    'wpseo_twitter-image'         => '_seo_fury_twitter_image',
                );

                $did = false;
                foreach ($map as $src => $tgt) {
                    if (empty($meta[$src])) {
                        continue;
                    }
                    $existing = get_term_meta($term_id, $tgt, true);
                    if (!empty($existing)) {
                        continue;
                    }
                    $value = $this->convert_yoast_tags(sanitize_text_field($meta[$src]));
                    update_term_meta($term_id, $tgt, $value);
                    $did = true;
                }

                // Noindex
                if (!empty($meta['wpseo_noindex']) && $meta['wpseo_noindex'] === 'noindex') {
                    $existing = get_term_meta($term_id, '_seo_fury_page_robots_noindex', true);
                    if (empty($existing)) {
                        update_term_meta($term_id, '_seo_fury_page_robots_noindex', 'on');
                        $did = true;
                    }
                }

                if ($did) {
                    $count++;
                }
            }
        }

        if ($count > 0) {
            /* translators: %d: number of taxonomy terms migrated */
            $migrated[] = sprintf(__('%d taxonomy term SEO entries', 'seo-fury'), $count);
        }

        return $migrated;
    }

    /**
     * Migrate Rank Math taxonomy term meta
     *
     * Rank Math stores term meta as standard term_meta:
     * rank_math_title, rank_math_description, rank_math_facebook_title, etc.
     */
    private function migrate_rankmath_taxonomy_meta() {
        global $wpdb;
        $migrated = array();

        $source_keys = array(
            'rank_math_title', 'rank_math_description', 'rank_math_focus_keyword',
            'rank_math_canonical_url', 'rank_math_facebook_title', 'rank_math_facebook_description',
            'rank_math_facebook_image', 'rank_math_twitter_title', 'rank_math_twitter_description',
            'rank_math_twitter_image',
        );

        $placeholders = implode(',', array_fill(0, count($source_keys), '%s'));

        $term_ids = $wpdb->get_col($wpdb->prepare(
            "SELECT DISTINCT term_id FROM {$wpdb->termmeta}
             WHERE meta_key IN ({$placeholders}) AND meta_value != ''
             ORDER BY term_id ASC",
            $source_keys
        ));

        if (empty($term_ids)) {
            return $migrated;
        }

        $map = array(
            'rank_math_title'                => '_seo_fury_title',
            'rank_math_description'          => '_seo_fury_description',
            'rank_math_focus_keyword'        => '_seo_fury_focus_keyword',
            'rank_math_canonical_url'        => '_seo_fury_canonical',
            'rank_math_facebook_title'       => '_seo_fury_og_title',
            'rank_math_facebook_description' => '_seo_fury_og_description',
            'rank_math_facebook_image'       => '_seo_fury_og_image',
            'rank_math_twitter_title'        => '_seo_fury_twitter_title',
            'rank_math_twitter_description'  => '_seo_fury_twitter_description',
            'rank_math_twitter_image'        => '_seo_fury_twitter_image',
        );

        $count = 0;
        foreach ($term_ids as $term_id) {
            $did = false;
            foreach ($map as $src => $tgt) {
                $val = get_term_meta($term_id, $src, true);
                if (empty($val)) {
                    continue;
                }
                $existing = get_term_meta($term_id, $tgt, true);
                if (!empty($existing)) {
                    continue;
                }
                update_term_meta($term_id, $tgt, $this->convert_rankmath_tags(sanitize_text_field($val)));
                $did = true;
            }

            // Robots array
            $robots = get_term_meta($term_id, 'rank_math_robots', true);
            if (is_array($robots)) {
                if (in_array('noindex', $robots, true) && empty(get_term_meta($term_id, '_seo_fury_page_robots_noindex', true))) {
                    update_term_meta($term_id, '_seo_fury_page_robots_noindex', 'on');
                    $did = true;
                }
                if (in_array('nofollow', $robots, true) && empty(get_term_meta($term_id, '_seo_fury_page_robots_nofollow', true))) {
                    update_term_meta($term_id, '_seo_fury_page_robots_nofollow', 'on');
                    $did = true;
                }
            }

            if ($did) {
                $count++;
            }
        }

        if ($count > 0) {
            /* translators: %d: number of taxonomy terms migrated */
            $migrated[] = sprintf(__('%d taxonomy term SEO entries', 'seo-fury'), $count);
        }

        return $migrated;
    }

    /**
     * Migrate SEOPress taxonomy term meta
     *
     * SEOPress stores term meta as: _seopress_titles_title, _seopress_titles_desc, etc.
     */
    private function migrate_seopress_taxonomy_meta() {
        global $wpdb;
        $migrated = array();

        $source_keys = array(
            '_seopress_titles_title', '_seopress_titles_desc',
            '_seopress_social_fb_title', '_seopress_social_fb_desc', '_seopress_social_fb_img',
            '_seopress_social_twitter_title', '_seopress_social_twitter_desc', '_seopress_social_twitter_img',
            '_seopress_robots_canonical',
        );

        $placeholders = implode(',', array_fill(0, count($source_keys), '%s'));

        $term_ids = $wpdb->get_col($wpdb->prepare(
            "SELECT DISTINCT term_id FROM {$wpdb->termmeta}
             WHERE meta_key IN ({$placeholders}) AND meta_value != ''
             ORDER BY term_id ASC",
            $source_keys
        ));

        if (empty($term_ids)) {
            return $migrated;
        }

        $map = array(
            '_seopress_titles_title'          => '_seo_fury_title',
            '_seopress_titles_desc'           => '_seo_fury_description',
            '_seopress_robots_canonical'      => '_seo_fury_canonical',
            '_seopress_social_fb_title'       => '_seo_fury_og_title',
            '_seopress_social_fb_desc'        => '_seo_fury_og_description',
            '_seopress_social_fb_img'         => '_seo_fury_og_image',
            '_seopress_social_twitter_title'  => '_seo_fury_twitter_title',
            '_seopress_social_twitter_desc'   => '_seo_fury_twitter_description',
            '_seopress_social_twitter_img'    => '_seo_fury_twitter_image',
        );

        $count = 0;
        foreach ($term_ids as $term_id) {
            $did = false;
            foreach ($map as $src => $tgt) {
                $val = get_term_meta($term_id, $src, true);
                if (empty($val)) {
                    continue;
                }
                $existing = get_term_meta($term_id, $tgt, true);
                if (!empty($existing)) {
                    continue;
                }
                update_term_meta($term_id, $tgt, $this->convert_seopress_tags(sanitize_text_field($val)));
                $did = true;
            }

            // Noindex/nofollow
            $noindex = get_term_meta($term_id, '_seopress_robots_index', true);
            if ($noindex === 'yes' && empty(get_term_meta($term_id, '_seo_fury_page_robots_noindex', true))) {
                update_term_meta($term_id, '_seo_fury_page_robots_noindex', 'on');
                $did = true;
            }
            $nofollow = get_term_meta($term_id, '_seopress_robots_follow', true);
            if ($nofollow === 'yes' && empty(get_term_meta($term_id, '_seo_fury_page_robots_nofollow', true))) {
                update_term_meta($term_id, '_seo_fury_page_robots_nofollow', 'on');
                $did = true;
            }

            if ($did) {
                $count++;
            }
        }

        if ($count > 0) {
            /* translators: %d: number of taxonomy terms migrated */
            $migrated[] = sprintf(__('%d taxonomy term SEO entries', 'seo-fury'), $count);
        }

        return $migrated;
    }

    /**
     * Migrate AIOSEO taxonomy term meta
     *
     * AIOSEO v4 uses a custom table: {prefix}aioseo_terms
     * Fallback to term meta for v3: _aioseop_title, _aioseop_description
     */
    private function migrate_aioseo_taxonomy_meta($options) {
        global $wpdb;
        $migrated = array();

        // Try v4 table first
        $table = $wpdb->prefix . 'aioseo_terms';
        $table_exists = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = %s AND table_name = %s",
            DB_NAME,
            $table
        ));

        $count = 0;

        if ($table_exists) {
            $rows = $wpdb->get_results("SELECT * FROM {$table} WHERE (title IS NOT NULL AND title != '') OR (description IS NOT NULL AND description != '')");

            if (!empty($rows)) {
                $v4_map = array(
                    'title'             => '_seo_fury_title',
                    'description'       => '_seo_fury_description',
                    'canonical_url'     => '_seo_fury_canonical',
                    'og_title'          => '_seo_fury_og_title',
                    'og_description'    => '_seo_fury_og_description',
                    'og_image_url'      => '_seo_fury_og_image',
                    'twitter_title'     => '_seo_fury_twitter_title',
                    'twitter_description' => '_seo_fury_twitter_description',
                    'twitter_image_url' => '_seo_fury_twitter_image',
                );

                foreach ($rows as $row) {
                    $term_id = isset($row->term_id) ? intval($row->term_id) : 0;
                    if (!$term_id) {
                        continue;
                    }

                    $did = false;
                    $row_arr = (array) $row;

                    foreach ($v4_map as $col => $target_key) {
                        if (empty($row_arr[$col])) {
                            continue;
                        }
                        $existing = get_term_meta($term_id, $target_key, true);
                        if (!empty($existing)) {
                            continue;
                        }
                        $value = $this->convert_aioseo_tags(sanitize_text_field($row_arr[$col]));
                        update_term_meta($term_id, $target_key, $value);
                        $did = true;
                    }

                    // Robots
                    if (!empty($row_arr['robots_noindex']) && $row_arr['robots_noindex'] == 1) {
                        if (empty(get_term_meta($term_id, '_seo_fury_page_robots_noindex', true))) {
                            update_term_meta($term_id, '_seo_fury_page_robots_noindex', 'on');
                            $did = true;
                        }
                    }

                    if ($did) {
                        $count++;
                    }
                }
            }
        }

        // v3 fallback: term meta _aioseop_title, _aioseop_description
        if ($count === 0) {
            $v3_keys = array('_aioseop_title', '_aioseop_description');
            $placeholders = implode(',', array_fill(0, count($v3_keys), '%s'));

            $term_ids = $wpdb->get_col($wpdb->prepare(
                "SELECT DISTINCT term_id FROM {$wpdb->termmeta}
                 WHERE meta_key IN ({$placeholders}) AND meta_value != ''",
                $v3_keys
            ));

            if (!empty($term_ids)) {
                $v3_map = array(
                    '_aioseop_title'       => '_seo_fury_title',
                    '_aioseop_description' => '_seo_fury_description',
                );

                foreach ($term_ids as $term_id) {
                    $did = false;
                    foreach ($v3_map as $src => $tgt) {
                        $val = get_term_meta($term_id, $src, true);
                        if (empty($val)) {
                            continue;
                        }
                        $existing = get_term_meta($term_id, $tgt, true);
                        if (!empty($existing)) {
                            continue;
                        }
                        update_term_meta($term_id, $tgt, sanitize_text_field($val));
                        $did = true;
                    }
                    if ($did) {
                        $count++;
                    }
                }
            }
        }

        if ($count > 0) {
            /* translators: %d: number of taxonomy terms migrated */
            $migrated[] = sprintf(__('%d taxonomy term SEO entries', 'seo-fury'), $count);
        }

        return $migrated;
    }

    /**
     * Get total post count for a plugin (used by JS for progress bar).
     *
     * Counts posts with ANY source meta key, including special keys like
     * rank_math_robots that are not in the standard meta_map.
     */
    public function get_total_count($plugin) {
        global $wpdb;

        if ($plugin === 'aioseo' && $this->has_aioseo_v4_table()) {
            $table = $wpdb->prefix . 'aioseo_posts';
            return (int) $wpdb->get_var(
                "SELECT COUNT(*) FROM {$table} WHERE (title IS NOT NULL AND title != '') OR (description IS NOT NULL AND description != '')"
            );
        }

        $map = $this->get_meta_map_for_plugin($plugin);
        $source_keys = array_keys($map);

        // Add extra keys that are handled separately but should count for detection
        if ($plugin === 'rankmath') {
            $source_keys[] = 'rank_math_robots';
        }

        if (empty($source_keys)) {
            return 0;
        }

        $placeholders = implode(',', array_fill(0, count($source_keys), '%s'));

        return (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} WHERE meta_key IN ({$placeholders}) AND meta_value != ''",
            $source_keys
        ));
    }
}
