<?php

/**
 * Schema Batch Processor
 *
 * Processes products in batches to apply AI schema enhancements
 *
 * @package ProRank\SEO\Core\Schema
 * @since   2.0.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Core\Schema;

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


/**
 * SchemaBatchProcessor class
 */


class SchemaBatchProcessor {
    
    /**
     * Batch size for processing
     */
    private const BATCH_SIZE = 10;
    
    /**
     * Option key for tracking batch progress
     */
    private const PROGRESS_OPTION = 'prorank_schema_batch_progress';
    
    /**
     * AI Enhancer instance
     *
     * @var SchemaAIEnhancer
     */
    private SchemaAIEnhancer $enhancer;
    
    /**
     * Constructor
     */
    public function __construct() {
        $this->enhancer = new SchemaAIEnhancer();
    }
    
    /**
     * Initialize batch processing hooks
     *
     * @return void
     */
    public static function init_hooks(): void {
        $instance = new self();
        
        // Register AJAX handlers
        add_action('wp_ajax_prorank_batch_enhance_schemas', [$instance, 'ajax_process_batch']);
        
        // Register WP-CLI command if available
        if (defined('WP_CLI') && WP_CLI) {
            \WP_CLI::add_command('prorank enhance-schemas', [$instance, 'cli_process_all']);
        }
        
        // Schedule cron job for background processing
        add_action('prorank_schema_batch_cron', [$instance, 'process_batch']);
    }
    
    /**
     * Start batch processing
     *
     * @return array Status information.
     */
    public function start_batch_processing(): array {
        // Get total products count
        $total = $this->get_total_products();
        
        if ($total === 0) {
            return [
                'status' => 'error',
                'message' => 'No products found to process'
            ];
        }
        
        // Initialize progress
        $progress = [
            'total' => $total,
            'processed' => 0,
            'enhanced' => 0,
            'errors' => 0,
            'current_offset' => 0,
            'started_at' => time(),
            'status' => 'processing'
        ];
        
        update_option(self::PROGRESS_OPTION, $progress);
        
        // Schedule first batch
        if (!wp_next_scheduled('prorank_schema_batch_cron')) {
            wp_schedule_single_event(time() + 5, 'prorank_schema_batch_cron');
        }
        
        return [
            'status' => 'started',
            'total' => $total,
            'message' => sprintf('Started processing %d products', $total)
        ];
    }
    
    /**
     * Process a batch of products
     *
     * @return array Batch results.
     */
    public function process_batch(): array {
        $progress = get_option(self::PROGRESS_OPTION, []);
        
        if (empty($progress) || $progress['status'] !== 'processing') {
            return [
                'status' => 'idle',
                'message' => 'No batch processing in progress'
            ];
        }
        
        // Get batch of products
        $products = $this->get_product_batch($progress['current_offset'], self::BATCH_SIZE);
        
        if (empty($products)) {
            // Processing complete
            $progress['status'] = 'completed';
            $progress['completed_at'] = time();
            update_option(self::PROGRESS_OPTION, $progress);
            
            return [
                'status' => 'completed',
                'processed' => $progress['processed'],
                'enhanced' => $progress['enhanced'],
                'errors' => $progress['errors']
            ];
        }
        
        $batch_results = [
            'processed' => 0,
            'enhanced' => 0,
            'errors' => 0
        ];
        
        foreach ($products as $product_id) {
            try {
                $product = wc_get_product($product_id);
                if (!$product) {
                    $batch_results['errors']++;
                    continue;
                }
                
                // Build basic schema
                $schema = [
                    '@type' => 'Product',
                    'name' => $product->get_name()
                ];
                
                // Enhance with AI
                $enhanced = $this->enhancer->enhance_product_schema($schema, $product);
                
                // Check if enhancements were made
                if (count($enhanced) > count($schema)) {
                    $batch_results['enhanced']++;
                }
                
                $batch_results['processed']++;
                
            } catch (\Exception $e) {
                $batch_results['errors']++;
                prorank_log('ProRank SEO: Batch enhancement error for product ' . $product_id . ': ' . $e->getMessage());
            }
        }
        
        // Update progress
        $progress['processed'] += $batch_results['processed'];
        $progress['enhanced'] += $batch_results['enhanced'];
        $progress['errors'] += $batch_results['errors'];
        $progress['current_offset'] += self::BATCH_SIZE;
        update_option(self::PROGRESS_OPTION, $progress);
        
        // Schedule next batch if not complete
        if ($progress['processed'] < $progress['total']) {
            wp_schedule_single_event(time() + 5, 'prorank_schema_batch_cron');
        }
        
        return $batch_results;
    }
    
    /**
     * AJAX handler for batch processing
     *
     * @return void
     */
    public function ajax_process_batch(): void {
        // Check nonce
        if (!check_ajax_referer('prorank_admin_nonce', 'nonce', false)) {
            wp_send_json_error('Invalid nonce');
        }
        
        // Check permissions
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Insufficient permissions');
        }
        
        $action = $_POST['batch_action'] ?? 'process';
        
        switch ($action) {
            case 'start':
                $result = $this->start_batch_processing();
                break;
            case 'process':
                $result = $this->process_batch();
                break;
            case 'status':
                $result = $this->get_batch_status();
                break;
            case 'cancel':
                $result = $this->cancel_batch_processing();
                break;
            default:
                wp_send_json_error('Invalid action');
        }
        
        wp_send_json_success($result);
    }
    
    /**
     * Get batch processing status
     *
     * @return array Status information.
     */
    public function get_batch_status(): array {
        $progress = get_option(self::PROGRESS_OPTION, []);
        
        if (empty($progress)) {
            return [
                'status' => 'idle',
                'message' => 'No batch processing in progress'
            ];
        }
        
        $percentage = $progress['total'] > 0 
            ? round(($progress['processed'] / $progress['total']) * 100) 
            : 0;
        
        return [
            'status' => $progress['status'],
            'total' => $progress['total'],
            'processed' => $progress['processed'],
            'enhanced' => $progress['enhanced'],
            'errors' => $progress['errors'],
            'percentage' => $percentage,
            'started_at' => $progress['started_at'],
            'completed_at' => $progress['completed_at'] ?? null
        ];
    }
    
    /**
     * Cancel batch processing
     *
     * @return array Status information.
     */
    public function cancel_batch_processing(): array {
        // Clear scheduled cron
        wp_clear_scheduled_hook('prorank_schema_batch_cron');
        
        // Update progress status
        $progress = get_option(self::PROGRESS_OPTION, []);
        if (!empty($progress)) {
            $progress['status'] = 'cancelled';
            $progress['cancelled_at'] = time();
            update_option(self::PROGRESS_OPTION, $progress);
        }
        
        return [
            'status' => 'cancelled',
            'message' => 'Batch processing cancelled'
        ];
    }
    
    /**
     * Get total products count
     *
     * @return int Total products.
     */
    private function get_total_products(): int {
        $args = [
            'post_type' => 'product',
            'post_status' => 'publish',
            'posts_per_page' => -1,
            'fields' => 'ids'
        ];
        
        $query = new \WP_Query($args);
        return $query->found_posts;
    }
    
    /**
     * Get batch of product IDs
     *
     * @param int $offset Offset for query.
     * @param int $limit  Limit for query.
     * @return array Product IDs.
     */
    private function get_product_batch(int $offset, int $limit): array {
        $args = [
            'post_type' => 'product',
            'post_status' => 'publish',
            'posts_per_page' => $limit,
            'offset' => $offset,
            'fields' => 'ids',
            'orderby' => 'ID',
            'order' => 'ASC'
        ];
        
        $query = new \WP_Query($args);
        return $query->posts;
    }
    
    /**
     * WP-CLI command to process all products
     *
     * @param array $args       Command arguments.
     * @param array $assoc_args Command options.
     * @return void
     */
    public function cli_process_all($args, $assoc_args): void {
        $batch_size = isset($assoc_args['batch-size']) ? (int) $assoc_args['batch-size'] : self::BATCH_SIZE;
        $total = $this->get_total_products();
        
        if ($total === 0) {
            \WP_CLI::error('No products found to process');
        }
        
        \WP_CLI::log(sprintf('Processing %d products in batches of %d...', $total, $batch_size));
        
        $progress = \WP_CLI\Utils\make_progress_bar('Enhancing schemas', $total);
        $offset = 0;
        $total_enhanced = 0;
        $total_errors = 0;
        
        while ($offset < $total) {
            $products = $this->get_product_batch($offset, $batch_size);
            
            foreach ($products as $product_id) {
                try {
                    $product = wc_get_product($product_id);
                    if (!$product) {
                        $total_errors++;
                        continue;
                    }
                    
                    $schema = [
                        '@type' => 'Product',
                        'name' => $product->get_name()
                    ];
                    
                    $enhanced = $this->enhancer->enhance_product_schema($schema, $product);
                    
                    if (count($enhanced) > count($schema)) {
                        $total_enhanced++;
                    }
                    
                } catch (\Exception $e) {
                    $total_errors++;
                    \WP_CLI::warning('Error processing product ' . $product_id . ': ' . $e->getMessage());
                }
                
                $progress->tick();
            }
            
            $offset += $batch_size;
        }
        
        $progress->finish();
        
        \WP_CLI::success(sprintf(
            'Processing complete! Enhanced: %d, Errors: %d',
            $total_enhanced,
            $total_errors
        ));
    }
}