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

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

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

    /**
     * Initialize the class and set its properties.
     *
     * @since    1.0.0
     */
    public function __construct() {
        // Register AJAX actions for migration
        add_action('wp_ajax_pinnerpress_scan_tasty_pins_data', array($this, 'scan_tasty_pins_data_ajax'));
        add_action('wp_ajax_pinnerpress_migrate_from_tasty_pins', array($this, 'migrate_from_tasty_pins_ajax'));
        add_action('wp_ajax_pinnerpress_migrate_tasty_pins_batch', array($this, 'migrate_batch_ajax'));
    }

    /**
     * Discover Tasty Pins settings in the database.
     *
     * @since    1.0.0
     * @return   array    Array of Tasty Pins options found
     */
    public function discover_tasty_pins_settings() {
        $settings = array();
        
        // Get main Tasty Pins settings
        $tasty_pins_settings = get_option('tasty_pins_settings');
        if ($tasty_pins_settings) {
            $settings['tasty_pins_settings'] = maybe_unserialize($tasty_pins_settings);
        }
        
        // Get follow box settings
        $follow_box = get_option('tasty_pins_follow_box');
        if ($follow_box) {
            $settings['tasty_pins_follow_box'] = maybe_unserialize($follow_box);
        }
        
        // Get banner settings
        $banner = get_option('tasty_pins_banner');
        if ($banner) {
            $settings['tasty_pins_banner'] = maybe_unserialize($banner);
        }
        
        return $settings;
    }

    /**
     * Find posts with Tasty Pins hidden images.
     *
     * @since    1.0.0
     * @return   array    Array of posts with hidden images
     */
    public function find_hidden_images() {
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.SlowDBQuery.slow_db_query_meta_value
        $hidden_images = $wpdb->get_results($wpdb->prepare(
            "SELECT post_id, meta_key, meta_value FROM {$wpdb->postmeta} \
             WHERE meta_key = %s AND meta_value != '' \
             ORDER BY post_id",
            'tp_pinterest_hidden_image'
        ));
        return $hidden_images;
    }

    /**
     * Count posts with Tasty Pins hidden images.
     *
     * @since    1.0.0
     * @return   int      Number of posts with hidden images
     */
    public function count_posts_with_hidden_images() {
        global $wpdb;
        // Count distinct posts with the specific meta key
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.SlowDBQuery.slow_db_query_meta_key
        $count = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT post_id) FROM {$wpdb->postmeta} WHERE meta_key = %s",
            'tp_pinterest_hidden_image'
        ));
        return $count;
    }

    /**
     * Count total hidden images across all posts.
     *
     * @since    1.0.0
     * @return   int      Total number of hidden images
     */
    public function count_total_hidden_images() {
        global $wpdb;
        // Fetch all non-empty meta values and aggregate counts in PHP (values are comma-separated IDs)
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.SlowDBQuery.slow_db_query_meta_value
        $values = $wpdb->get_col($wpdb->prepare(
            "SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value != ''",
            'tp_pinterest_hidden_image'
        ));
        $total_count = 0;
        foreach ($values as $value) {
            if ($value === '') {
                continue;
            }
            if (strpos($value, ',') !== false) {
                $ids = explode(',', $value);
                $total_count += count(array_filter($ids, 'is_numeric'));
            } else {
                $total_count++;
            }
        }
        return $total_count;
    }

    /**
     * Check if Tasty Pins plugin is active.
     *
     * @since    1.0.0
     * @return   bool     True if Tasty Pins is active, false otherwise
     */
    public function is_tasty_pins_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 Tasty Pins plugin
        foreach ($active_plugins as $plugin) {
            $plugin_lower = strtolower($plugin);
            if (strpos($plugin_lower, 'tasty-pins') !== false ||
                strpos($plugin_lower, 'tastypins') !== false) {
                return true;
            }
        }
        
        // Also check if any Tasty Pins options exist
        if (get_option('tasty_pins_settings') || 
            get_option('tasty_pins_follow_box') ||
            get_option('tasty_pins_banner')) {
            return true;
        }
        
        return false;
    }

    /**
     * Analyze Tasty Pins data for migration.
     *
     * @since    1.0.0
     * @return   array    Analysis of Tasty Pins data
     */
    public function analyze_tasty_pins_data() {
        $analysis = array(
            'settings' => $this->discover_tasty_pins_settings(),
            'posts_with_images' => $this->count_posts_with_hidden_images(),
            'total_images' => $this->count_total_hidden_images(),
            'tasty_pins_active' => $this->is_tasty_pins_active()
        );
        
        // Add detailed settings analysis
        if (!empty($analysis['settings']['tasty_pins_settings'])) {
            $settings = $analysis['settings']['tasty_pins_settings'];
            $analysis['button_settings'] = array(
                'custom_text' => isset($settings['custom_button_label_text']) ? $settings['custom_button_label_text'] : '',
                'button_color' => isset($settings['hover_button_color']) ? $settings['hover_button_color'] : '',
                'position' => isset($settings['hover_button_position']) ? $settings['hover_button_position'] : '',
                'min_width' => isset($settings['minimum_image_width']) ? $settings['minimum_image_width'] : '',
                'min_height' => isset($settings['minimum_image_height']) ? $settings['minimum_image_height'] : ''
            );
        }
        
        // Add debug information about hidden images
        $analysis['debug_hidden_images'] = $this->get_debug_hidden_images_info();
        
        return $analysis;
    }
    
    /**
     * Get debug information about hidden images in the database.
     *
     * @since    1.0.0
     * @return   array    Debug information
     */
    public function get_debug_hidden_images_info() {
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.SlowDBQuery.slow_db_query_meta_value
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value != '' ORDER BY post_id",
            'tp_pinterest_hidden_image'
        ));
        $debug_info = array(
            'total_meta_entries' => count($rows),
            'posts_breakdown' => array()
        );
        foreach ($rows as $row) {
            $post_id = (int) $row->post_id;
            $meta_value = (string) $row->meta_value;
            if (!isset($debug_info['posts_breakdown'][$post_id])) {
                $debug_info['posts_breakdown'][$post_id] = array(
                    'count' => 0,
                    'images' => array(),
                    'raw_value' => ''
                );
            }
            $debug_info['posts_breakdown'][$post_id]['raw_value'] = $meta_value;
            if (strpos($meta_value, ',') !== false) {
                $ids = explode(',', $meta_value);
                $debug_info['posts_breakdown'][$post_id]['count'] = count($ids);
                $debug_info['posts_breakdown'][$post_id]['images'] = array_map('trim', $ids);
            } else {
                $debug_info['posts_breakdown'][$post_id]['count'] = 1;
                $debug_info['posts_breakdown'][$post_id]['images'][] = $meta_value;
            }
        }
        return $debug_info;
    }

    /**
     * Migrate Pin Button Settings from Tasty Pins to PinnerPress.
     *
     * @since    1.0.0
     * @return   array    Migration results
     */
    public function migrate_pin_button_settings() {
        $results = array(
            'success' => false,
            'messages' => array()
        );
        
        $tasty_pins_settings = get_option('tasty_pins_settings');
        if (!$tasty_pins_settings) {
            $results['messages'][] = 'No Tasty Pins button settings found';
            return $results;
        }
        
        $settings = maybe_unserialize($tasty_pins_settings);
        if (!is_array($settings)) {
            $results['messages'][] = 'Could not parse Tasty Pins settings';
            return $results;
        }
        
        $migrated = array();
        
        // Migrate custom button text
        if (isset($settings['custom_button_label_enabled']) && 
            $settings['custom_button_label_enabled'] === 'yes' &&
            isset($settings['custom_button_label_text'])) {
            $button_text = sanitize_text_field($settings['custom_button_label_text']);
            update_option('pinnerpress_custom_button_text', $button_text);
            $migrated[] = 'Button text: "' . $button_text . '"';
        }
        
        // Migrate button color
        if (isset($settings['hover_button_color'])) {
            $color = $this->validate_color_format($settings['hover_button_color']);
            if ($color) {
                update_option('pinnerpress_hover_button_color', $color); // Fixed: use correct option name
                $migrated[] = 'Button color: ' . $color;
            }
        }
        
        // Migrate button position
        if (isset($settings['hover_button_position'])) {
            $position = $this->convert_position_format($settings['hover_button_position']);
            update_option('pinnerpress_hover_button_position', $position); // Fixed option name
            $migrated[] = 'Button position: ' . $settings['hover_button_position'] . ' → ' . $position;
        }
        
        // Migrate minimum image size
        $min_size = 0;
        if (isset($settings['minimum_image_height']) && !empty($settings['minimum_image_height'])) {
            $min_size = intval($settings['minimum_image_height']);
        } elseif (isset($settings['minimum_image_width']) && !empty($settings['minimum_image_width'])) {
            $min_size = intval($settings['minimum_image_width']);
        }
        
        if ($min_size > 0) {
            update_option('pinnerpress_minimum_image_size', $min_size);
            $migrated[] = 'Minimum image size: ' . $min_size . 'px';
        }
        
        // Migrate button shape
        if (isset($settings['hover_button_shape'])) {
            update_option('pinnerpress_pin_button_shape', $settings['hover_button_shape']);
            $migrated[] = 'Button shape: ' . $settings['hover_button_shape'];
        }
        
        // Migrate image overlay
        if (isset($settings['image_overlay_enabled']) && $settings['image_overlay_enabled'] === 'yes') {
            update_option('pinnerpress_enable_image_overlay', true);
            $migrated[] = 'Image overlay enabled';
        }
        
        if (!empty($migrated)) {
            $results['success'] = true;
            $results['messages'] = $migrated;
        } else {
            $results['messages'][] = 'No button settings to migrate';
        }
        
        return $results;
    }

    /**
     * Migrate Follow Box Settings from Tasty Pins to PinnerPress.
     *
     * @since    1.0.0
     * @return   array    Migration results
     */
    public function migrate_follow_box_settings() {
        $results = array(
            'success' => false,
            'messages' => array()
        );
        
        $follow_box = get_option('tasty_pins_follow_box');
        if (!$follow_box) {
            $results['messages'][] = 'No Tasty Pins follow box settings found';
            return $results;
        }
        
        $settings = maybe_unserialize($follow_box);
        if (!is_array($settings)) {
            $results['messages'][] = 'Could not parse follow box settings';
            return $results;
        }
        
        $migrated = array();
        
        // Enable follow box if it was enabled in Tasty Pins
        if (isset($settings['enabled']) && $settings['enabled'] === 'yes') {
            update_option('pinnerpress_follow_box_status', 'on'); // Fixed: use correct option name
            $migrated[] = 'Follow box enabled';
        }
        
        // Migrate header image (follow box background)
        if (isset($settings['header_image_url']) && !empty($settings['header_image_url'])) {
            $url = esc_url_raw($settings['header_image_url']);
            // This is the header/background image for the follow box
            update_option('pinnerpress_header_image', $url); // Fixed: use correct option name
            $migrated[] = 'Follow box header/background image migrated';
        }
        
        // Migrate logo/profile image
        if (isset($settings['logo_image_url']) && !empty($settings['logo_image_url'])) {
            $url = esc_url_raw($settings['logo_image_url']);
            // Logo image in Tasty Pins is actually the profile image
            update_option('pinnerpress_profile_image', $url); // Set as profile image
            update_option('pinnerpress_follow_box_logo_image', $url); // Also keep as logo
            $migrated[] = 'Profile image migrated';
        }
        
        // Migrate account information
        if (isset($settings['account_name'])) {
            update_option('pinnerpress_follow_box_account_name', sanitize_text_field($settings['account_name']));
            $migrated[] = 'Account name: ' . $settings['account_name'];
        }
        
        if (isset($settings['account_description'])) {
            update_option('pinnerpress_follow_box_description', sanitize_text_field($settings['account_description']));
            $migrated[] = 'Account description migrated';
        }
        
        if (isset($settings['account_url']) && !empty($settings['account_url'])) {
            $url = $this->validate_pinterest_url($settings['account_url']);
            if ($url) {
                update_option('pinnerpress_pinterest_url', $url);
                $migrated[] = 'Pinterest URL: ' . $url;
                
                // Extract and save username from URL
                $username = $this->extract_pinterest_username($url);
                if ($username) {
                    update_option('pinnerpress_pinterest_display_name', $username);
                    $migrated[] = 'Pinterest username: @' . $username;
                }
            }
        }
        
        // Migrate color settings
        if (isset($settings['logo_background_color'])) {
            $color = $this->validate_color_format($settings['logo_background_color']);
            if ($color) {
                update_option('pinnerpress_follow_box_logo_bg_color', $color);
                $migrated[] = 'Logo background color: ' . $color;
            }
        }
        
        if (isset($settings['button_background_color'])) {
            $color = $this->validate_color_format($settings['button_background_color']);
            if ($color) {
                update_option('pinnerpress_follow_box_button_bg_color', $color);
                $migrated[] = 'Button background color: ' . $color;
            }
        }
        
        if (isset($settings['button_text_color'])) {
            $color = $this->validate_color_format($settings['button_text_color']);
            if ($color) {
                update_option('pinnerpress_follow_box_button_text_color', $color);
                $migrated[] = 'Button text color: ' . $color;
            }
        }
        
        // Migrate affiliate settings
        if (isset($settings['shareasale_affiliate_id']) && !empty($settings['shareasale_affiliate_id'])) {
            update_option('pinnerpress_shareasale_affiliate_id', sanitize_text_field($settings['shareasale_affiliate_id']));
            $migrated[] = 'ShareASale affiliate ID migrated';
        }
        
        if (!empty($migrated)) {
            $results['success'] = true;
            $results['messages'] = $migrated;
        } else {
            $results['messages'][] = 'No follow box settings to migrate';
        }
        
        return $results;
    }

    /**
     * Migrate Banner Settings from Tasty Pins to PinnerPress.
     *
     * @since    1.0.0
     * @return   array    Migration results
     */
    public function migrate_banner_settings() {
        $results = array(
            'success' => false,
            'messages' => array()
        );
        
        $banner = get_option('tasty_pins_banner');
        if (!$banner) {
            $results['messages'][] = 'No Tasty Pins banner settings found';
            return $results;
        }
        
        $settings = maybe_unserialize($banner);
        if (!is_array($settings)) {
            $results['messages'][] = 'Could not parse banner settings';
            return $results;
        }
        
        $migrated = array();
        
        // Enable banner if it was enabled in Tasty Pins
        if (isset($settings['enabled']) && $settings['enabled'] === 'on') {
            update_option('pinnerpress_banner_status', 'on'); // Fixed: use correct option name
            $migrated[] = 'Banner enabled';
        }
        
        // Migrate background color
        if (isset($settings['background_color'])) {
            $color = $this->validate_color_format($settings['background_color']);
            if ($color) {
                update_option('pinnerpress_banner_bg_color', $color);
                $migrated[] = 'Banner background color: ' . $color;
            }
        }
        
        // Migrate text color
        if (isset($settings['text_color'])) {
            $color = $this->validate_color_format($settings['text_color']);
            if ($color) {
                update_option('pinnerpress_banner_text_color', $color);
                $migrated[] = 'Banner text color: ' . $color;
            }
        }
        
        // Migrate banner text
        if (isset($settings['banner_label_text'])) {
            update_option('pinnerpress_banner_text', sanitize_text_field($settings['banner_label_text']));
            $migrated[] = 'Banner text: "' . $settings['banner_label_text'] . '"';
        }
        
        if (!empty($migrated)) {
            $results['success'] = true;
            $results['messages'] = $migrated;
        } else {
            $results['messages'][] = 'No banner settings to migrate';
        }
        
        return $results;
    }

    /**
     * Migrate hidden images from Tasty Pins to PinnerPress format.
     *
     * @since    1.0.0
     * @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->get_posts_with_hidden_images();
        
        if (empty($posts_with_images)) {
            $results['messages'][] = 'No hidden images found in Tasty Pins data';
            return $results;
        }
        
        foreach ($posts_with_images as $post_id) {
            $result = $this->migrate_post_hidden_images($post_id);
            if ($result['success']) {
                $results['migrated_posts']++;
                $results['migrated_images'] += $result['images_count'];
            } else {
                $results['errors'][] = "Post {$post_id}: " . $result['message'];
            }
        }
        
        if ($results['migrated_posts'] > 0) {
            $results['success'] = true;
            $results['messages'][] = "Successfully migrated {$results['migrated_images']} hidden images from {$results['migrated_posts']} posts";
        }
        
        return $results;
    }

    /**
     * Get posts that have hidden images.
     *
     * @since    1.0.0
     * @param    int    $limit   Number of posts to return
     * @param    int    $offset  Offset for pagination
     * @return   array  Array of post IDs
     */
    public function get_posts_with_hidden_images($limit = -1, $offset = 0) {
        global $wpdb;
        if ($limit > 0) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.SlowDBQuery.slow_db_query_meta_value
            $post_ids = $wpdb->get_col(
                $wpdb->prepare(
                    "SELECT DISTINCT post_id FROM {$wpdb->postmeta} \
                     WHERE meta_key = %s AND meta_value != '' \
                     ORDER BY post_id ASC \
                     LIMIT %d OFFSET %d",
                    'tp_pinterest_hidden_image', (int) $limit, (int) $offset
                )
            );
        } else {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.SlowDBQuery.slow_db_query_meta_key,WordPress.DB.SlowDBQuery.slow_db_query_meta_value
            $post_ids = $wpdb->get_col(
                $wpdb->prepare(
                    "SELECT DISTINCT post_id FROM {$wpdb->postmeta} \
                     WHERE meta_key = %s AND meta_value != '' \
                     ORDER BY post_id ASC",
                    'tp_pinterest_hidden_image'
                )
            );
        }
        return array_map('intval', $post_ids);
    }

    /**
     * Migrate hidden images for a single post.
     *
     * @since    1.0.0
     * @param    int    $post_id  The post ID
     * @return   array  Migration result
     */
    public function migrate_post_hidden_images($post_id) {
        // Get tp_pinterest_hidden_image entry for this post (should be one entry with comma-separated IDs)
        $tasty_pins_value = get_post_meta($post_id, 'tp_pinterest_hidden_image', true);
        
        if (empty($tasty_pins_value)) {
            return array(
                'success' => false,
                'message' => 'No hidden images found',
                'images_count' => 0
            );
        }
        
        $hidden_images = array();
        $images_count = 0;
        $image_ids = array();
        
        // Parse the comma-separated list of IDs
        if (strpos($tasty_pins_value, ',') !== false) {
            // Multiple IDs
            $image_ids = array_map('trim', explode(',', $tasty_pins_value));
        } else {
            // Single ID
            $image_ids = array(trim($tasty_pins_value));
        }
        
        // Convert each ID to a URL
        foreach ($image_ids as $image_data) {
            $url = '';
            
            // Check if it's an attachment ID or URL
            if (is_numeric($image_data)) {
                // It's an attachment ID
                $attachment_id = intval($image_data);
                if ($attachment_id > 0) {
                    $url = wp_get_attachment_url($attachment_id);
                }
            } else if (!empty($image_data)) {
                // It might be a URL already
                $url = $image_data;
            }
            
            if (!empty($url) && filter_var($url, FILTER_VALIDATE_URL)) {
                $hidden_images[] = array('url' => esc_url_raw($url));
                $images_count++;
            }
        }
        
        if (empty($hidden_images)) {
            return array(
                'success' => false,
                'message' => 'No valid image URLs found from IDs: ' . $tasty_pins_value,
                'images_count' => 0
            );
        }
        
        // Get existing PinnerPress hidden images and merge
        $existing_images = get_post_meta($post_id, '_pinnerpress_hidden_images', true);
        if (!empty($existing_images) && is_array($existing_images)) {
            // Merge and remove duplicates
            $all_urls = array();
            
            // Add existing images
            foreach ($existing_images as $img) {
                if (isset($img['url']) && !empty($img['url'])) {
                    $all_urls[$img['url']] = true;
                }
            }
            
            // Add new images
            foreach ($hidden_images as $img) {
                $all_urls[$img['url']] = true;
            }
            
            // Rebuild array
            $hidden_images = array();
            foreach (array_keys($all_urls) as $url) {
                $hidden_images[] = array('url' => $url);
            }
        }
        
        // Save to PinnerPress format
        update_post_meta($post_id, '_pinnerpress_hidden_images', $hidden_images);
        
        return array(
            'success' => true,
            'message' => 'Images migrated successfully',
            'images_count' => $images_count
        );
    }

    /**
     * Validate and sanitize color format.
     *
     * @since    1.0.0
     * @param    string   $color    Color value to validate
     * @return   string             Validated color or empty string
     */
    private function validate_color_format($color) {
        if (empty($color)) {
            return '';
        }
        
        // Handle hex colors
        if (preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $color)) {
            return $color;
        }
        
        // Handle RGB/RGBA
        if (preg_match('/^rgba?\([\d\s,\.]+\)$/i', $color)) {
            return $color;
        }
        
        // Try adding # if it looks like hex without it
        if (preg_match('/^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/', $color)) {
            return '#' . $color;
        }
        
        return '';
    }

    /**
     * Convert Tasty Pins position format to PinnerPress format.
     *
     * @since    1.0.0
     * @param    string   $position    Tasty Pins position
     * @return   string                PinnerPress position
     */
    private function convert_position_format($position) {
        $position_map = array(
            'top-left' => 'top_left',
            'top-right' => 'top_right',
            'bottom-left' => 'bottom_left',
            'bottom-right' => 'bottom_right',
            'center' => 'top_left' // Default center to top_left
        );
        
        return isset($position_map[$position]) ? $position_map[$position] : 'top_left';
    }

    /**
     * Validate Pinterest URL format.
     *
     * @since    1.0.0
     * @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) {
            // If not a Pinterest URL, try to construct one
            $username = trim($url, '/@');
            if (!empty($username)) {
                return 'https://www.pinterest.com/' . $username . '/';
            }
            return false;
        }
        
        return esc_url_raw($url);
    }
    
    /**
     * Extract Pinterest username from URL.
     *
     * @since    1.0.0
     * @param    string   $url    Pinterest URL
     * @return   string           Username or empty string
     */
    private function extract_pinterest_username($url) {
        if (empty($url)) {
            return '';
        }
        
        // Parse URL to get path
        $parsed = wp_parse_url($url);
        if (!isset($parsed['path'])) {
            return '';
        }
        
        // Remove leading/trailing slashes and split by /
        $path = trim($parsed['path'], '/');
        $parts = explode('/', $path);
        
        // First part should be the username
        if (!empty($parts[0])) {
            // Clean up the username (remove any special characters that shouldn't be there)
            $username = preg_replace('/[^a-zA-Z0-9_-]/', '', $parts[0]);
            return sanitize_text_field($username);
        }
        
        return '';
    }

    /**
     * AJAX handler for scanning Tasty Pins data.
     *
     * @since    1.0.0
     */
    public function scan_tasty_pins_data_ajax() {
        // Check nonce and permissions
        $nonce = isset($_POST['nonce']) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
        if (!wp_verify_nonce($nonce, 'pinnerpress_admin_nonce') || !current_user_can('manage_options')) {
            wp_die('Security check failed');
        }
        
        $data = $this->analyze_tasty_pins_data();
        
        wp_send_json_success($data);
    }

    /**
     * AJAX handler for migrating from Tasty Pins.
     *
     * @since    1.0.0
     */
    public function migrate_from_tasty_pins_ajax() {
        // Check nonce and permissions
        $nonce = isset($_POST['nonce']) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
        if (!wp_verify_nonce($nonce, 'pinnerpress_admin_nonce') || !current_user_can('manage_options')) {
            wp_die('Security check failed');
        }
        
        // Initialize migration session
        $migration_id = 'tasty_pins_migration_' . time();
        $batch_size = 10; // Process 10 posts at a time
        
        // Count total posts with hidden images
        $total_posts = count($this->get_posts_with_hidden_images());
        
        set_transient('pinnerpress_migration_' . $migration_id, array(
            'started' => current_time('mysql'),
            'status' => 'starting',
            'settings_done' => false,
            'images_done' => false,
            'batch_size' => $batch_size,
            'current_batch' => 0,
            'total_posts' => $total_posts,
            'processed_posts' => 0
        ), 3600); // 1 hour expiry
        
        $results = array(
            'success' => true,
            'migration_id' => $migration_id,
            'use_batch_processing' => $total_posts > 0,
            'messages' => array('Migration initialized...'),
            'settings_results' => array(),
            'total_posts' => $total_posts,
            'batch_size' => $batch_size
        );
        
        // Migrate settings first
        $button_result = $this->migrate_pin_button_settings();
        $results['settings_results']['button'] = $button_result;
        
        $follow_box_result = $this->migrate_follow_box_settings();
        $results['settings_results']['follow_box'] = $follow_box_result;
        
        $banner_result = $this->migrate_banner_settings();
        $results['settings_results']['banner'] = $banner_result;
        
        // Update migration session
        $migration_data = get_transient('pinnerpress_migration_' . $migration_id);
        $migration_data['settings_done'] = true;
        set_transient('pinnerpress_migration_' . $migration_id, $migration_data, 3600);
        
        wp_send_json_success($results);
    }

    /**
     * AJAX handler for batch processing migration.
     *
     * @since    1.0.0
     */
    public function migrate_batch_ajax() {
        // Check nonce and permissions
        $nonce = isset($_POST['nonce']) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
        if (!wp_verify_nonce($nonce, 'pinnerpress_admin_nonce') || !current_user_can('manage_options')) {
            wp_die('Security check failed');
        }
        
        $migration_id = isset($_POST['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');
            $migration_data['images_done'] = true;
            update_option('pinnerpress_tasty_pins_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);
    }
}
}