<?php
namespace Blogibot\Handlers;

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

/**
 * Content Analyzer Handler
 * Handles content scanning and analysis functionality
 */
class ContentAnalyzerHandler
{
    /**
     * Handle start content scan AJAX request
     */
    public static function handle_start_scan()
    {
        // Verify nonce
        if (!wp_verify_nonce($_POST['nonce'] ?? '', 'blogibot_content_scan')) {
            wp_send_json_error(['message' => 'Security check failed. Please refresh the page and try again.']);
            return;
        }

        // Check user capabilities
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'You do not have permission to scan content.']);
            return;
        }

        // Check if scan is already in progress
        if (get_transient('blogibot_content_scan_in_progress')) {
            wp_send_json_error(['message' => 'Content scan is already in progress.']);
            return;
        }

        try {
            // Check license status
            require_once WP_PLUGIN_DIR . '/blogibot/src/License/LicenseManager.php';
            
            if (!\Blog82AI_License_Manager::is_license_valid()) {
                wp_send_json_error(['message' => 'Valid license required for content analysis. Please check your license status.']);
                return;
            }

            // Get license data
            $license_data = \Blog82AI_License_Manager::get_license_data();
            
            if (empty($license_data['license_key'])) {
                wp_send_json_error(['message' => 'License key not found. Please activate your license first.']);
                return;
            }

            // Start the scan process using an async/resumable approach
            $scan_id = self::start_background_scan($license_data);

            if ($scan_id) {
                wp_send_json_success([
                    'message' => 'Content scan started successfully',
                    'scan_id' => $scan_id
                ]);
            } else {
                wp_send_json_error(['message' => 'Failed to start content scan. Please try again.']);
            }

        } catch (\Exception $e) {
            error_log('Blogibot Content Scan Error: ' . $e->getMessage());
            wp_send_json_error(['message' => 'An error occurred while starting the scan.']);
        }
    }

    /**
     * Handle get scan progress AJAX request
     */
    public static function handle_get_progress()
    {
        // Verify nonce
        if (!wp_verify_nonce($_POST['nonce'] ?? '', 'blogibot_content_scan')) {
            wp_send_json_error(['message' => 'Security check failed.']);
            return;
        }

        $progress_data = self::get_scan_progress();
        wp_send_json_success(['data' => $progress_data]);
    }

    /**
     * Handle get scan log AJAX request
     */
    public static function handle_get_log()
    {
        // Verify nonce
        if (!wp_verify_nonce($_POST['nonce'] ?? '', 'blogibot_content_scan')) {
            wp_send_json_error(['message' => 'Security check failed.']);
            return;
        }

        $log_data = self::get_scan_log();
        wp_send_json_success(['data' => $log_data]);
    }

    /**
     * Handle process batch AJAX request (direct batch processing)
     */
    public static function handle_process_batch()
    {
        // Verify nonce
        if (!wp_verify_nonce($_POST['nonce'] ?? '', 'blogibot_content_scan')) {
            wp_send_json_error(['message' => 'Security check failed.']);
            return;
        }

        // Check user capabilities
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'You do not have permission to scan content.']);
            return;
        }

        $scan_id = sanitize_text_field($_POST['scan_id'] ?? '');
        $page = intval($_POST['page'] ?? 1);

        if (empty($scan_id)) {
            wp_send_json_error(['message' => 'Invalid scan ID.']);
            return;
        }

        try {
            // Get license data from transient
            $license_data = get_transient("blogibot_scan_license_{$scan_id}");
            if (empty($license_data)) {
                wp_send_json_error(['message' => 'Scan session expired. Please start a new scan.']);
                return;
            }

            // Process this batch
            $result = self::process_single_batch($scan_id, $page, $license_data);

            if ($result['success']) {
                wp_send_json_success([
                    'message' => 'Batch processed successfully',
                    'progress' => $result['progress'],
                    'has_more' => $result['has_more'],
                    'next_page' => $result['next_page'] ?? null
                ]);
            } else {
                wp_send_json_error(['message' => $result['error'] ?? 'Batch processing failed']);
            }

        } catch (\Exception $e) {
            error_log('Blogibot Process Batch Error: ' . $e->getMessage());
            wp_send_json_error(['message' => 'An error occurred while processing the batch.']);
        }
    }

    /**
     * Handle reset scan AJAX request (for debugging stuck scans)
     */
    public static function handle_reset_scan()
    {
        // Verify nonce
        if (!wp_verify_nonce($_POST['nonce'] ?? '', 'blogibot_content_scan')) {
            wp_send_json_error(['message' => 'Security check failed.']);
            return;
        }

        // Check user capabilities
        if (!current_user_can('edit_posts')) {
            wp_send_json_error(['message' => 'You do not have permission to reset scan.']);
            return;
        }

        try {
            // Clear all scan-related transients and options
            delete_transient('blogibot_content_scan_in_progress');
            
            // Reset scan progress
            update_option('blogibot_scan_progress', [
                'status' => 'not_started',
                'percentage' => 0,
                'message' => 'Scan reset by user',
                'posts_processed' => 0,
                'total_posts' => 0
            ]);

            // Clear any scheduled cron events
            wp_clear_scheduled_hook('blogibot_process_content_scan');

            // Add reset log entry
            $scan_log = get_option('blogibot_scan_log', []);
            $scan_log[] = [
                'timestamp' => current_time('timestamp'),
                'level' => 'info',
                'message' => 'Scan process manually reset by user'
            ];
            update_option('blogibot_scan_log', $scan_log);

            wp_send_json_success(['message' => 'Scan process reset successfully']);

        } catch (\Exception $e) {
            error_log('Blogibot Reset Scan Error: ' . $e->getMessage());
            wp_send_json_error(['message' => 'Failed to reset scan process']);
        }
    }

    /**
     * Start background content scan
     */
    private static function start_background_scan($license_data)
    {
        // Log scan start for debugging
        error_log('Blogibot: Starting content scan at ' . date('Y-m-d H:i:s'));
        error_log('Blogibot: License key: ' . (isset($license_data['license_key']) ? 'Present' : 'Missing'));
        error_log('Blogibot: Domain: ' . (isset($license_data['domain']) ? $license_data['domain'] : 'Missing'));

        // Create a scan id and persist minimal scan state
        $scan_id = 'scan_' . uniqid('', true);

        $initial_state = [
            'scan_id' => $scan_id,
            'status' => 'queued',
            'percentage' => 0,
            'message' => 'Scan queued',
            'posts_processed' => 0,
            'total_posts' => 0,
            'page' => 0,
            'batch_size' => apply_filters('blogibot_content_scan_batch_size', 10),
            'start_time' => current_time('timestamp')
        ];

        // Persist license data in a transient keyed by scan_id (keeps cron/action args small)
        set_transient("blogibot_scan_license_{$scan_id}", $license_data, 12 * HOUR_IN_SECONDS);
        // Determine total posts up-front so the UI can show progress immediately
        // Only count posts from the last 14 days
        try {
            $date_14_days_ago = date('Y-m-d', strtotime('-14 days'));
            $count_query = new \WP_Query([
                'post_type' => 'post',
                'post_status' => 'publish',
                'posts_per_page' => -1,
                'fields' => 'ids',
                'date_query' => [
                    [
                        'after' => $date_14_days_ago,
                        'inclusive' => true,
                    ],
                ],
            ]);
            $total_posts = $count_query->found_posts;
            $initial_state['total_posts'] = $total_posts;
            error_log('Blogibot: Found ' . $total_posts . ' posts from the last 14 days');
        } catch (\Throwable $e) {
            $initial_state['total_posts'] = 0;
            error_log('Blogibot: Error counting posts: ' . $e->getMessage());
        }

        update_option("blogibot_scan_state_{$scan_id}", $initial_state);
        set_transient('blogibot_content_scan_in_progress', $scan_id, 12 * HOUR_IN_SECONDS);

        // Initialize the public progress option so the frontend will begin polling
        update_option('blogibot_scan_progress', [
            'status' => 'in_progress',
            'percentage' => 0,
            'message' => 'Initializing content scan...',
            'posts_processed' => 0,
            'total_posts' => 0,
            'start_time' => $initial_state['start_time']
        ]);

        // Schedule first batch using Action Scheduler if available, otherwise fallback to WP cron
        $args = ['scan_id' => $scan_id, 'page' => 1];

        if (function_exists('as_enqueue_async_action')) {
            try {
                as_enqueue_async_action('blogibot_process_scan_batch', $args);
                error_log('Blogibot: Enqueued first Action Scheduler job for scan ' . $scan_id);
            } catch (\Throwable $e) {
                error_log('Blogibot: Action Scheduler enqueue failed: ' . $e->getMessage());
                // Fallback to WP cron schedule
                wp_schedule_single_event(time() + 5, 'blogibot_process_content_scan', [$args]);
                wp_schedule_single_event(time() + 30, 'blogibot_process_content_scan_fallback', [$args]);
            }
        } else {
            // Fallback: use WP cron to schedule the first batch
            if (!wp_next_scheduled('blogibot_process_content_scan')) {
                wp_schedule_single_event(time() + 5, 'blogibot_process_content_scan', [$args]);
                wp_schedule_single_event(time() + 30, 'blogibot_process_content_scan_fallback', [$args]);
                error_log('Blogibot: WP cron scheduled first batch for scan ' . $scan_id);
            } else {
                error_log('Blogibot: WP cron job already scheduled');
            }
        }

        // Fast-path: for small sites, run the first batch synchronously so users see immediate progress
        try {
            // Use the already calculated total_posts from above (which includes 14-day filter)
            $total_posts = $initial_state['total_posts'] ?? 0;
            $batch_size = $initial_state['batch_size'] ?? apply_filters('blogibot_content_scan_batch_size', 10);
            if ($total_posts > 0 && $total_posts <= $batch_size) {
                error_log('Blogibot: Small site detected, running first batch synchronously for scan ' . $scan_id);
                // Update scan state total and progress before running
                $initial_state['total_posts'] = $total_posts;
                $initial_state['status'] = 'in_progress';
                update_option("blogibot_scan_state_{$scan_id}", $initial_state);
                update_option('blogibot_scan_progress', [
                    'status' => 'in_progress',
                    'percentage' => 0,
                    'message' => 'Initializing content scan...',
                    'posts_processed' => 0,
                    'total_posts' => $total_posts,
                    'start_time' => $initial_state['start_time']
                ]);

                // Run the batch worker inline
                try {
                    self::process_scan_batch_action(['scan_id' => $scan_id, 'page' => 1]);
                } catch (\Throwable $e) {
                    error_log('Blogibot: Inline batch execution failed: ' . $e->getMessage());
                }
            }
        } catch (\Throwable $e) {
            error_log('Blogibot: Failed to determine total posts for fast-path: ' . $e->getMessage());
        }

        // Note: We no longer run inline batches here.
        // JavaScript will handle batch processing via AJAX calls,
        // providing immediate progress feedback without relying on background workers.

        return $scan_id;
    }

    /**
     * Process a single batch of posts (used by both AJAX and background workers)
     */
    private static function process_single_batch($scan_id, $page, $license_data)
    {
        $batch_size = apply_filters('blogibot_content_scan_batch_size', 10);

        // Get scan state
        $scan_state = get_option("blogibot_scan_state_{$scan_id}", []);
        if (empty($scan_state)) {
            return ['success' => false, 'error' => 'Scan state not found'];
        }

        $total_posts = $scan_state['total_posts'] ?? 0;
        $posts_processed = $scan_state['posts_processed'] ?? 0;

        // Calculate date 14 days ago for filtering recent posts
        $date_14_days_ago = date('Y-m-d', strtotime('-14 days'));

        // Query posts for this page (only posts from last 14 days)
        $posts_query = new \WP_Query([
            'post_type' => 'post',
            'post_status' => 'publish',
            'posts_per_page' => $batch_size,
            'paged' => $page,
            'fields' => '',
            'date_query' => [
                [
                    'after' => $date_14_days_ago,
                    'inclusive' => true,
                ],
            ],
        ]);

        $posts = $posts_query->posts;
        $batch_data = [];
        $yoast_active = is_plugin_active('wordpress-seo/wp-seo.php');

        foreach ($posts as $post) {
            $post_id = $post->ID;
            $post_data = self::extract_post_data($post_id, $yoast_active);
            if ($post_data) {
                $batch_data[] = $post_data;
                $posts_processed++;
            }
        }

        // Send batch to API
        $api_success = true;
        if (!empty($batch_data)) {
            $api_result = self::send_content_to_api($batch_data, $license_data);

            $scan_log = get_option('blogibot_scan_log', []);
            if ($api_result['success']) {
                $scan_log[] = [
                    'timestamp' => current_time('timestamp'),
                    'level' => 'success',
                    'message' => "Batch page {$page} sent successfully (" . count($batch_data) . " posts)"
                ];

                // Store fingerprints if returned
                if (isset($api_result['data']['results']['fingerprints'])) {
                    $fingerprints = $api_result['data']['results']['fingerprints'];
                    $existing_fingerprints = get_option('blogibot_content_fingerprints', []);
                    foreach ($fingerprints as $fingerprint) {
                        $existing_fingerprints[$fingerprint['post_id']] = [
                            'hash' => $fingerprint['hash'],
                            'fingerprint_id' => $fingerprint['fingerprint_id'],
                            'action' => $fingerprint['action'],
                            'synced_at' => current_time('timestamp')
                        ];
                    }
                    update_option('blogibot_content_fingerprints', $existing_fingerprints);
                }
            } else {
                $scan_log[] = [
                    'timestamp' => current_time('timestamp'),
                    'level' => 'warning',
                    'message' => "Batch page {$page} failed: " . ($api_result['error'] ?? 'Unknown')
                ];
                $api_success = false;
            }

            update_option('blogibot_scan_log', $scan_log);
        }

        // Update progress
        $percentage = $total_posts > 0 ? round(($posts_processed / $total_posts) * 100, 1) : 100;
        $max_pages = $total_posts > 0 ? ceil($total_posts / $batch_size) : 0;
        $has_more = $page < $max_pages;
        $status = $has_more ? 'in_progress' : 'completed';

        $scan_state['posts_processed'] = $posts_processed;
        $scan_state['percentage'] = $percentage;
        $scan_state['last_page'] = $page;
        $scan_state['status'] = $status;
        update_option("blogibot_scan_state_{$scan_id}", $scan_state);

        update_option('blogibot_scan_progress', [
            'status' => $status,
            'percentage' => $percentage,
            'message' => "Processed {$posts_processed} of {$total_posts} posts",
            'posts_processed' => $posts_processed,
            'total_posts' => $total_posts,
            'start_time' => $scan_state['start_time'] ?? current_time('timestamp')
        ]);

        // If completed, clean up
        if (!$has_more) {
            $end_time = current_time('timestamp');
            $scan_state['status'] = 'completed';
            $scan_state['end_time'] = $end_time;
            update_option("blogibot_scan_state_{$scan_id}", $scan_state);
            update_option('blogibot_last_content_scan', $end_time);
            update_option('blogibot_total_posts_scanned', $posts_processed);
            delete_transient('blogibot_content_scan_in_progress');
        }

        return [
            'success' => $api_success,
            'progress' => [
                'status' => $status,
                'percentage' => $percentage,
                'posts_processed' => $posts_processed,
                'total_posts' => $total_posts
            ],
            'has_more' => $has_more,
            'next_page' => $has_more ? ($page + 1) : null
        ];
    }

    /**
     * Action Scheduler / cron worker for a single scan batch.
     * $args may be an array with keys 'scan_id' and 'page', or a single-arg payload from as_enqueue.
     */
    public static function process_scan_batch_action($args = [])
    {
        // Normalize args
        if (!is_array($args)) {
            $args = (array) $args;
        }

        $scan_id = $args['scan_id'] ?? ($args[0]['scan_id'] ?? null);
        $page = isset($args['page']) ? intval($args['page']) : 1;

        if (!$scan_id) {
            error_log('Blogibot: process_scan_batch_action called without scan_id');
            return;
        }

        // Retrieve license data from transient
        $license_data = get_transient("blogibot_scan_license_{$scan_id}");
        if (empty($license_data)) {
            error_log('Blogibot: No license data found for scan ' . $scan_id);
            return;
        }

        $batch_size = apply_filters('blogibot_content_scan_batch_size', 10);

        // Run a single paged batch
        try {
            // Use the shared batch processing logic
            $result = self::process_single_batch($scan_id, $page, $license_data);

            // If there are more pages and this is background processing, schedule next batch
            if ($result['success'] && $result['has_more']) {
                $next_args = ['scan_id' => $scan_id, 'page' => $result['next_page']];
                if (function_exists('as_enqueue_async_action')) {
                    as_enqueue_async_action('blogibot_process_scan_batch', $next_args);
                } else {
                    wp_schedule_single_event(time() + 5, 'blogibot_process_content_scan', [$next_args]);
                }
            }

        } catch (\Exception $e) {
            error_log('Blogibot Content Scan Batch Error: ' . $e->getMessage());
            $scan_log = get_option('blogibot_scan_log', []);
            $scan_log[] = [
                'timestamp' => current_time('timestamp'),
                'level' => 'error',
                'message' => 'Batch processing failed: ' . $e->getMessage()
            ];
            update_option('blogibot_scan_log', $scan_log);
            update_option('blogibot_scan_progress', [
                'status' => 'error',
                'percentage' => 0,
                'message' => 'Scan batch failed: ' . $e->getMessage()
            ]);
        }
    }

    /**
     * Get current scan progress
     */
    private static function get_scan_progress()
    {
        // Base progress from option
        $progress = get_option('blogibot_scan_progress', [
            'status' => 'not_started',
            'percentage' => 0,
            'message' => 'No scan in progress',
            'posts_processed' => 0,
            'total_posts' => 0
        ]);

        // If a scan is active, prefer data from the scan_state for accuracy
        $scan_id = get_transient('blogibot_content_scan_in_progress');
        if ($scan_id) {
            $scan_state = get_option("blogibot_scan_state_{$scan_id}", []);
            if (!empty($scan_state)) {
                $posts_processed = isset($scan_state['posts_processed']) ? (int) $scan_state['posts_processed'] : 0;
                $total_posts = isset($scan_state['total_posts']) ? (int) $scan_state['total_posts'] : 0;
                $percentage = $total_posts > 0 ? round(($posts_processed / $total_posts) * 100, 1) : 0;

                $progress = [
                    'status' => $scan_state['status'] ?? 'in_progress',
                    'percentage' => $percentage,
                    'message' => $scan_state['message'] ?? "Processed {$posts_processed} of {$total_posts} posts",
                    'posts_processed' => $posts_processed,
                    'total_posts' => $total_posts,
                    'scan_id' => $scan_id
                ];
            }
        }

        // If no transient and previously marked in_progress, mark completed
        if (!get_transient('blogibot_content_scan_in_progress') && isset($progress['status']) && $progress['status'] === 'in_progress') {
            $progress['status'] = 'completed';
            update_option('blogibot_scan_progress', $progress);
        }

        return $progress;
    }

    /**
     * Get scan log data
     */
    private static function get_scan_log()
    {
        $scan_log = get_option('blogibot_scan_log', []);
        $last_scan_time = get_option('blogibot_last_content_scan', false);
        
        $log_html = '<div class="scan-log-container">';
        
        if ($last_scan_time) {
            $log_html .= '<div class="log-header">';
            $log_html .= '<h4>Scan completed on ' . date('F j, Y \a\t g:i A', $last_scan_time) . '</h4>';
            $log_html .= '</div>';
        }
        
        if (!empty($scan_log)) {
            $log_html .= '<div class="log-entries">';
            foreach ($scan_log as $entry) {
                $timestamp = isset($entry['timestamp']) ? date('H:i:s', $entry['timestamp']) : 'Unknown';
                $level = $entry['level'] ?? 'info';
                $message = esc_html($entry['message'] ?? '');
                
                $log_html .= '<div class="log-entry log-' . $level . '">';
                $log_html .= '<span class="log-time">' . $timestamp . '</span>';
                $log_html .= '<span class="log-message">' . $message . '</span>';
                $log_html .= '</div>';
            }
            $log_html .= '</div>';
        } else {
            $log_html .= '<p>No log entries available.</p>';
        }
        
        $log_html .= '</div>';
        
        // Add CSS for log styling
        $log_html .= '<style>
            .scan-log-container { font-family: monospace; }
            .log-header { margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #ddd; }
            .log-entry { padding: 5px 0; border-bottom: 1px solid #f0f0f0; }
            .log-time { color: #666; margin-right: 10px; }
            .log-message { color: #333; }
            .log-info .log-message { color: #0073aa; }
            .log-success .log-message { color: #00a32a; }
            .log-warning .log-message { color: #dba617; }
            .log-error .log-message { color: #d63638; }
        </style>';

        return ['log_html' => $log_html];
    }

    /**
     * Process content scan (called by WordPress cron)
     */
    public static function process_content_scan($license_data)
    {
        // Set time limit for long-running process
        if (!ini_get('safe_mode')) {
            set_time_limit(300); // 5 minutes maximum
        }
        
        $start_time = current_time('timestamp');
        $scan_log = [];
        
        // Log that we've started
        error_log('Blogibot: Content scan process started at ' . date('Y-m-d H:i:s', $start_time));
        
        try {
            // Log scan start
            $scan_log[] = [
                'timestamp' => $start_time,
                'level' => 'info',
                'message' => 'Content scan started'
            ];

            // Calculate date 14 days ago for filtering recent posts
            $date_14_days_ago = date('Y-m-d', strtotime('-14 days'));

            $scan_log[] = [
                'timestamp' => current_time('timestamp'),
                'level' => 'info',
                'message' => 'Analyzing posts from the last 14 days (since ' . $date_14_days_ago . ')'
            ];

            // Get all published posts from the last 14 days only
            $posts_query = new \WP_Query([
                'post_type' => 'post',
                'post_status' => 'publish',
                'posts_per_page' => -1,
                'fields' => 'ids',
                'date_query' => [
                    [
                        'after' => $date_14_days_ago,
                        'inclusive' => true,
                    ],
                ],
            ]);

            $post_ids = $posts_query->posts;
            $total_posts = count($post_ids);

            if ($total_posts === 0) {
                throw new \Exception('No published posts found to scan');
            }

            $scan_log[] = [
                'timestamp' => current_time('timestamp'),
                'level' => 'info',
                'message' => "Found {$total_posts} posts to analyze"
            ];

            // Update progress
            update_option('blogibot_scan_progress', [
                'status' => 'in_progress',
                'percentage' => 0,
                'message' => "Processing {$total_posts} posts...",
                'posts_processed' => 0,
                'total_posts' => $total_posts,
                'start_time' => $start_time
            ]);

            // Check if Yoast SEO is active
            $yoast_active = is_plugin_active('wordpress-seo/wp-seo.php');
            
            $scan_log[] = [
                'timestamp' => current_time('timestamp'),
                'level' => 'info',
                'message' => 'Yoast SEO is ' . ($yoast_active ? 'active' : 'not active')
            ];

            // Process posts in batches
            $batch_size = 10; // Process 10 posts at a time
            $batches = array_chunk($post_ids, $batch_size);
            $posts_processed = 0;
            $yoast_fields_count = 0;

            foreach ($batches as $batch_index => $batch_post_ids) {
                $batch_data = [];
                
                foreach ($batch_post_ids as $post_id) {
                    $post_data = self::extract_post_data($post_id, $yoast_active);
                    if ($post_data) {
                        $batch_data[] = $post_data;
                        $posts_processed++;
                        
                        if ($yoast_active && !empty($post_data['yoast_data'])) {
                            $yoast_fields_count += count(array_filter($post_data['yoast_data']));
                        }
                    }
                }

                // Send batch to API
                if (!empty($batch_data)) {
                    $api_result = self::send_content_to_api($batch_data, $license_data);
                    
                    if ($api_result['success']) {
                        $scan_log[] = [
                            'timestamp' => current_time('timestamp'),
                            'level' => 'success',
                            'message' => "Batch " . ($batch_index + 1) . " sent successfully (" . count($batch_data) . " posts)"
                        ];

                        // Store fingerprint data if returned by API
                        if (isset($api_result['data']['results']['fingerprints'])) {
                            $fingerprints = $api_result['data']['results']['fingerprints'];
                            $existing_fingerprints = get_option('blogibot_content_fingerprints', []);
                            
                            foreach ($fingerprints as $fingerprint) {
                                $existing_fingerprints[$fingerprint['post_id']] = [
                                    'hash' => $fingerprint['hash'],
                                    'fingerprint_id' => $fingerprint['fingerprint_id'],
                                    'action' => $fingerprint['action'],
                                    'synced_at' => current_time('timestamp')
                                ];
                            }
                            
                            update_option('blogibot_content_fingerprints', $existing_fingerprints);
                            
                            $scan_log[] = [
                                'timestamp' => current_time('timestamp'),
                                'level' => 'info',
                                'message' => "Stored " . count($fingerprints) . " content fingerprints"
                            ];
                        }
                    } else {
                        $scan_log[] = [
                            'timestamp' => current_time('timestamp'),
                            'level' => 'warning',
                            'message' => "Batch " . ($batch_index + 1) . " failed: " . $api_result['error']
                        ];
                    }
                }

                // Update progress
                $percentage = round(($posts_processed / $total_posts) * 100, 1);
                update_option('blogibot_scan_progress', [
                    'status' => 'in_progress',
                    'percentage' => $percentage,
                    'message' => "Processed {$posts_processed} of {$total_posts} posts ({$percentage}%)",
                    'posts_processed' => $posts_processed,
                    'total_posts' => $total_posts,
                    'start_time' => $start_time
                ]);

                // Small delay to prevent overwhelming the server
                usleep(500000); // 0.5 seconds
            }

            // Scan completed successfully
            $end_time = current_time('timestamp');
            $duration = $end_time - $start_time;
            $duration_formatted = gmdate('H:i:s', $duration);

            $scan_log[] = [
                'timestamp' => $end_time,
                'level' => 'success',
                'message' => "Content scan completed successfully in {$duration_formatted}"
            ];

            // Update final status
            update_option('blogibot_scan_progress', [
                'status' => 'completed',
                'percentage' => 100,
                'message' => "Scan completed successfully",
                'posts_processed' => $posts_processed,
                'total_posts' => $total_posts,
                'start_time' => $start_time,
                'end_time' => $end_time
            ]);

            // Save scan completion data
            update_option('blogibot_last_content_scan', $end_time);
            update_option('blogibot_total_posts_scanned', $posts_processed);
            update_option('blogibot_last_scan_duration', $duration_formatted);
            
            if ($yoast_active) {
                update_option('blogibot_yoast_fields_scanned', $yoast_fields_count);
            }

        } catch (\Exception $e) {
            // Log error
            $scan_log[] = [
                'timestamp' => current_time('timestamp'),
                'level' => 'error',
                'message' => 'Scan failed: ' . $e->getMessage()
            ];

            // Update error status
            update_option('blogibot_scan_progress', [
                'status' => 'error',
                'percentage' => 0,
                'message' => 'Scan failed: ' . $e->getMessage(),
                'posts_processed' => $posts_processed ?? 0,
                'total_posts' => $total_posts ?? 0,
                'error' => $e->getMessage()
            ]);

            error_log('Blogibot Content Scan Error: ' . $e->getMessage());
        }

        // Save scan log
        update_option('blogibot_scan_log', $scan_log);

        // Clear scan in progress flag
        delete_transient('blogibot_content_scan_in_progress');
    }

    /**
     * Extract post data including Yoast SEO fields
     */
    private static function extract_post_data($post_id, $yoast_active = false)
    {
        $post = get_post($post_id);
        if (!$post) {
            return null;
        }

        $post_data = [
            'id' => $post_id,
            'title' => $post->post_title,
            'content' => wp_strip_all_tags($post->post_content),
            'excerpt' => $post->post_excerpt,
            'date' => $post->post_date,
            'author' => get_the_author_meta('display_name', $post->post_author),
            'categories' => wp_get_post_categories($post_id, ['fields' => 'names']),
            'tags' => wp_get_post_tags($post_id, ['fields' => 'names']),
            'permalink' => get_permalink($post_id)
        ];

        // Extract Yoast SEO data if available
        if ($yoast_active) {
            $yoast_data = [
                'meta_title' => get_post_meta($post_id, '_yoast_wpseo_title', true),
                'meta_description' => get_post_meta($post_id, '_yoast_wpseo_metadesc', true),
                'focus_keyphrase' => get_post_meta($post_id, '_yoast_wpseo_focuskw', true),
                'seo_score' => get_post_meta($post_id, '_yoast_wpseo_linkdex', true),
                'readability_score' => get_post_meta($post_id, '_yoast_wpseo_content_score', true)
            ];

            // Only include non-empty Yoast fields
            $post_data['yoast_data'] = array_filter($yoast_data);
        }

        return $post_data;
    }

    /**
     * Send content data to API
     */
    /**
     * Test API connectivity for content sync
     */
    public static function test_api_connectivity()
    {
        try {
            require_once WP_PLUGIN_DIR . '/blogibot/src/API/Client.php';
            
            // Get license data from options
            $license_data = get_option('blog82ai_license', []);
            if (empty($license_data['license_key'])) {
                return ['success' => false, 'error' => 'No license key found'];
            }
            
            // Test basic connectivity
            $connection_test = \Blog82AI_API_Client::test_connection();
            error_log("ContentAnalyzer: Connection test result: " . json_encode($connection_test));
            
            if (!$connection_test['success']) {
                return [
                    'success' => false, 
                    'error' => 'API connection failed: ' . $connection_test['error'],
                    'debug' => $connection_test
                ];
            }
            
            // Test with a minimal payload to content_sync endpoint
            $test_payload = [
                'license_key' => $license_data['license_key'],
                'domain' => home_url(),
                'posts' => [
                    [
                        'post_id' => 'test',
                        'title' => 'Test Post',
                        'content' => 'Test content for API connectivity'
                    ]
                ]
            ];
            
            error_log("ContentAnalyzer: Testing content_sync endpoint with test payload");
            $response = \Blog82AI_API_Client::request('content_sync', $test_payload);
            
            error_log("ContentAnalyzer: Test response: " . json_encode($response));
            
            return [
                'success' => true,
                'connection_test' => $connection_test,
                'endpoint_test' => $response,
                'message' => 'API connectivity test completed'
            ];
            
        } catch (\Exception $e) {
            error_log("ContentAnalyzer: Exception in test_api_connectivity: " . $e->getMessage());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }

    private static function send_content_to_api($content_data, $license_data)
    {
        try {
            require_once WP_PLUGIN_DIR . '/blogibot/src/API/Client.php';

            // Format posts data for the API
            $posts = [];
            foreach ($content_data as $post_data) {
                $post_item = [
                    'post_id' => $post_data['id'],
                    'title' => $post_data['title'],
                    'content' => $post_data['content']
                ];

                // Add Yoast SEO data if available
                if (!empty($post_data['yoast_data'])) {
                    if (!empty($post_data['yoast_data']['meta_title'])) {
                        $post_item['seo_title'] = $post_data['yoast_data']['meta_title'];
                    }
                    if (!empty($post_data['yoast_data']['meta_description'])) {
                        $post_item['seo_description'] = $post_data['yoast_data']['meta_description'];
                    }
                    if (!empty($post_data['yoast_data']['focus_keyphrase'])) {
                        $post_item['focus_keyword'] = $post_data['yoast_data']['focus_keyphrase'];
                    }
                }

                $posts[] = $post_item;
            }

            $payload = [
                'license_key' => $license_data['license_key'],
                'domain' => $license_data['domain'] ?? home_url(),
                'posts' => $posts
            ];

            // Debug logging before API call
            error_log("ContentAnalyzer: Attempting to send content to API");
            error_log("ContentAnalyzer: License Key: " . substr($license_data['license_key'], 0, 8) . "...");
            error_log("ContentAnalyzer: Domain: " . ($license_data['domain'] ?? home_url()));
            error_log("ContentAnalyzer: Posts count: " . count($posts));
            
            // Log first post for debugging (truncated content)
            if (!empty($posts)) {
                $debug_post = $posts[0];
                $debug_post['content'] = substr($debug_post['content'], 0, 100) . '...';
                error_log("ContentAnalyzer: Sample post data: " . json_encode($debug_post));
            }

            // Use the API client to send data
            $response = \Blog82AI_API_Client::request('content_sync', $payload);

            // Debug logging after API call
            error_log("ContentAnalyzer: API response received");
            error_log("ContentAnalyzer: Response success: " . ($response['success'] ? 'true' : 'false'));
            
            if (!$response['success']) {
                error_log("ContentAnalyzer: API Error: " . ($response['error'] ?? 'Unknown error'));
                if (isset($response['status_code'])) {
                    error_log("ContentAnalyzer: Status Code: " . $response['status_code']);
                }
            } else {
                error_log("ContentAnalyzer: API Success - data received");
            }

            if ($response && $response['success']) {
                return ['success' => true, 'data' => $response['data']];
            } else {
                $error = $response['error'] ?? $response['message'] ?? 'Unknown API error';
                return ['success' => false, 'error' => $error];
            }

        } catch (\Exception $e) {
            error_log("ContentAnalyzer: Exception in send_content_to_api: " . $e->getMessage());
            error_log("ContentAnalyzer: Exception trace: " . $e->getTraceAsString());
            return ['success' => false, 'error' => $e->getMessage()];
        }
    }
}

// Register hooks for Action Scheduler and WP cron fallback
add_action('blogibot_process_scan_batch', ['\\Blogibot\\Handlers\\ContentAnalyzerHandler', 'process_scan_batch_action']);
add_action('blogibot_process_content_scan', ['\\Blogibot\\Handlers\\ContentAnalyzerHandler', 'process_scan_batch_action']);
add_action('blogibot_process_content_scan_fallback', ['\\Blogibot\\Handlers\\ContentAnalyzerHandler', 'process_scan_batch_action']);
