package com.lingyue.parse.service;

import com.lingyue.parse.config.RabbitMQConfig;
import com.lingyue.parse.dto.ParseTaskMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

/**
 * 解析任务执行器
 * 支持两种模式：
 * 1. 线程池模式（默认，符合GPU线性处理约束）
 * 2. RabbitMQ消息队列模式（可选，支持任务持久化和重试）
 */
@Slf4j
@Component
public class ParseTaskExecutor {

    private final ParseService parseService;
    private final RabbitTemplate rabbitTemplate;
    
    @org.springframework.beans.factory.annotation.Value("${parse.task.use-mq:false}")
    private boolean useMq;

    private final ThreadPoolTaskExecutor executor;

    public ParseTaskExecutor(ParseService parseService, 
                             @org.springframework.beans.factory.annotation.Autowired(required = false) 
                             RabbitTemplate rabbitTemplate) {
        this.parseService = parseService;
        this.rabbitTemplate = rabbitTemplate;
        ThreadPoolTaskExecutor tp = new ThreadPoolTaskExecutor();
        tp.setCorePoolSize(1);
        tp.setMaxPoolSize(1);
        tp.setQueueCapacity(1000);
        tp.setThreadNamePrefix("parse-task-");
        tp.initialize();
        this.executor = tp;
    }

    /**
     * 提交解析任务（异步执行）
     * 根据配置选择线程池或消息队列模式
     *
     * @param documentId 文档ID
     * @param sourceFilePath 原始文件路径
     * @param fileType 文件类型
     */
    public void submitParseTask(String documentId, String sourceFilePath, com.lingyue.parse.enums.FileType fileType) {
        if (useMq && rabbitTemplate != null) {
            submitParseTaskViaMq(documentId, sourceFilePath, fileType, null, 0);
        } else {
            submitParseTaskViaThreadPool(documentId, sourceFilePath, fileType);
        }
    }
    
    /**
     * 提交解析任务（异步执行，兼容旧接口）
     *
     * @param documentId 文档ID
     * @param sourceFilePath 原始文件路径
     */
    public void submitParseTask(String documentId, String sourceFilePath) {
        // 自动检测文件类型
        com.lingyue.parse.enums.FileType fileType = detectFileType(sourceFilePath);
        submitParseTask(documentId, sourceFilePath, fileType);
    }
    
    /**
     * 通过消息队列提交解析任务
     */
    private void submitParseTaskViaMq(String documentId, String sourceFilePath, 
                                      com.lingyue.parse.enums.FileType fileType, 
                                      String userId, int priority) {
        ParseTaskMessage message = ParseTaskMessage.builder()
                .documentId(documentId)
                .sourceFilePath(sourceFilePath)
                .fileType(fileType.name())
                .userId(userId)
                .priority(priority)
                .retryCount(0)
                .maxRetries(3)
                .timestamp(System.currentTimeMillis())
                .build();
        
        try {
            rabbitTemplate.convertAndSend(RabbitMQConfig.PARSE_TASK_QUEUE, message);
            log.info("解析任务已发送到消息队列: documentId={}, fileType={}", documentId, fileType);
        } catch (Exception e) {
            log.error("发送解析任务到消息队列失败，降级为线程池模式: documentId={}", documentId, e);
            // 降级为线程池模式
            submitParseTaskViaThreadPool(documentId, sourceFilePath, fileType);
        }
    }
    
    /**
     * 通过线程池提交解析任务
     */
    private void submitParseTaskViaThreadPool(String documentId, String sourceFilePath, 
                                              com.lingyue.parse.enums.FileType fileType) {
        executor.submit(() -> {
            try {
                parseService.parseAndSaveText(documentId, sourceFilePath, fileType);
            } catch (Exception e) {
                log.error("解析任务执行失败, documentId={}", documentId, e);
            }
        });
    }
    
    /**
     * 检测文件类型
     */
    private com.lingyue.parse.enums.FileType detectFileType(String filePath) {
        java.io.File file = new java.io.File(filePath);
        String fileName = file.getName();
        String extension = "";
        if (fileName.contains(".")) {
            extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        }
        return com.lingyue.parse.enums.FileType.fromExtension(extension);
    }
}


