<?php
/**
 * AI Post 插件异步任务队列系统
 * 
 * 提供后台任务处理功能，提升插件性能和用户体验
 * 
 * @package AI-Post
 * @since 2.8.9
 */

namespace HaoZiTeam\AIPost\Service\Features;

defined('ABSPATH') || exit;

/**
 * 异步任务队列类
 */
class AsyncQueue {
    
    /**
     * 任务状态常量
     */
    const STATUS_PENDING = 'pending';
    const STATUS_PROCESSING = 'processing';
    const STATUS_COMPLETED = 'completed';
    const STATUS_FAILED = 'failed';
    const STATUS_RETRY = 'retry';
    
    /**
     * 任务优先级常量
     */
    const PRIORITY_HIGH = 1;
    const PRIORITY_NORMAL = 5;
    const PRIORITY_LOW = 10;
    
    /**
     * 任务类型常量
     */
    const TYPE_CONTENT_GENERATE = 'content_generate';
    const TYPE_IMAGE_PROCESS = 'image_process';
    const TYPE_POST_PUBLISH = 'post_publish';
    const TYPE_API_CALL = 'api_call';
    const TYPE_DATA_SYNC = 'data_sync';
    
    /**
     * 单例实例
     */
    private static $instance = null;
    
    /**
     * 数据库表名
     */
    private $table_name;
    
    /**
     * 最大重试次数
     */
    private $max_retries = 3;
    
    /**
     * 重试延迟（秒）
     */
    private $retry_delays = [60, 300, 1800]; // 1分钟, 5分钟, 30分钟
    
    /**
     * 获取单例实例
     * 
     * @return AsyncQueue
     */
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * 构造函数
     */
    private function __construct() {
        global $wpdb;
        $this->table_name = $wpdb->prefix . 'ai_post_async_queue';
        
        // 初始化队列
        $this->init();
    }
    
    /**
     * 初始化队列
     */
    private function init() {
        // 注册队列处理定时任务
        if (!wp_next_scheduled('ai_post_process_queue')) {
            wp_schedule_event(time(), 'every_5_minutes', 'ai_post_process_queue');
        }
        
        // 添加队列处理回调
        add_action('ai_post_process_queue', [$this, 'process_queue']);
        
        // 添加队列监控
        add_action('admin_init', [$this, 'monitor_queue_health']);
    }
    
    /**
     * 创建数据库表
     */
    public static function create_table() {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'ai_post_async_queue';
        $charset_collate = $wpdb->get_charset_collate();
        
        $sql = "CREATE TABLE IF NOT EXISTS {$table_name} (
            id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
            task_type VARCHAR(50) NOT NULL,
            task_data LONGTEXT NOT NULL,
            priority TINYINT(1) DEFAULT 5,
            status VARCHAR(20) DEFAULT 'pending',
            retry_count TINYINT(2) DEFAULT 0,
            max_retries TINYINT(2) DEFAULT 3,
            scheduled_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            started_at DATETIME NULL,
            completed_at DATETIME NULL,
            result_data LONGTEXT NULL,
            error_message TEXT NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            PRIMARY KEY (id),
            KEY idx_status (status),
            KEY idx_priority (priority),
            KEY idx_scheduled_at (scheduled_at),
            KEY idx_task_type (task_type)
        ) {$charset_collate};";
        
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
        dbDelta($sql);
        
        // 添加队列清理定时任务
        if (!wp_next_scheduled('ai_post_cleanup_queue')) {
            wp_schedule_event(time(), 'daily', 'ai_post_cleanup_queue');
        }
        
        add_action('ai_post_cleanup_queue', [__CLASS__, 'cleanup_old_tasks']);
    }
    
    /**
     * 添加任务到队列
     * 
     * @param string $task_type 任务类型
     * @param array $task_data 任务数据
     * @param int $priority 任务优先级
     * @param string $scheduled_at 计划执行时间
     * @return int|false 任务ID或false
     */
    public function add_task($task_type, $task_data, $priority = self::PRIORITY_NORMAL, $scheduled_at = null) {
        global $wpdb;
        
        // 验证任务类型
        if (!in_array($task_type, [
            self::TYPE_CONTENT_GENERATE,
            self::TYPE_IMAGE_PROCESS,
            self::TYPE_POST_PUBLISH,
            self::TYPE_API_CALL,
            self::TYPE_DATA_SYNC
        ])) {
            error_log("AI Post AsyncQueue: Invalid task type: {$task_type}");
            return false;
        }
        
        // 序列化任务数据
        $serialized_data = wp_json_encode($task_data);
        if ($serialized_data === false) {
            error_log('AI Post AsyncQueue: Failed to serialize task data');
            return false;
        }
        
        // 设置计划时间
        if ($scheduled_at === null) {
            $scheduled_at = current_time('mysql');
        }
        
        // 插入任务
        $result = $wpdb->insert(
            $this->table_name,
            [
                'task_type' => $task_type,
                'task_data' => $serialized_data,
                'priority' => $priority,
                'status' => self::STATUS_PENDING,
                'scheduled_at' => $scheduled_at,
                'max_retries' => $this->max_retries
            ],
            ['%s', '%s', '%d', '%s', '%s', '%d']
        );
        
        if ($result === false) {
            error_log('AI Post AsyncQueue: Failed to insert task: ' . $wpdb->last_error);
            return false;
        }
        
        $task_id = $wpdb->insert_id;
        
        // 记录日志
        error_log("AI Post AsyncQueue: Task added - ID: {$task_id}, Type: {$task_type}, Priority: {$priority}");
        
        // 触发队列处理（如果任务需要立即执行）
        if ($scheduled_at === current_time('mysql')) {
            $this->trigger_processing();
        }
        
        return $task_id;
    }
    
    /**
     * 处理队列
     */
    public function process_queue() {
        global $wpdb;
        
        // 获取待处理任务（按优先级排序）
        $tasks = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM {$this->table_name} 
                 WHERE status IN (%s, %s) 
                 AND scheduled_at <= %s 
                 ORDER BY priority ASC, created_at ASC 
                 LIMIT 10",
                self::STATUS_PENDING,
                self::STATUS_RETRY,
                current_time('mysql')
            )
        );
        
        if (empty($tasks)) {
            error_log('AI Post AsyncQueue: No tasks to process');
            return;
        }
        
        error_log("AI Post AsyncQueue: Processing " . count($tasks) . " tasks");
        
        foreach ($tasks as $task) {
            $this->process_task($task);
        }
        
        // 更新队列统计
        $this->update_queue_stats();
    }
    
    /**
     * 处理单个任务
     * 
     * @param object $task 任务对象
     */
    private function process_task($task) {
        global $wpdb;
        
        // 更新任务状态为处理中
        $wpdb->update(
            $this->table_name,
            [
                'status' => self::STATUS_PROCESSING,
                'started_at' => current_time('mysql')
            ],
            ['id' => $task->id],
            ['%s', '%s'],
            ['%d']
        );
        
        try {
            // 解析任务数据
            $task_data = json_decode($task->task_data, true);
            if ($task_data === null) {
                throw new \Exception('Failed to parse task data');
            }
            
            // 根据任务类型执行相应处理
            $result = $this->execute_task($task->task_type, $task_data);
            
            // 更新任务为完成状态
            $wpdb->update(
                $this->table_name,
                [
                    'status' => self::STATUS_COMPLETED,
                    'completed_at' => current_time('mysql'),
                    'result_data' => wp_json_encode($result)
                ],
                ['id' => $task->id],
                ['%s', '%s', '%s'],
                ['%d']
            );
            
            error_log("AI Post AsyncQueue: Task {$task->id} completed successfully");
            
        } catch (\Exception $e) {
            // 处理任务失败
            $this->handle_task_failure($task, $e->getMessage());
        }
    }
    
    /**
     * 执行任务
     * 
     * @param string $task_type 任务类型
     * @param array $task_data 任务数据
     * @return mixed 执行结果
     * @throws \Exception 执行异常
     */
    private function execute_task($task_type, $task_data) {
        switch ($task_type) {
            case self::TYPE_CONTENT_GENERATE:
                return $this->execute_content_generation($task_data);
                
            case self::TYPE_IMAGE_PROCESS:
                return $this->execute_image_processing($task_data);
                
            case self::TYPE_POST_PUBLISH:
                return $this->execute_post_publishing($task_data);
                
            case self::TYPE_API_CALL:
                return $this->execute_api_call($task_data);
                
            case self::TYPE_DATA_SYNC:
                return $this->execute_data_sync($task_data);
                
            default:
                throw new \Exception("Unknown task type: {$task_type}");
        }
    }
    
    /**
     * 执行内容生成任务
     * 
     * @param array $task_data 任务数据
     * @return array 执行结果
     */
    private function execute_content_generation($task_data) {
        // 这里调用原插件的内容生成逻辑
        // 为了兼容性，我们使用现有的API
        
        $result = [
            'success' => true,
            'content' => 'Generated content placeholder',
            'generated_at' => current_time('mysql')
        ];
        
        // 实际实现应该调用原插件的内容生成器
        // $generator = new ContentGenerator();
        // $result = $generator->generate($task_data);
        
        return $result;
    }
    
    /**
     * 执行图片处理任务
     * 
     * @param array $task_data 任务数据
     * @return array 执行结果
     */
    private function execute_image_processing($task_data) {
        $result = [
            'success' => true,
            'processed_images' => [],
            'processed_at' => current_time('mysql')
        ];
        
        // 实际实现应该调用原插件的图片处理器
        // $processor = new ImageProcessor();
        // $result = $processor->process($task_data);
        
        return $result;
    }
    
    /**
     * 执行文章发布任务
     * 
     * @param array $task_data 任务数据
     * @return array 执行结果
     */
    private function execute_post_publishing($task_data) {
        $result = [
            'success' => true,
            'post_id' => 0,
            'published_at' => current_time('mysql')
        ];
        
        // 实际实现应该调用原插件的文章发布器
        // $publisher = new PostPublisher();
        // $result = $publisher->publish($task_data);
        
        return $result;
    }
    
    /**
     * 执行API调用任务
     * 
     * @param array $task_data 任务数据
     * @return array 执行结果
     */
    private function execute_api_call($task_data) {
        $result = [
            'success' => true,
            'response' => [],
            'called_at' => current_time('mysql')
        ];
        
        // 实际实现应该调用原插件的API客户端
        // $client = new APIClient();
        // $result = $client->call($task_data);
        
        return $result;
    }
    
    /**
     * 执行数据同步任务
     * 
     * @param array $task_data 任务数据
     * @return array 执行结果
     */
    private function execute_data_sync($task_data) {
        $result = [
            'success' => true,
            'synced_items' => 0,
            'synced_at' => current_time('mysql')
        ];
        
        // 实际实现应该调用原插件的数据同步器
        // $syncer = new DataSyncer();
        // $result = $syncer->sync($task_data);
        
        return $result;
    }
    
    /**
     * 处理任务失败
     * 
     * @param object $task 任务对象
     * @param string $error_message 错误信息
     */
    private function handle_task_failure($task, $error_message) {
        global $wpdb;
        
        $retry_count = $task->retry_count + 1;
        
        if ($retry_count >= $task->max_retries) {
            // 达到最大重试次数，标记为失败
            $wpdb->update(
                $this->table_name,
                [
                    'status' => self::STATUS_FAILED,
                    'error_message' => $error_message,
                    'completed_at' => current_time('mysql')
                ],
                ['id' => $task->id],
                ['%s', '%s', '%s'],
                ['%d']
            );
            
            error_log("AI Post AsyncQueue: Task {$task->id} failed after {$retry_count} retries: {$error_message}");
            
        } else {
            // 安排重试
            $retry_delay = isset($this->retry_delays[$retry_count - 1]) 
                ? $this->retry_delays[$retry_count - 1] 
                : 3600; // 默认1小时
            
            $scheduled_at = date('Y-m-d H:i:s', strtotime("+{$retry_delay} seconds"));
            
            $wpdb->update(
                $this->table_name,
                [
                    'status' => self::STATUS_RETRY,
                    'retry_count' => $retry_count,
                    'error_message' => $error_message,
                    'scheduled_at' => $scheduled_at
                ],
                ['id' => $task->id],
                ['%s', '%d', '%s', '%s'],
                ['%d']
            );
            
            error_log("AI Post AsyncQueue: Task {$task->id} scheduled for retry {$retry_count} at {$scheduled_at}");
        }
    }
    
    /**
     * 触发队列处理
     */
    public function trigger_processing() {
        // 使用wp_schedule_single_event来立即处理队列
        if (!wp_next_scheduled('ai_post_process_queue_immediate')) {
            wp_schedule_single_event(time(), 'ai_post_process_queue_immediate');
        }
        
        add_action('ai_post_process_queue_immediate', [$this, 'process_queue']);
    }
    
    /**
     * 获取队列状态
     * 
     * @return array 队列状态
     */
    public function get_queue_status() {
        global $wpdb;
        
        $status_counts = $wpdb->get_results(
            "SELECT status, COUNT(*) as count 
             FROM {$this->table_name} 
             GROUP BY status"
        );
        
        $status = [
            'total' => 0,
            'pending' => 0,
            'processing' => 0,
            'completed' => 0,
            'failed' => 0,
            'retry' => 0
        ];
        
        foreach ($status_counts as $row) {
            $status[$row->status] = (int) $row->count;
            $status['total'] += (int) $row->count;
        }
        
        // 获取最近的任务
        $recent_tasks = $wpdb->get_results(
            "SELECT * FROM {$this->table_name} 
             ORDER BY created_at DESC 
             LIMIT 10"
        );
        
        $status['recent_tasks'] = $recent_tasks;
        
        return $status;
    }
    
    /**
     * 清理旧任务
     */
    public static function cleanup_old_tasks() {
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'ai_post_async_queue';
        
        // 删除30天前的已完成或失败任务
        $cutoff_date = date('Y-m-d H:i:s', strtotime('-30 days'));
        
        $deleted = $wpdb->query(
            $wpdb->prepare(
                "DELETE FROM {$table_name} 
                 WHERE status IN (%s, %s) 
                 AND completed_at < %s",
                self::STATUS_COMPLETED,
                self::STATUS_FAILED,
                $cutoff_date
            )
        );
        
        if ($deleted !== false) {
            error_log("AI Post AsyncQueue: Cleaned up {$deleted} old tasks");
        }
    }
    
    /**
     * 更新队列统计
     */
    private function update_queue_stats() {
        $status = $this->get_queue_status();
        
        // 更新选项，供监控使用
        update_option('ai_post_queue_stats', [
            'last_updated' => current_time('mysql'),
            'total_tasks' => $status['total
