<?php
/**
 * Background Processor Class
 *
 * Handles background processing for bulk operations
 *
 * @package AIProductContentImageGenerator\Core
 * @since 1.0.0
 */

namespace AIProductContentImageGenerator\Core;

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

use AIProductContentImageGenerator\Core\Container;

/**
 * BackgroundProcessor class for handling bulk operations
 */
class BackgroundProcessor {
    /**
     * Container instance
     *
     * @var Container
     */
    private $container;

    /**
     * Current batch ID
     *
     * @var string
     */
    private $current_batch_id;

    /**
     * Constructor
     *
     * @param Container $container
     */
    public function __construct(Container $container) {
        $this->container = $container;
    }

    /**
     * Initialize background processor
     */
    public function init() {
        add_action('apcig_process_batch', [$this, 'process_batch']);
        add_action('apcig_cleanup_old_records', [$this, 'cleanup_old_records']);
        
        // Schedule cleanup if not already scheduled
        if (!wp_next_scheduled('apcig_cleanup_old_records')) {
            wp_schedule_event(time(), 'daily', 'apcig_cleanup_old_records');
        }
    }

    /**
     * Start batch processing
     *
     * @param string $batch_id Batch ID
     * @param string $action Action type
     * @param array $product_ids Product IDs to process
     * @param array $settings Processing settings
     * @return bool
     */
    public function start_batch($batch_id, $action, $product_ids, $settings = []) {
        $database = $this->container->get('database');
        
        $batch_data = [
            'id' => $batch_id,
            'action_type' => $action,
            'status' => 'pending',
            'total_items' => count($product_ids),
            'processed_items' => 0,
            'failed_items' => 0,
            'settings' => $settings,
            'product_ids' => $product_ids,
            'results' => [],
            'error_log' => '',
            'user_id' => get_current_user_id()
        ];

        $result = $database->save_batch_job($batch_data);
        
        if ($result) {
            // Schedule immediate processing
            wp_schedule_single_event(time(), 'apcig_process_batch', [$batch_id]);
            return true;
        }
        
        return false;
    }

    /**
     * Process batch
     *
     * @param string $batch_id Batch ID
     */
    public function process_batch($batch_id) {
        $database = $this->container->get('database');
        $batch = $database->get_batch_job($batch_id);
        
        if (!$batch || $batch->status !== 'pending') {
            return;
        }

        // Update status to processing
        $database->update_batch_job($batch_id, [
            'status' => 'processing',
            'started_at' => current_time('mysql')
        ]);

        $this->current_batch_id = $batch_id;
        
        try {
            switch ($batch->action_type) {
                case 'generate_content':
                    $this->process_content_generation($batch);
                    break;
                case 'generate_images':
                    $this->process_image_generation($batch);
                    break;
                case 'enhance_images':
                    $this->process_image_enhancement($batch);
                    break;
                default:
                    throw new \Exception('Unknown batch action: ' . $batch->action_type);
            }
            
            // Mark as completed
            $database->update_batch_job($batch_id, [
                'status' => 'completed',
                'completed_at' => current_time('mysql')
            ]);
            
        } catch (\Exception $e) {
            // Mark as failed
            $database->update_batch_job($batch_id, [
                'status' => 'failed',
                'error_log' => $e->getMessage(),
                'completed_at' => current_time('mysql')
            ]);
        }
    }

    /**
     * Process content generation batch
     *
     * @param object $batch Batch data
     */
    private function process_content_generation($batch) {
        $content_generator = $this->container->get('content_generator');
        $database = $this->container->get('database');
        
        $product_ids = $batch->product_ids;
        $settings = $batch->settings;
        $processed = 0;
        $failed = 0;
        $results = [];

        foreach ($product_ids as $product_id) {
            // Check if batch was paused or stopped
            $current_batch = $database->get_batch_job($batch->id);
            if ($current_batch->status !== 'processing') {
                break;
            }

            try {
                $result = $content_generator->generate_content($product_id, $settings);
                
                if ($result['success']) {
                    // Apply content if auto-apply is enabled
                    if (!empty($settings['auto_apply'])) {
                        $content_generator->apply_content($product_id, $result['results']);
                    }
                    
                    $results[$product_id] = $result;
                    $processed++;
                } else {
                    $failed++;
                    $results[$product_id] = ['error' => $result['error'] ?? 'Unknown error'];
                }
                
            } catch (\Exception $e) {
                $failed++;
                $results[$product_id] = ['error' => $e->getMessage()];
            }

            // Update progress
            $database->update_batch_job($batch->id, [
                'processed_items' => $processed,
                'failed_items' => $failed,
                'results' => $results
            ]);

            // Add delay between requests to avoid rate limiting
            if (!empty($settings['delay_between_requests'])) {
                sleep((int) $settings['delay_between_requests']);
            }
        }
    }

    /**
     * Process image generation batch
     *
     * @param object $batch Batch data
     */
    private function process_image_generation($batch) {
        $image_generator = $this->container->get('image_generator');
        $database = $this->container->get('database');
        
        $product_ids = $batch->product_ids;
        $settings = $batch->settings;
        $processed = 0;
        $failed = 0;
        $results = [];

        foreach ($product_ids as $product_id) {
            // Check if batch was paused or stopped
            $current_batch = $database->get_batch_job($batch->id);
            if ($current_batch->status !== 'processing') {
                break;
            }

            try {
                $product = wc_get_product($product_id);
                if (!$product) {
                    throw new \Exception('Product not found');
                }

                $description = $settings['description'] ?? $product->get_name();
                $style = $settings['style'] ?? 'clean-white';
                $size = $settings['size'] ?? '1024x1024';
                $count = $settings['count'] ?? 1;
                $provider = $settings['provider'] ?? 'openai';

                $result = $image_generator->generate_images(
                    $product,
                    $description,
                    $style,
                    $size,
                    $count,
                    $provider
                );
                
                if (!is_wp_error($result)) {
                    $results[$product_id] = $result;
                    $processed++;
                } else {
                    $failed++;
                    $results[$product_id] = ['error' => $result->get_error_message()];
                }
                
            } catch (\Exception $e) {
                $failed++;
                $results[$product_id] = ['error' => $e->getMessage()];
            }

            // Update progress
            $database->update_batch_job($batch->id, [
                'processed_items' => $processed,
                'failed_items' => $failed,
                'results' => $results
            ]);

            // Add delay between requests
            if (!empty($settings['delay_between_requests'])) {
                \sleep((int) $settings['delay_between_requests']);
            }
        }
    }

    /**
     * Process image enhancement batch
     *
     * @param object $batch Batch data
     */
    private function process_image_enhancement($batch) {
        $image_generator = $this->container->get('image_generator');
        $database = $this->container->get('database');
        
        $product_ids = $batch->product_ids;
        $settings = $batch->settings;
        $processed = 0;
        $failed = 0;
        $results = [];

        foreach ($product_ids as $product_id) {
            // Check if batch was paused or stopped
            $current_batch = $database->get_batch_job($batch->id);
            if ($current_batch->status !== 'processing') {
                break;
            }

            try {
                $product = wc_get_product($product_id);
                if (!$product) {
                    throw new \Exception('Product not found');
                }

                // Get product images
                $image_urls = [];
                $image_id = $product->get_image_id();
                if ($image_id) {
                    $image_urls[] = wp_get_attachment_url($image_id);
                }

                if (empty($image_urls)) {
                    throw new \Exception('No images found for product');
                }

                $enhancements = $settings['enhancements'] ?? ['upscale'];
                $strength = $settings['strength'] ?? 0.7;
                $provider = $settings['provider'] ?? 'openai';

                $result = $image_generator->enhance_images(
                    $image_urls,
                    $enhancements,
                    $strength,
                    $provider
                );
                
                if (!is_wp_error($result)) {
                    $results[$product_id] = $result;
                    $processed++;
                } else {
                    $failed++;
                    $results[$product_id] = ['error' => $result->get_error_message()];
                }
                
            } catch (\Exception $e) {
                $failed++;
                $results[$product_id] = ['error' => $e->getMessage()];
            }

            // Update progress
            $database->update_batch_job($batch->id, [
                'processed_items' => $processed,
                'failed_items' => $failed,
                'results' => $results
            ]);

            // Add delay between requests
            if (!empty($settings['delay_between_requests'])) {
                \sleep((int) $settings['delay_between_requests']);
            }
        }
    }

    /**
     * Pause batch processing
     *
     * @param string $batch_id Batch ID
     * @return bool
     */
    public function pause_batch($batch_id) {
        $database = $this->container->get('database');
        
        return $database->update_batch_job($batch_id, [
            'status' => 'paused',
            'paused_at' => current_time('mysql')
        ]);
    }

    /**
     * Resume batch processing
     *
     * @param string $batch_id Batch ID
     * @return bool
     */
    public function resume_batch($batch_id) {
        $database = $this->container->get('database');
        
        $result = $database->update_batch_job($batch_id, [
            'status' => 'processing'
        ]);
        
        if ($result) {
            // Schedule processing
            wp_schedule_single_event(time(), 'apcig_process_batch', [$batch_id]);
        }
        
        return $result;
    }

    /**
     * Stop batch processing
     *
     * @param string $batch_id Batch ID
     * @return bool
     */
    public function stop_batch($batch_id) {
        $database = $this->container->get('database');
        
        // Clear any scheduled events
        wp_clear_scheduled_hook('apcig_process_batch', [$batch_id]);
        
        return $database->update_batch_job($batch_id, [
            'status' => 'stopped',
            'stopped_at' => current_time('mysql')
        ]);
    }

    /**
     * Get batch status
     *
     * @param string $batch_id Batch ID
     * @return object|null
     */
    public function get_batch_status($batch_id) {
        $database = $this->container->get('database');
        return $database->get_batch_job($batch_id);
    }

    /**
     * Cleanup old records
     */
    public function cleanup_old_records() {
        $database = $this->container->get('database');
        $retention_days = get_option('apcig_data_retention_days', 90);
        
        $database->cleanup_old_records($retention_days);
    }

    /**
     * Get processing queue
     *
     * @return array
     */
    public function get_processing_queue() {
        global $wpdb;
        $database = $this->container->get('database');
        $table = $database->get_table_name('batch_jobs');
        
        return $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            "SELECT * FROM {$wpdb->prefix}apcig_batch_jobs 
             WHERE status IN ('pending', 'processing', 'paused') 
             ORDER BY created_at ASC"
        );
    }

    /**
     * Process queue
     */
    public function process_queue() {
        $queue = $this->get_processing_queue();
        
        foreach ($queue as $batch) {
            if ($batch->status === 'pending') {
                $this->process_batch($batch->id);
                break; // Process one at a time
            }
        }
    }
}