package com.dora.scheduler;

import com.dora.entity.AiTask;
import com.dora.mapper.AiTaskMapper;
import com.dora.service.AiTaskService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 队列任务超时检查器
 * 
 * <p>功能：
 * <ul>
 *   <li>定期检查在队列中等待超过指定时间的任务</li>
 *   <li>自动取消超时任务并退还积分</li>
 *   <li>防止任务长时间卡在队列中</li>
 * </ul>
 *
 * @author 1818AI
 * @since 2025-11-03
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class QueuedTaskTimeoutChecker {

    private final AiTaskMapper aiTaskMapper;
    private final AiTaskService aiTaskService;

    /**
     * 队列超时时间（小时）
     * 默认24小时，可通过配置文件修改
     */
    @Value("${ai.queue.timeout-hours:24}")
    private int queueTimeoutHours;

    /**
     * 每小时执行一次超时检查
     */
    @Scheduled(fixedRate = 3600000) // 3600000ms = 1小时
    public void checkQueuedTasksTimeout() {
        try {
            LocalDateTime timeoutThreshold = LocalDateTime.now().minusHours(queueTimeoutHours);
            
            log.debug("开始检查队列超时任务，超时阈值: {} ({}小时前)", 
                     timeoutThreshold, queueTimeoutHours);
            
            // 查询超时的队列任务
            List<AiTask> timeoutTasks = aiTaskMapper.findQueuedTasksBeforeTime(timeoutThreshold);
            
            if (timeoutTasks.isEmpty()) {
                log.debug("未发现队列超时任务");
                return;
            }
            
            log.warn("发现 {} 个队列超时任务（超过{}小时），准备自动取消", 
                    timeoutTasks.size(), queueTimeoutHours);
            
            int successCount = 0;
            int failCount = 0;
            
            for (AiTask task : timeoutTasks) {
                try {
                    log.warn("队列任务超时 - taskNo: {}, 模型: {}, 创建时间: {}, 已等待: {} 小时", 
                            task.getTaskNo(), 
                            task.getModelName(), 
                            task.getCreateTime(),
                            java.time.Duration.between(task.getCreateTime(), LocalDateTime.now()).toHours());
                    
                    // 调用取消任务方法（会自动退还积分和从队列移除）
                    boolean success = aiTaskService.cancelTask(task.getTaskNo());
                    
                    if (success) {
                        successCount++;
                        log.info("队列超时任务已自动取消: {}", task.getTaskNo());
                    } else {
                        failCount++;
                        log.error("队列超时任务取消失败: {}, 状态: {}", 
                                 task.getTaskNo(), task.getStatus());
                    }
                    
                } catch (Exception e) {
                    failCount++;
                    log.error("处理队列超时任务异常: {}", task.getTaskNo(), e);
                }
            }
            
            log.info("队列超时检查完成 - 总计: {}, 成功取消: {}, 失败: {}", 
                    timeoutTasks.size(), successCount, failCount);
            
        } catch (Exception e) {
            log.error("队列超时检查器执行失败", e);
        }
    }

    /**
     * 立即执行一次检查（用于测试或手动触发）
     */
    public void checkNow() {
        log.info("手动触发队列超时检查");
        checkQueuedTasksTimeout();
    }
}

