<?php
/**
 * Hubbub to PinnerPress Migration functionality
 *
 * @link       https://pinnerpress.com
 * @since      0.6.8
 *
 * @package    PinnerPress
 * @subpackage PinnerPress/includes
 */

if (!defined('WPINC')) {
    die;
}

/**
 * The Hubbub migration functionality of the plugin.
 *
 * Handles discovery and migration of Hubbub settings and hidden images.
 *
 * @package    PinnerPress
 * @subpackage PinnerPress/includes
 */
if (!class_exists('PinnerPress_Hubbub_Migration')) {
class PinnerPress_Hubbub_Migration {

    /**
     * Initialize the class and set its properties.
     *
     * @since    0.6.8
     */
    public function __construct() {
        // Register AJAX actions for migration
        add_action('wp_ajax_pinnerpress_scan_hubbub_data', array($this, 'scan_hubbub_data_ajax'));
        add_action('wp_ajax_pinnerpress_migrate_from_hubbub', array($this, 'migrate_from_hubbub_ajax'));
        add_action('wp_ajax_pinnerpress_migrate_batch', array($this, 'migrate_batch_ajax'));
    }

    /**
     * Discover Hubbub settings in the database.
     *
     * @since    0.6.8
     * @return   array    Array of Hubbub options found
     */
    public function discover_hubbub_settings() {
        global $wpdb;
        
        // Try to get from cache first
        $cache_key = 'pinnerpress_hubbub_settings_discovery';
        $hubbub_options = wp_cache_get($cache_key, 'pinnerpress');
        
        if ($hubbub_options === false) {
            // Find all potential Hubbub-related options with broader search patterns
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Migration discovery query with caching
            $hubbub_options = $wpdb->get_results(
                "SELECT option_name, option_value FROM {$wpdb->options} 
                 WHERE option_name LIKE '%hubbub%' 
                 OR option_name LIKE '%pinterest%' 
                 OR option_name LIKE '%pin%it%'
                 OR option_name LIKE '%social%share%'
                 ORDER BY option_name"
            );
            wp_cache_set($cache_key, $hubbub_options, 'pinnerpress', 600); // Cache for 10 minutes
        }
        
        // Filter out PinnerPress options and transients to avoid confusion
        $filtered_options = array();
        foreach ($hubbub_options as $option) {
            // Skip PinnerPress options
            if (strpos($option->option_name, 'pinnerpress') !== false || 
                strpos($option->option_name, 'pinterest_pro') !== false) {
                continue;
            }
            
            // Skip transients and temporary options
            if (strpos($option->option_name, '_transient_') !== false || 
                strpos($option->option_name, 'timeout_') !== false ||
                $option->option_name === 'ping_sites') {
                continue;
            }
            
            $filtered_options[] = $option;
        }
        
        return $filtered_options;
    }

    /**
     * Find posts with Hubbub hidden images.
     *
     * @since    0.6.8
     * @return   array    Array of posts with hidden images
     */
    public function find_hidden_images() {
        global $wpdb;
        
        // Try to get from cache first
        $cache_key = 'pinnerpress_hubbub_hidden_images';
        $hidden_images = wp_cache_get($cache_key, 'pinnerpress');
        
        if ($hidden_images === false) {
            // Look for both possible Hubbub hidden image meta keys
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Migration query with caching
            $hidden_images = $wpdb->get_results(
                "SELECT post_id, meta_key, meta_value FROM {$wpdb->postmeta} 
                 WHERE meta_key = 'dpsp_pinterest_hidden_images_json'
                 OR meta_key = 'dpsp_pinterest_hidden_images'
                 ORDER BY post_id, meta_key"
            );
            wp_cache_set($cache_key, $hidden_images, 'pinnerpress', 600); // Cache for 10 minutes
        }
        
        return $hidden_images;
    }

    /**
     * Count posts with Hubbub hidden images.
     *
     * @since    0.6.8
     * @return   int      Number of posts with hidden images
     */
    public function count_posts_with_hidden_images() {
        // Use the same logic as find_hidden_images() to ensure consistency
        $hidden_images = $this->find_hidden_images();
        $unique_posts = array();
        
        foreach ($hidden_images as $image) {
            $unique_posts[$image->post_id] = true;
        }
        
        return count($unique_posts);
    }

    /**
     * Count total hidden images across all posts.
     *
     * @since    0.6.8
     * @return   int      Total number of hidden images
     */
    public function count_total_hidden_images() {
        $hidden_images = $this->find_hidden_images();
        $total = 0;
        
        foreach ($hidden_images as $image_data) {
            // Handle JSON data from dpsp_pinterest_hidden_images_json
            $images = json_decode($image_data->meta_value, true);
            
            // If JSON decode failed, try unserialize as fallback
            if (json_last_error() !== JSON_ERROR_NONE) {
                $images = maybe_unserialize($image_data->meta_value);
            }
            
            if (is_array($images)) {
                $total += count($images);
            } elseif (!empty($images)) {
                $total += 1;
            }
        }
        
        return $total;
    }

    /**
     * Search for Pinterest username in dpsp_settings using WordPress methods.
     *
     * @since    0.6.8
     * @return   array    Results of looking for pinterest_username in dpsp_settings
     */
    public function search_for_pinterest_usernames() {
        $found_options = array();
        
        // Get dpsp_settings option (WordPress automatically unserializes it)
        $dpsp_settings = get_option('dpsp_settings');
        
        if ($dpsp_settings && is_array($dpsp_settings)) {
            // Check if pinterest_username key exists
            if (isset($dpsp_settings['pinterest_username']) && !empty($dpsp_settings['pinterest_username'])) {
                $username = $dpsp_settings['pinterest_username'];
                
                $found_options[] = array(
                    'location' => 'wp_options',
                    'option_name' => 'dpsp_settings',
                    'option_value' => 'Array with ' . count($dpsp_settings) . ' keys',
                    'extracted_username' => $username,
                    'username_length' => strlen($username),
                    'pattern_found' => 'pinterest_username key found in array',
                    'method' => 'WordPress get_option() with array access'
                );
            } else {
                // Debug: Show what keys are available
                $available_keys = array_keys($dpsp_settings);
                $pinterest_keys = array_filter($available_keys, function($key) {
                    return stripos($key, 'pinterest') !== false;
                });
                
                $found_options[] = array(
                    'location' => 'wp_options',
                    'option_name' => 'dpsp_settings',
                    'option_value' => 'Array with ' . count($dpsp_settings) . ' keys',
                    'extracted_username' => 'NOT_FOUND',
                    'username_length' => 0,
                    'pattern_found' => 'pinterest_username key not found',
                    'available_pinterest_keys' => $pinterest_keys,
                    'method' => 'WordPress get_option() with array access'
                );
            }
        } else {
            $found_options[] = array(
                'location' => 'wp_options',
                'option_name' => 'dpsp_settings',
                'option_value' => 'Not an array or empty',
                'extracted_username' => 'ERROR',
                'username_length' => 0,
                'pattern_found' => 'dpsp_settings is not a valid array',
                'data_type' => gettype($dpsp_settings),
                'method' => 'WordPress get_option() with array access'
            );
        }
        
        return $found_options;
    }

    /**
     * Get detailed Pinterest settings analysis for debugging.
     *
     * @since    0.6.8
     * @return   array    Pinterest settings analysis
     */
    public function analyze_pinterest_settings() {
        $analysis = array();
        
        // Search for Pinterest usernames using serialized string patterns
        $analysis['username_search'] = $this->search_for_pinterest_usernames();
        
        // Check the main DPSP settings option (where Pinterest username is stored)
        $dpsp_main_settings = get_option('dpsp_settings');
        if ($dpsp_main_settings) {
            // Always store the raw string version for debugging
            if (is_string($dpsp_main_settings)) {
                $analysis['dpsp_settings_raw'] = $dpsp_main_settings;
            } else {
                // If it's already unserialized, try to serialize it back to show the raw format
                $analysis['dpsp_settings_raw'] = serialize($dpsp_main_settings);
            }
            $analysis['dpsp_settings_is_serialized'] = is_serialized($dpsp_main_settings);
            
            if (is_serialized($dpsp_main_settings)) {
                $unserialized = maybe_unserialize($dpsp_main_settings);
                $analysis['dpsp_main_unserialized'] = $unserialized;
                
                if (is_array($unserialized)) {
                    $analysis['dpsp_main_keys'] = array_keys($unserialized);
                    
                    // Look for potential username fields
                    foreach ($unserialized as $key => $value) {
                        if (stripos($key, 'username') !== false || 
                            stripos($key, 'pinterest') !== false ||
                            (is_string($value) && $value === 'girlyglimmer')) {
                            $analysis['potential_username_fields'][$key] = $value;
                        }
                    }
                }
            }
        }

        // Also check the Pinterest images settings
        $dpsp_pinterest_settings = get_option('dpsp_pinterest_share_images_setting');
        if ($dpsp_pinterest_settings) {
            $analysis['dpsp_pinterest_raw'] = $dpsp_pinterest_settings;
            $analysis['dpsp_pinterest_is_serialized'] = is_serialized($dpsp_pinterest_settings);
            
            if (is_serialized($dpsp_pinterest_settings)) {
                $unserialized = maybe_unserialize($dpsp_pinterest_settings);
                $analysis['dpsp_pinterest_unserialized'] = $unserialized;
                
                if (is_array($unserialized)) {
                    $analysis['dpsp_pinterest_keys'] = array_keys($unserialized);
                    
                    // Look for potential username fields
                    foreach ($unserialized as $key => $value) {
                        if (stripos($key, 'username') !== false || stripos($key, 'pinterest') !== false) {
                            if (!isset($analysis['potential_username_fields'])) {
                                $analysis['potential_username_fields'] = array();
                            }
                            $analysis['potential_username_fields'][$key] = $value;
                        }
                    }
                }
            }
        }
        
        // Check for other Pinterest options
        $other_pinterest_options = array();
        $all_options = wp_load_alloptions();
        foreach ($all_options as $option_name => $option_value) {
            if (stripos($option_name, 'pinterest') !== false && 
                strpos($option_name, 'pinnerpress') === false) {
                $other_pinterest_options[$option_name] = $option_value;
            }
        }
        $analysis['other_pinterest_options'] = $other_pinterest_options;
        
        return $analysis;
    }

    /**
     * Investigate all Hubbub data for migration analysis.
     *
     * @since    0.6.8
     * @return   array    Complete analysis of Hubbub data
     */
    public function investigate_hubbub_data() {
        $results = array(
            'options' => $this->discover_hubbub_settings(),
            'hidden_images' => $this->find_hidden_images(),
            'posts_with_images' => $this->count_posts_with_hidden_images(),
            'total_images' => $this->count_total_hidden_images(),
            'pinterest_url' => $this->get_hubbub_pinterest_url(),
            'hubbub_active' => $this->is_hubbub_active(),
            'debug_info' => $this->get_debug_info(),
            'pinterest_analysis' => $this->analyze_pinterest_settings(),
            'pin_button_position' => $this->get_hubbub_pin_button_position(),
            'button_text_settings' => $this->get_hubbub_button_text_settings()
        );
        
        return $results;
    }

    /**
     * Get debug information about the WordPress environment.
     *
     * @since    0.6.8
     * @return   array    Debug information
     */
    public function get_debug_info() {
        $active_plugins = get_option('active_plugins', array());
        
        return array(
            'active_plugins_count' => count($active_plugins),
            'active_plugins' => array_slice($active_plugins, 0, 20), // Limit to first 20 for display
            'wp_version' => get_bloginfo('version'),
            'php_version' => PHP_VERSION,
            'functions_exist' => array(
                'add_pin_it_button' => function_exists('add_pin_it_button'),
                'hubbub_init' => function_exists('hubbub_init'),
                'Hubbub_class' => class_exists('Hubbub'),
                'HUBBUB_VERSION' => defined('HUBBUB_VERSION')
            )
        );
    }

    /**
     * Get Hubbub Pinterest URL if available.
     *
     * @since    0.6.8
     * @return   string   Pinterest URL from Hubbub or empty string
     */
    public function get_hubbub_pinterest_url() {
        $pinterest_username = '';
        
        // Get the dpsp_settings option from wp_options table (WordPress handles unserialization automatically)
        $dpsp_settings = get_option('dpsp_settings');
        if ($dpsp_settings && is_array($dpsp_settings)) {
            // Simply access the pinterest_username key from the array
            if (isset($dpsp_settings['pinterest_username']) && !empty($dpsp_settings['pinterest_username'])) {
                $pinterest_username = sanitize_text_field($dpsp_settings['pinterest_username']);
            }
        }
        
        // If not found in dpsp_settings, check dpsp_pinterest_share_images_setting
        if (empty($pinterest_username)) {
            $dpsp_pinterest_settings = get_option('dpsp_pinterest_share_images_setting');
            if ($dpsp_pinterest_settings && is_serialized($dpsp_pinterest_settings)) {
                $settings = maybe_unserialize($dpsp_pinterest_settings);
                if (is_array($settings)) {
                    $username_keys = array(
                        'pinterest_username', 
                        'username', 
                        'pinterest_user',
                        'share_image_pinterest_username',
                        'pin_username'
                    );
                    
                    foreach ($username_keys as $key) {
                        if (isset($settings[$key]) && !empty($settings[$key])) {
                            $pinterest_username = sanitize_text_field($settings[$key]);
                            break;
                        }
                    }
                }
            }
        }
        
        // If still not found, check other possible options
        if (empty($pinterest_username)) {
            $possible_options = array(
                'hubbub_pinterest_url',
                'hubbub_pinterest_username', 
                'hubbub_settings',
                'social_pinterest_url',
                'pinterest_username',
                'pinterest_url'
            );
            
            foreach ($possible_options as $option) {
                $value = get_option($option);
                if ($value) {
                    if (is_serialized($value)) {
                        $settings = maybe_unserialize($value);
                        if (is_array($settings)) {
                            foreach ($settings as $key => $setting_value) {
                                if (is_string($setting_value) && !empty($setting_value)) {
                                    if (stripos($key, 'pinterest') !== false || 
                                        stripos($key, 'username') !== false ||
                                        $setting_value === 'girlyglimmer') {
                                        $pinterest_username = sanitize_text_field($setting_value);
                                        break 2;
                                    }
                                }
                            }
                        }
                    } else {
                        $clean_value = sanitize_text_field($value);
                        if (stripos($clean_value, 'pinterest.com') !== false) {
                            return $clean_value; // Already a full URL
                        } else if (!empty($clean_value)) {
                            $pinterest_username = $clean_value;
                            break;
                        }
                    }
                }
            }
        }
        
        // If we found a username, construct the full Pinterest URL
        if (!empty($pinterest_username)) {
            // Clean the username (remove @ if present, trim whitespace)
            $pinterest_username = trim($pinterest_username, '@ ');
            
            // Construct the full Pinterest URL
            return 'https://www.pinterest.com/' . $pinterest_username . '/';
        }
        
        return '';
    }

    /**
     * Check if Hubbub plugin is active.
     *
     * @since    0.6.8
     * @return   bool     True if Hubbub is active, false otherwise
     */
    public function is_hubbub_active() {
        if (!function_exists('is_plugin_active')) {
            include_once(ABSPATH . 'wp-admin/includes/plugin.php');
        }
        
        // Get all active plugins
        $active_plugins = get_option('active_plugins', array());
        
        // Check for any plugin that might be Hubbub or similar Pinterest plugin
        foreach ($active_plugins as $plugin) {
            $plugin_lower = strtolower($plugin);
            if (strpos($plugin_lower, 'hubbub') !== false ||
                strpos($plugin_lower, 'pinterest') !== false ||
                strpos($plugin_lower, 'pin-it') !== false ||
                strpos($plugin_lower, 'social-share') !== false) {
                
                // Exclude PinnerPress itself
                if (strpos($plugin_lower, 'pinnerpress') === false) {
                    return true;
                }
            }
        }
        
        // Also check if any Pinterest-related plugin functions exist
        if (function_exists('add_pin_it_button') || 
            function_exists('hubbub_init') ||
            class_exists('Hubbub') ||
            defined('HUBBUB_VERSION')) {
            return true;
        }
        
        return false;
    }

    /**
     * Migrate Pinterest settings from Hubbub to PinnerPress.
     *
     * @since    0.6.8
     * @return   array    Migration results
     */
    public function migrate_pinterest_settings() {
        $results = array(
            'success' => false,
            'messages' => array()
        );
        
        // Get Hubbub Pinterest URL
        $hubbub_url = $this->get_hubbub_pinterest_url();
        
        if ($hubbub_url) {
            // Validate and sanitize URL
            $sanitized_url = $this->validate_pinterest_url($hubbub_url);
            
            if ($sanitized_url) {
                update_option('pinnerpress_pinterest_url', $sanitized_url);
                $results['messages'][] = 'Pinterest URL migrated successfully: ' . $sanitized_url;
                
                // Extract and set display name
                $username = $this->extract_username_from_url($sanitized_url);
                if ($username) {
                    update_option('pinnerpress_pinterest_display_name', $username);
                    $results['messages'][] = 'Pinterest display name set to: ' . $username;
                }
                
                $results['success'] = true;
            } else {
                $results['messages'][] = 'Invalid Pinterest URL found in Hubbub settings: ' . $hubbub_url;
            }
        } else {
            $results['messages'][] = 'No Pinterest URL found in Hubbub settings';
        }
        
        // Migrate pin button position
        $position_result = $this->migrate_pin_button_position();
        if ($position_result['success']) {
            $results['success'] = true;
            $results['messages'] = array_merge($results['messages'], $position_result['messages']);
        }
        
        // Migrate pin button text settings
        $text_result = $this->migrate_pin_button_text();
        if ($text_result['success']) {
            $results['success'] = true;
            $results['messages'] = array_merge($results['messages'], $text_result['messages']);
        }
        
        return $results;
    }
    
    /**
     * Get Hubbub pin button position setting.
     *
     * @since    0.6.8
     * @return   string   Pin button position from Hubbub or empty string
     */
    private function get_hubbub_pin_button_position() {
        $dpsp_pinterest_settings = get_option('dpsp_pinterest_share_images_setting');
        
        if (!$dpsp_pinterest_settings) {
            return '';
        }
        
        // Unserialize the data if needed
        if (is_serialized($dpsp_pinterest_settings)) {
            $settings = maybe_unserialize($dpsp_pinterest_settings);
        } else {
            $settings = $dpsp_pinterest_settings;
        }
        
        // Check for share_image_button_position (correct field name)
        if (!is_array($settings) || !isset($settings['share_image_button_position'])) {
            return '';
        }
        
        return $settings['share_image_button_position'];
    }
    
    /**
     * Get Hubbub button text settings.
     *
     * @since    0.6.8
     * @return   array    Button text settings from Hubbub
     */
    private function get_hubbub_button_text_settings() {
        $settings_info = array();
        
        $dpsp_pinterest_settings = get_option('dpsp_pinterest_share_images_setting');
        
        if (!$dpsp_pinterest_settings) {
            return $settings_info;
        }
        
        // Unserialize the data if needed
        if (is_serialized($dpsp_pinterest_settings)) {
            $settings = maybe_unserialize($dpsp_pinterest_settings);
        } else {
            $settings = $dpsp_pinterest_settings;
        }
        
        if (!is_array($settings)) {
            return $settings_info;
        }
        
        // Get button text
        if (isset($settings['share_image_button_text_label'])) {
            $settings_info['button_text'] = $settings['share_image_button_text_label'];
        }
        
        // Get show button text setting
        if (isset($settings['share_image_show_button_text_label'])) {
            $settings_info['show_button_text'] = $settings['share_image_show_button_text_label'];
        }
        
        // Get minimum image width
        if (isset($settings['share_image_minimum_image_width'])) {
            $settings_info['minimum_image_width'] = $settings['share_image_minimum_image_width'];
        }
        
        return $settings_info;
    }
    
    /**
     * Migrate pin button position from Hubbub to PinnerPress.
     *
     * @since    0.6.8
     * @return   array    Migration results
     */
    private function migrate_pin_button_position() {
        $results = array(
            'success' => false,
            'messages' => array()
        );
        
        // Get DPSP Pinterest share images setting
        $dpsp_pinterest_settings = get_option('dpsp_pinterest_share_images_setting');
        
        if (!$dpsp_pinterest_settings) {
            $results['messages'][] = 'No DPSP Pinterest share images settings found';
            return $results;
        }
        
        // Unserialize the data if needed
        if (is_serialized($dpsp_pinterest_settings)) {
            $settings = maybe_unserialize($dpsp_pinterest_settings);
        } else {
            $settings = $dpsp_pinterest_settings;
        }
        
        if (!is_array($settings)) {
            $results['messages'][] = 'Could not parse DPSP Pinterest settings';
            return $results;
        }
        
        // Look for share_image_button_position setting
        if (!isset($settings['share_image_button_position'])) {
            $results['messages'][] = 'No pin button position found in Hubbub settings';
            return $results;
        }
        
        $hubbub_position = $settings['share_image_button_position'];
        
        // Map Hubbub positions to PinnerPress positions
        $position_mapping = array(
            'center' => 'top_left', // default center to top_left
            'top_left' => 'top_left', 
            'top_right' => 'top_right',
            'bottom_right' => 'bottom_right',
            'bottom_left' => 'bottom_left'
        );
        
        if (!isset($position_mapping[$hubbub_position])) {
            $results['messages'][] = 'Unknown pin button position: ' . $hubbub_position . '. Defaulting to top_left.';
            $pinnerpress_position = 'top_left';
        } else {
            $pinnerpress_position = $position_mapping[$hubbub_position];
        }
        
        // Update PinnerPress pin button position
        update_option('pinnerpress_pin_button_position', $pinnerpress_position);
        
        $results['success'] = true;
        $results['messages'][] = 'Pin button position migrated: ' . $hubbub_position . ' → ' . $pinnerpress_position;
        
        return $results;
    }
    
    /**
     * Migrate pin button text settings from Hubbub to PinnerPress.
     *
     * @since    0.6.8
     * @return   array    Migration results
     */
    private function migrate_pin_button_text() {
        $results = array(
            'success' => false,
            'messages' => array()
        );
        
        // Get DPSP Pinterest share images setting
        $dpsp_pinterest_settings = get_option('dpsp_pinterest_share_images_setting');
        
        if (!$dpsp_pinterest_settings) {
            $results['messages'][] = 'No DPSP Pinterest share images settings found for button text';
            return $results;
        }
        
        // Unserialize the data if needed
        if (is_serialized($dpsp_pinterest_settings)) {
            $settings = maybe_unserialize($dpsp_pinterest_settings);
        } else {
            $settings = $dpsp_pinterest_settings;
        }
        
        if (!is_array($settings)) {
            $results['messages'][] = 'Could not parse DPSP Pinterest settings for button text';
            return $results;
        }
        
        $migrated_settings = array();
        
        // Migrate button label text
        if (isset($settings['share_image_button_text_label'])) {
            $button_text = sanitize_text_field($settings['share_image_button_text_label']);
            update_option('pinnerpress_custom_button_text', $button_text);
            $migrated_settings[] = 'Button text: "' . $button_text . '"';
        }
        
        // Migrate show button text setting
        if (isset($settings['share_image_show_button_text_label'])) {
            $show_text = strtolower($settings['share_image_show_button_text_label']);
            // PinnerPress uses 'default' for showing text, 'pinterest-logo' for logo only
            if ($show_text === 'yes' || $show_text === 'true' || $show_text === '1') {
                update_option('pinnerpress_hover_button_style', 'default');
                $migrated_settings[] = 'Show button text: yes (showing text)';
            } else {
                update_option('pinnerpress_hover_button_style', 'pinterest-logo');
                $migrated_settings[] = 'Show button text: no (logo only)';
            }
        }
        
        // Migrate minimum image width
        if (isset($settings['share_image_minimum_image_width'])) {
            $min_width = intval($settings['share_image_minimum_image_width']);
            if ($min_width > 0) {
                update_option('pinnerpress_minimum_image_size', $min_width);
                $migrated_settings[] = 'Minimum image size: ' . $min_width . 'px';
            }
        }
        
        if (!empty($migrated_settings)) {
            $results['success'] = true;
            $results['messages'] = array_merge($results['messages'], $migrated_settings);
        } else {
            $results['messages'][] = 'No button text settings found in Hubbub';
        }
        
        return $results;
    }

    /**
     * Migrate hidden images from Hubbub to PinnerPress format.
     *
     * @since    0.6.8
     * @return   array    Migration results
     */
    public function migrate_hidden_images() {
        $results = array(
            'success' => false,
            'migrated_posts' => 0,
            'migrated_images' => 0,
            'errors' => array(),
            'messages' => array()
        );
        
        $posts_with_images = $this->find_hidden_images();
        
        if (empty($posts_with_images)) {
            $results['messages'][] = 'No hidden images found in Hubbub data';
            return $results;
        }
        
        foreach ($posts_with_images as $post_data) {
            try {
                $post_id = $post_data->post_id;
                $meta_key = $post_data->meta_key;
                $meta_value = $post_data->meta_value;
                
                // Convert the Hubbub images to PinnerPress format
                $pinnerpress_format = $this->convert_image_format($meta_value, $meta_key);
                
                if (!empty($pinnerpress_format)) {
                    // Check if PinnerPress already has hidden images for this post
                    $existing_images = get_post_meta($post_id, '_pinnerpress_hidden_images', true);
                    
                    if (empty($existing_images)) {
                        update_post_meta($post_id, '_pinnerpress_hidden_images', $pinnerpress_format);
                        $results['migrated_posts']++;
                        $results['migrated_images'] += count($pinnerpress_format);
                        $results['messages'][] = "Migrated {$meta_key} from post ID {$post_id} (" . count($pinnerpress_format) . " images)";
                    } else {
                        // Merge with existing PinnerPress images
                        $merged_images = array_merge($existing_images, $pinnerpress_format);
                        // Remove duplicates based on URL
                        $unique_images = array();
                        $seen_urls = array();
                        foreach ($merged_images as $image) {
                            if (isset($image['url']) && !in_array($image['url'], $seen_urls)) {
                                $unique_images[] = $image;
                                $seen_urls[] = $image['url'];
                            }
                        }
                        
                        update_post_meta($post_id, '_pinnerpress_hidden_images', $unique_images);
                        $results['migrated_posts']++;
                        $results['migrated_images'] += count($pinnerpress_format);
                        $results['messages'][] = "Merged {$meta_key} with existing PinnerPress images for post ID {$post_id}";
                    }
                }
            } catch (Exception $e) {
                $results['errors'][] = "Error migrating post ID {$post_data->post_id}: " . $e->getMessage();
            }
        }
        
        if ($results['migrated_posts'] > 0) {
            $results['success'] = true;
            $results['messages'][] = "Successfully migrated {$results['migrated_images']} hidden images from {$results['migrated_posts']} posts";
        }
        
        return $results;
    }

    /**
     * Convert Hubbub image format to PinnerPress format.
     *
     * @since    0.6.8
     * @param    mixed    $hubbub_images    Hubbub image data (JSON string, serialized, or array)
     * @param    string   $meta_key         The meta key to help determine format
     * @return   array                      PinnerPress formatted images
     */
    private function convert_image_format($hubbub_images, $meta_key = '') {
        $pinnerpress_images = array();
        
        // Handle different data formats based on the meta key
        if (is_string($hubbub_images)) {
            if ($meta_key === 'dpsp_pinterest_hidden_images_json') {
                // JSON format
                $decoded = json_decode($hubbub_images, true);
                if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
                    $hubbub_images = $decoded;
                }
            } else {
                // Try JSON first, then serialized data
                $decoded = json_decode($hubbub_images, true);
                if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
                    $hubbub_images = $decoded;
                } else {
                    // Try unserialization (for dpsp_pinterest_hidden_images)
                    $unserialized = maybe_unserialize($hubbub_images);
                    if (is_array($unserialized)) {
                        $hubbub_images = $unserialized;
                    }
                }
            }
        }
        
        if (is_array($hubbub_images)) {
            foreach ($hubbub_images as $image) {
                $image_url = '';
                
                if (is_numeric($image)) {
                    // Handle attachment IDs (from dpsp_pinterest_hidden_images)
                    $attachment_id = intval($image);
                    $image_url = wp_get_attachment_url($attachment_id);
                } elseif (is_string($image) && filter_var($image, FILTER_VALIDATE_URL)) {
                    // Direct URL
                    $image_url = $image;
                } elseif (is_array($image)) {
                    // Handle different possible structures in the data
                    if (isset($image['url'])) {
                        $image_url = $image['url'];
                    } elseif (isset($image['src'])) {
                        $image_url = $image['src'];
                    } elseif (isset($image['image'])) {
                        $image_url = $image['image'];
                    } elseif (isset($image['href'])) {
                        $image_url = $image['href'];
                    } elseif (isset($image['id']) && is_numeric($image['id'])) {
                        // Attachment ID in array format
                        $attachment_id = intval($image['id']);
                        $image_url = wp_get_attachment_url($attachment_id);
                    }
                }
                
                if (!empty($image_url) && filter_var($image_url, FILTER_VALIDATE_URL)) {
                    $pinnerpress_images[] = array('url' => esc_url_raw($image_url));
                }
            }
        } elseif (is_string($hubbub_images) && filter_var($hubbub_images, FILTER_VALIDATE_URL)) {
            $pinnerpress_images[] = array('url' => esc_url_raw($hubbub_images));
        }
        
        return $pinnerpress_images;
    }

    /**
     * Validate Pinterest URL format.
     *
     * @since    0.6.8
     * @param    string   $url    URL to validate
     * @return   string           Validated URL or false
     */
    private function validate_pinterest_url($url) {
        if (empty($url)) {
            return false;
        }
        
        // Add https if no protocol specified
        if (!preg_match('~^https?://~i', $url)) {
            $url = 'https://' . $url;
        }
        
        // Validate URL format
        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            return false;
        }
        
        // Check if it's a Pinterest URL
        if (stripos($url, 'pinterest.com') === false) {
            return false;
        }
        
        return esc_url_raw($url);
    }

    /**
     * Extract username from Pinterest URL.
     *
     * @since    0.6.8
     * @param    string   $url    Pinterest URL
     * @return   string           Extracted username
     */
    private function extract_username_from_url($url) {
        $parsed = wp_parse_url($url);
        if (isset($parsed['path'])) {
            $path = trim($parsed['path'], '/');
            $parts = explode('/', $path);
            return !empty($parts[0]) ? sanitize_text_field($parts[0]) : '';
        }
        return '';
    }

    /**
     * Get complete database analysis for Hubbub data.
     *
     * @since    0.6.8
     * @return   array    Detailed database analysis
     */
    public function get_database_analysis() {
        global $wpdb;
        
        $analysis = array();
        
        // Try to get from cache first
        $cache_key = 'pinnerpress_hubbub_db_analysis';
        $cached_analysis = wp_cache_get($cache_key, 'pinnerpress');
        
        if ($cached_analysis !== false) {
            return $cached_analysis;
        }
        
        // 1. Get all wp_options that might be related to Pinterest/Hubbub
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Migration analysis query with caching
        $analysis['all_options'] = $wpdb->get_results(
            "SELECT option_name, option_value FROM {$wpdb->options} 
             WHERE option_name LIKE '%hubbub%' 
             OR option_name LIKE '%pinterest%' 
             OR option_name LIKE '%pin%it%'
             OR option_name LIKE '%social%'
             ORDER BY option_name"
        );
        
        // 2. Check for custom Hubbub tables
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Migration analysis query with caching
        $analysis['hubbub_tables'] = $wpdb->get_results("SHOW TABLES LIKE '%hubbub%'", ARRAY_N);
        
        // 3. Check postmeta for Pinterest/Hubbub data
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Migration analysis query with caching
        $analysis['postmeta_keys'] = $wpdb->get_results(
            "SELECT DISTINCT meta_key, COUNT(*) as count FROM {$wpdb->postmeta} 
             WHERE meta_key LIKE '%hubbub%' 
             OR meta_key LIKE '%pinterest%' 
             OR meta_key LIKE '%pin%'
             GROUP BY meta_key 
             ORDER BY meta_key"
        );
        
        // 4. Check user meta for any Pinterest settings
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Migration analysis query with caching
        $analysis['usermeta_keys'] = $wpdb->get_results(
            "SELECT DISTINCT meta_key, COUNT(*) as count FROM {$wpdb->usermeta} 
             WHERE meta_key LIKE '%hubbub%' 
             OR meta_key LIKE '%pinterest%' 
             GROUP BY meta_key"
        );
        
        // 5. Sample some postmeta values to understand structure
        if (!empty($analysis['postmeta_keys'])) {
            $analysis['postmeta_samples'] = array();
            foreach ($analysis['postmeta_keys'] as $meta) {
                if ($meta->count > 0) {
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Migration analysis query with caching
                    $samples = $wpdb->get_results(
                        $wpdb->prepare(
                            "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s LIMIT 3",
                            $meta->meta_key
                        )
                    );
                    $analysis['postmeta_samples'][$meta->meta_key] = $samples;
                }
            }
        }
        
        // Cache the analysis for 10 minutes
        wp_cache_set($cache_key, $analysis, 'pinnerpress', 600);
        
        return $analysis;
    }

    /**
     * AJAX handler for scanning Hubbub data.
     *
     * @since    0.6.8
     */
    public function scan_hubbub_data_ajax() {
        // Check nonce and permissions
        check_ajax_referer('pinnerpress_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_die('Security check failed');
        }
        
        $data = $this->investigate_hubbub_data();
        
        // Add detailed database analysis
        $data['database_analysis'] = $this->get_database_analysis();
        
        wp_send_json_success($data);
    }

    /**
     * AJAX handler for migrating from Hubbub.
     *
     * @since    0.6.8
     */
    public function migrate_from_hubbub_ajax() {
        // Check nonce and permissions
        check_ajax_referer('pinnerpress_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_die('Security check failed');
        }
        
        // Clean up any previously migrated invalid data before starting new migration
        $this->cleanup_invalid_hidden_images();
        
        // Initialize migration session
        $migration_id = 'migration_' . time();
        set_transient('pinnerpress_migration_' . $migration_id, array(
            'started' => current_time('mysql'),
            'status' => 'starting',
            'settings_done' => false,
            'images_done' => false,
            'batch_size' => 10, // Process 10 posts at a time
            'current_batch' => 0,
            'total_posts' => 0,
            'processed_posts' => 0
        ), 3600); // 1 hour expiry
        
        $results = array(
            'success' => true,
            'migration_id' => $migration_id,
            'use_batch_processing' => true,
            'messages' => array('Migration initialized. Starting batch processing...')
        );
        
        // First migrate settings (quick operation)
        $settings_result = $this->migrate_pinterest_settings();
        $results['settings_migration'] = $settings_result;
        
        // Count total posts with hidden images for progress tracking
        $posts_with_images = $this->get_posts_with_hidden_images();
        $total_posts = count($posts_with_images);
        
        // Update migration session with total count
        $migration_data = get_transient('pinnerpress_migration_' . $migration_id);
        $migration_data['total_posts'] = $total_posts;
        $migration_data['settings_done'] = $settings_result['success'];
        set_transient('pinnerpress_migration_' . $migration_id, $migration_data, 3600);
        
        $results['total_posts'] = $total_posts;
        $results['batch_size'] = $migration_data['batch_size'];
        
        wp_send_json_success($results);
    }
    
    /**
     * AJAX handler for batch processing migration.
     *
     * @since    0.6.8
     */
    public function migrate_batch_ajax() {
        // Check nonce and permissions
        check_ajax_referer('pinnerpress_admin_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_die('Security check failed');
        }
        
        // Validate migration_id
        if ( ! isset($_POST['migration_id']) ) {
            wp_send_json_error(array('message' => 'Missing migration ID.'));
        }
        $migration_id = sanitize_text_field( wp_unslash( $_POST['migration_id'] ) );
        $migration_data = get_transient('pinnerpress_migration_' . $migration_id);
        
        if (!$migration_data) {
            wp_send_json_error(array('message' => 'Migration session expired or not found.'));
        }
        
        $batch_size = $migration_data['batch_size'];
        $current_batch = $migration_data['current_batch'];
        $offset = $current_batch * $batch_size;
        
        // Get posts for this batch
        $posts_with_images = $this->get_posts_with_hidden_images($batch_size, $offset);
        
        $batch_results = array(
            'migrated_posts' => 0,
            'migrated_images' => 0,
            'errors' => array(),
            'messages' => array()
        );
        
        // Process each post in the batch
        foreach ($posts_with_images as $post_id) {
            try {
                $result = $this->migrate_post_hidden_images($post_id);
                if ($result['success']) {
                    $batch_results['migrated_posts']++;
                    $batch_results['migrated_images'] += $result['images_count'];
                } else {
                    $batch_results['errors'][] = "Post {$post_id}: " . $result['message'];
                }
            } catch (Exception $e) {
                $batch_results['errors'][] = "Post {$post_id}: " . $e->getMessage();
            }
        }
        
        // Update migration progress
        $migration_data['current_batch']++;
        $migration_data['processed_posts'] += count($posts_with_images);
        $migration_data['status'] = 'processing';
        
        // Check if we're done
        $is_complete = $migration_data['processed_posts'] >= $migration_data['total_posts'];
        if ($is_complete) {
            $migration_data['status'] = 'completed';
            $migration_data['completed'] = current_time('mysql');
            update_option('pinnerpress_hubbub_migration_completed', current_time('mysql'));
        }
        
        set_transient('pinnerpress_migration_' . $migration_id, $migration_data, 3600);
        
        $response = array(
            'success' => true,
            'batch_complete' => true,
            'migration_complete' => $is_complete,
            'progress' => array(
                'processed' => $migration_data['processed_posts'],
                'total' => $migration_data['total_posts'],
                'percentage' => $migration_data['total_posts'] > 0 ? round(($migration_data['processed_posts'] / $migration_data['total_posts']) * 100, 1) : 100
            ),
            'batch_results' => $batch_results,
            'next_batch' => $is_complete ? null : $migration_data['current_batch']
        );
        
        wp_send_json_success($response);
    }
    
    /**
     * Get posts that have hidden images.
     *
     * @since    0.6.8
     * @param    int    $limit   Number of posts to return
     * @param    int    $offset  Offset for pagination
     * @return   array  Array of post IDs
     */
    private function get_posts_with_hidden_images($limit = -1, $offset = 0) {
        global $wpdb;

        // Create cache key based on parameters
        $cache_key = 'pinnerpress_hubbub_hidden_posts_' . md5($limit . '_' . $offset);
        $post_ids = wp_cache_get($cache_key, 'pinnerpress');
        
        if ($post_ids === false) {
            if ( $limit > 0 ) {
                if ( $offset > 0 ) {
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Migration query with caching
                    $post_ids = $wpdb->get_col(
                        $wpdb->prepare(
                            "SELECT DISTINCT post_id FROM {$wpdb->postmeta}
                             WHERE meta_key IN ('dpsp_pinterest_hidden_images', 'dpsp_pinterest_hidden_images_json')
                             AND meta_value != ''
                             AND meta_value != 'a:0:{}'
                             ORDER BY post_id
                             LIMIT %d OFFSET %d",
                            (int) $limit,
                            (int) $offset
                        )
                    );
                } else {
                    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Migration query with caching
                    $post_ids = $wpdb->get_col(
                        $wpdb->prepare(
                            "SELECT DISTINCT post_id FROM {$wpdb->postmeta}
                             WHERE meta_key IN ('dpsp_pinterest_hidden_images', 'dpsp_pinterest_hidden_images_json')
                             AND meta_value != ''
                             AND meta_value != 'a:0:{}'
                             ORDER BY post_id
                             LIMIT %d",
                            (int) $limit
                        )
                    );
                }
            } else {
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Migration query with caching
                $post_ids = $wpdb->get_col(
                    "SELECT DISTINCT post_id FROM {$wpdb->postmeta}
                     WHERE meta_key IN ('dpsp_pinterest_hidden_images', 'dpsp_pinterest_hidden_images_json')
                     AND meta_value != ''
                     AND meta_value != 'a:0:{}'
                     ORDER BY post_id"
                );
            }
            wp_cache_set($cache_key, $post_ids, 'pinnerpress', 300); // Cache for 5 minutes
        }

        return array_map( 'intval', $post_ids );
    }
    
    /**
     * Migrate hidden images for a single post.
     *
     * @since    0.6.8
     * @param    int    $post_id  The post ID
     * @return   array  Migration result
     */
    private function migrate_post_hidden_images($post_id) {
        $all_image_urls = array(); // Store unique URLs to avoid duplicates
        $images_count = 0;
        
        // Get JSON format first (newer format)
        $json_images = get_post_meta($post_id, 'dpsp_pinterest_hidden_images_json', true);
        if (!empty($json_images)) {
            $decoded_images = json_decode($json_images, true);
            if (is_array($decoded_images)) {
                foreach ($decoded_images as $item) {
                    // Check if it's a URL string
                    if (is_string($item) && !empty($item)) {
                        // It's already a URL string - add to set
                        $all_image_urls[$item] = true;
                    } else if (is_numeric($item)) {
                        // It's an attachment ID - convert to URL
                        $attachment_id = intval($item);
                        if ($attachment_id > 0) {
                            $image_url = wp_get_attachment_url($attachment_id);
                            if ($image_url && is_string($image_url)) {
                                $all_image_urls[$image_url] = true;
                            }
                        }
                    }
                }
            }
        }
        
        // Get serialized format (older format with attachment IDs)
        $serialized_images = get_post_meta($post_id, 'dpsp_pinterest_hidden_images', true);
        if (!empty($serialized_images)) {
            // Handle both serialized and unserialized data
            if (is_serialized($serialized_images)) {
                $attachment_ids = maybe_unserialize($serialized_images);
            } else if (is_array($serialized_images)) {
                $attachment_ids = $serialized_images;
            } else {
                $attachment_ids = array();
            }
            
            if (is_array($attachment_ids)) {
                foreach ($attachment_ids as $attachment_id) {
                    // Make sure we have a valid attachment ID (integer)
                    $attachment_id = intval($attachment_id);
                    if ($attachment_id > 0) {
                        $image_url = wp_get_attachment_url($attachment_id);
                        // Only add if we successfully got a URL
                        if ($image_url && is_string($image_url)) {
                            $all_image_urls[$image_url] = true;
                        }
                    }
                }
            }
        }
        
        // Convert unique URLs to PinnerPress format
        $hidden_images = array();
        foreach (array_keys($all_image_urls) as $url) {
            $hidden_images[] = array('url' => $url);
            $images_count++;
        }
        
        if (empty($hidden_images)) {
            return array(
                'success' => false,
                'message' => 'No hidden images found',
                'images_count' => 0
            );
        }
        
        // Get existing PinnerPress hidden images
        $existing_images = get_post_meta($post_id, '_pinnerpress_hidden_images', true);
        if (!empty($existing_images) && is_array($existing_images)) {
            // Add existing valid images to our URL set to prevent duplicates
            foreach ($existing_images as $img) {
                if (is_array($img) && isset($img['url'])) {
                    // Skip invalid entries (where URL is an integer or empty)
                    if (is_string($img['url']) && !empty($img['url'])) {
                        $all_image_urls[$img['url']] = true;
                    }
                } else if (is_string($img) && !empty($img)) {
                    // Old format - add to set
                    $all_image_urls[$img] = true;
                }
            }
            
            // Rebuild the hidden_images array with all unique URLs
            $hidden_images = array();
            foreach (array_keys($all_image_urls) as $url) {
                $hidden_images[] = array('url' => $url);
            }
        }
        
        // Save to PinnerPress format (serialized array)
        update_post_meta($post_id, '_pinnerpress_hidden_images', $hidden_images);
        
        // Run cleanup on this post to ensure no invalid data
        $this->cleanup_invalid_hidden_images($post_id);
        
        return array(
            'success' => true,
            'message' => 'Images migrated successfully',
            'images_count' => $images_count
        );
    }
    
    /**
     * Clean up invalid hidden images entries.
     * Removes entries where URL is not a valid string.
     *
     * @since    0.6.8
     * @param    int    $post_id  The post ID to clean
     * @return   bool   True if cleaned, false if no changes needed
     */
    public function cleanup_invalid_hidden_images($post_id = null) {
        global $wpdb;
        
        if ($post_id) {
            // Clean specific post
            $posts = array($post_id);
        } else {
            // Get all posts with hidden images
            $cache_key = 'pinnerpress_cleanup_posts';
            $posts = wp_cache_get($cache_key, 'pinnerpress');
            
            if ($posts === false) {
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Cleanup query with caching
                $posts = $wpdb->get_col(
                    "SELECT post_id FROM {$wpdb->postmeta} 
                     WHERE meta_key = '_pinnerpress_hidden_images'"
                );
                wp_cache_set($cache_key, $posts, 'pinnerpress', 300); // Cache for 5 minutes
            }
        }
        
        $cleaned_count = 0;
        
        foreach ($posts as $post_id) {
            $hidden_images = get_post_meta($post_id, '_pinnerpress_hidden_images', true);
            
            if (!empty($hidden_images) && is_array($hidden_images)) {
                $cleaned_images = array();
                $needs_cleaning = false;
                
                foreach ($hidden_images as $img) {
                    if (is_array($img) && isset($img['url'])) {
                        // Only keep entries with valid string URLs
                        if (is_string($img['url']) && !empty($img['url'])) {
                            $cleaned_images[] = $img;
                        } else {
                            $needs_cleaning = true;
                        }
                    }
                }
                
                if ($needs_cleaning) {
                    if (empty($cleaned_images)) {
                        // Delete meta if no valid images remain
                        delete_post_meta($post_id, '_pinnerpress_hidden_images');
                    } else {
                        // Update with cleaned array
                        update_post_meta($post_id, '_pinnerpress_hidden_images', $cleaned_images);
                    }
                    $cleaned_count++;
                }
            }
        }
        
        return $cleaned_count > 0;
    }
}
}
