/**
 * @ProjectName: 智慧评标-主观分助手
 * @Package: com.zhpb.gdyd_zhpb_zgf.service
 * @ClassName: CatalogExtractionRetryService
 * @Description: 目录摘取重试定时任务服务 - 扫描卡住的文件并进行重试
 * @Author: 张志锋
 * @Date: 2025-12-11
 * @Version: 1.0
 * @Copyright: © 2025 智慧评标-主观分助手
 */
package com.zhpb.gdyd_zhpb_zgf.service;

import com.zhpb.gdyd_zhpb_zgf.entity.mysql.File;
import com.zhpb.gdyd_zhpb_zgf.repository.mysql.FileRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 目录摘取重试定时任务服务
 * 每5分钟扫描一次状态为processing且超过30分钟未更新的文件，进行重试
 * 重试3次后标记为失败
 */
@Service
public class CatalogExtractionRetryService {

    private static final Logger logger = LoggerFactory.getLogger(CatalogExtractionRetryService.class);

    /** 卡住超时时间：30分钟 */
    private static final int STUCK_TIMEOUT_MINUTES = 30;
    
    /** 最大重试次数 */
    private static final int MAX_RETRY_COUNT = 3;

    @Autowired
    private FileRepository fileRepository;

    @Autowired
    private FileService fileService;

    /**
     * 定时任务：每5分钟执行一次，扫描卡住的目录摘取任务
     */
    @Scheduled(fixedRate = 5 * 60 * 1000, initialDelay = 60 * 1000) // 5分钟执行一次，启动后1分钟开始
    @Transactional
    public void scanAndRetryStuckCatalogExtraction() {
        logger.info("[目录摘取重试] ========== 开始扫描卡住的目录摘取任务 ==========");
        
        try {
            // 计算30分钟前的时间点
            LocalDateTime cutoffTime = LocalDateTime.now().minusMinutes(STUCK_TIMEOUT_MINUTES);
            
            // 查询状态为processing且更新时间超过30分钟的文件
            List<File> stuckFiles = fileRepository.findByCatalogExtractionStatusAndUpdateTimeBefore("processing", cutoffTime);
            
            if (stuckFiles.isEmpty()) {
                logger.info("[目录摘取重试] 没有发现卡住的文件");
                return;
            }
            
            logger.info("[目录摘取重试] 发现 {} 个卡住的文件，开始处理", stuckFiles.size());
            
            int retriedCount = 0;
            int failedCount = 0;
            
            for (File file : stuckFiles) {
                try {
                    int retryCount = file.getCatalogExtractionRetryCount() != null ? file.getCatalogExtractionRetryCount() : 0;
                    
                    if (retryCount >= MAX_RETRY_COUNT) {
                        // 已达到最大重试次数，标记为失败
                        file.setCatalogExtractionStatus("failed");
                        fileRepository.save(file);
                        failedCount++;
                        logger.warn("[目录摘取重试] 文件已达最大重试次数({}次)，标记为失败: fileId={}, fileName={}", 
                            MAX_RETRY_COUNT, file.getFileId(), file.getFileName());
                    } else {
                        // 重置状态为 not_started，等待下次正常处理流程
                        file.setCatalogExtractionStatus("not_started");
                        fileRepository.save(file);
                        retriedCount++;
                        logger.info("[目录摘取重试] 重置文件状态为not_started，等待重新处理: fileId={}, fileName={}, 当前重试次数={}",
                            file.getFileId(), file.getFileName(), retryCount);
                    }
                } catch (Exception e) {
                    logger.error("[目录摘取重试] 处理文件失败: fileId={}", file.getFileId(), e);
                }
            }
            
            logger.info("[目录摘取重试] ========== 扫描完成: 重置{}个, 标记失败{}个 ==========", retriedCount, failedCount);
            
        } catch (Exception e) {
            logger.error("[目录摘取重试] 扫描任务执行失败", e);
        }
    }
    
    /**
     * 手动触发重试所有卡住的文件（可通过API调用）
     */
    public int manualRetryStuckFiles() {
        logger.info("[目录摘取重试] 手动触发重试所有卡住文件");
        scanAndRetryStuckCatalogExtraction();
        return 0;
    }
}
