package com.example.demo.service;

import com.example.demo.model.*;
import com.example.demo.repository.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.HashMap;

/**
 * 任务清理服务
 * 负责定期清理失败任务记录，释放数据库空间
 * 
 * 说明：
 * - 成功任务保留在原表（text_to_video_tasks 等）中，不再复制到归档表
 * - 失败任务删除前通过 user_error_log 记录（失败信息在发生时已记录，这里做兜底）
 * - 已移除 completed_tasks_archive 和 failed_tasks_cleanup_log 表的依赖
 */
@Service
@Transactional
public class TaskCleanupService {
    
    private static final Logger logger = LoggerFactory.getLogger(TaskCleanupService.class);
    
    @Autowired
    private TaskQueueRepository taskQueueRepository;
    
    @Autowired
    private TextToVideoTaskRepository textToVideoTaskRepository;
    
    @Autowired
    private ImageToVideoTaskRepository imageToVideoTaskRepository;
    
    @Autowired
    private StoryboardVideoTaskRepository storyboardVideoTaskRepository;
    
    @Autowired
    private UserErrorLogService userErrorLogService;
    
    @Value("${task.cleanup.retention-days:30}")
    private int retentionDays;
    
    /**
     * 执行完整的任务清理
     * 1. 清理失败的文生视频任务
     * 2. 清理失败的图生视频任务
     * 3. 清理失败的分镜视频任务
     * 4. 清理已完成/失败的任务队列记录
     */
    public Map<String, Object> performFullCleanup() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            logger.info("开始执行完整任务清理...");
            
            // 1. 清理文生视频任务
            Map<String, Object> textCleanupResult = cleanupTextToVideoTasks();
            
            // 2. 清理图生视频任务
            Map<String, Object> imageCleanupResult = cleanupImageToVideoTasks();
            
            // 3. 清理分镜视频任务
            Map<String, Object> storyboardCleanupResult = cleanupStoryboardVideoTasks();
            
            // 4. 清理任务队列
            Map<String, Object> queueCleanupResult = cleanupTaskQueue();
            
            // 汇总结果
            result.put("success", true);
            result.put("message", "任务清理完成");
            result.put("textToVideo", textCleanupResult);
            result.put("imageToVideo", imageCleanupResult);
            result.put("storyboardVideo", storyboardCleanupResult);
            result.put("taskQueue", queueCleanupResult);
            
            logger.info("任务清理完成: {}", result);
            
        } catch (Exception e) {
            logger.error("任务清理失败", e);
            result.put("success", false);
            result.put("message", "任务清理失败: " + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 清理文生视频任务
     * 只删除失败任务，成功任务保留在原表中作为创作历史
     */
    private Map<String, Object> cleanupTextToVideoTasks() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<TextToVideoTask> failedTasks = textToVideoTaskRepository.findByStatus(TextToVideoTask.TaskStatus.FAILED);
            
            int cleanedCount = 0;
            
            // 删除前通过 user_error_log 做兜底记录
            for (TextToVideoTask task : failedTasks) {
                logFailedTaskCleanup(task.getUsername(), task.getTaskId(), "TEXT_TO_VIDEO", task.getErrorMessage());
                cleanedCount++;
            }
            
            // 删除失败任务记录
            if (!failedTasks.isEmpty()) {
                textToVideoTaskRepository.deleteAll(failedTasks);
            }
            
            long completedCount = textToVideoTaskRepository.findByStatus(TextToVideoTask.TaskStatus.COMPLETED).size();
            
            result.put("completedKept", completedCount);
            result.put("failedCleaned", cleanedCount);
            
            logger.info("文生视频任务处理完成: 保留{}个成功任务, 清理{}个失败任务", completedCount, cleanedCount);
            
        } catch (Exception e) {
            logger.error("清理文生视频任务失败", e);
            result.put("error", e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 清理图生视频任务
     * 只删除失败任务，成功任务保留在原表中作为创作历史
     */
    private Map<String, Object> cleanupImageToVideoTasks() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<ImageToVideoTask> failedTasks = imageToVideoTaskRepository.findByStatus(ImageToVideoTask.TaskStatus.FAILED);
            
            int cleanedCount = 0;
            
            for (ImageToVideoTask task : failedTasks) {
                logFailedTaskCleanup(task.getUsername(), task.getTaskId(), "IMAGE_TO_VIDEO", task.getErrorMessage());
                cleanedCount++;
            }
            
            if (!failedTasks.isEmpty()) {
                imageToVideoTaskRepository.deleteAll(failedTasks);
            }
            
            long completedCount = imageToVideoTaskRepository.findByStatus(ImageToVideoTask.TaskStatus.COMPLETED).size();
            
            result.put("completedKept", completedCount);
            result.put("failedCleaned", cleanedCount);
            
            logger.info("图生视频任务处理完成: 保留{}个成功任务, 清理{}个失败任务", completedCount, cleanedCount);
            
        } catch (Exception e) {
            logger.error("清理图生视频任务失败", e);
            result.put("error", e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 清理分镜视频任务
     * 只删除失败任务，成功任务保留在原表中作为创作历史
     */
    private Map<String, Object> cleanupStoryboardVideoTasks() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<StoryboardVideoTask> failedTasks = storyboardVideoTaskRepository.findByStatus(StoryboardVideoTask.TaskStatus.FAILED);
            
            int cleanedCount = 0;
            
            for (StoryboardVideoTask task : failedTasks) {
                logFailedTaskCleanup(task.getUsername(), task.getTaskId(), "STORYBOARD_VIDEO", task.getErrorMessage());
                cleanedCount++;
            }
            
            if (!failedTasks.isEmpty()) {
                storyboardVideoTaskRepository.deleteAll(failedTasks);
            }
            
            result.put("failedCleaned", cleanedCount);
            
            logger.info("分镜视频任务处理完成: 清理{}个失败任务（成功任务保留）", cleanedCount);
            
        } catch (Exception e) {
            logger.error("清理分镜视频任务失败", e);
            result.put("error", e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 清理任务队列
     */
    private Map<String, Object> cleanupTaskQueue() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<TaskQueue> completedQueues = taskQueueRepository.findByStatus(TaskQueue.QueueStatus.COMPLETED);
            List<TaskQueue> failedQueues = taskQueueRepository.findByStatus(TaskQueue.QueueStatus.FAILED);
            
            int cleanedCount = completedQueues.size() + failedQueues.size();
            
            if (!completedQueues.isEmpty()) {
                taskQueueRepository.deleteAll(completedQueues);
            }
            
            if (!failedQueues.isEmpty()) {
                taskQueueRepository.deleteAll(failedQueues);
            }
            
            result.put("cleaned", cleanedCount);
            
            logger.info("任务队列清理完成: 清理{}个记录", cleanedCount);
            
        } catch (Exception e) {
            logger.error("清理任务队列失败", e);
            result.put("error", e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 通过 user_error_log 记录失败任务清理信息（兜底，防止之前遗漏）
     */
    private void logFailedTaskCleanup(String username, String taskId, String taskType, String errorMessage) {
        try {
            userErrorLogService.logErrorAsync(
                username,
                UserErrorLog.ErrorType.TASK_PROCESSING_ERROR,
                "任务清理: " + (errorMessage != null ? errorMessage : "未知错误"),
                "TaskCleanupService",
                taskId,
                taskType
            );
        } catch (Exception e) {
            // 记录日志失败不影响清理流程
            logger.warn("记录失败任务清理日志失败: taskId={}", taskId);
        }
    }
    
    /**
     * 获取清理统计信息
     */
    @Transactional(readOnly = true)
    public Map<String, Object> getCleanupStats() {
        Map<String, Object> stats = new HashMap<>();
        
        try {
            long totalTextTasks = textToVideoTaskRepository.count();
            long completedTextTasks = textToVideoTaskRepository.findByStatus(TextToVideoTask.TaskStatus.COMPLETED).size();
            long failedTextTasks = textToVideoTaskRepository.findByStatus(TextToVideoTask.TaskStatus.FAILED).size();
            
            long totalImageTasks = imageToVideoTaskRepository.count();
            long completedImageTasks = imageToVideoTaskRepository.findByStatus(ImageToVideoTask.TaskStatus.COMPLETED).size();
            long failedImageTasks = imageToVideoTaskRepository.findByStatus(ImageToVideoTask.TaskStatus.FAILED).size();
            
            long totalQueueTasks = taskQueueRepository.count();
            long completedQueueTasks = taskQueueRepository.findByStatus(TaskQueue.QueueStatus.COMPLETED).size();
            long failedQueueTasks = taskQueueRepository.findByStatus(TaskQueue.QueueStatus.FAILED).size();
            
            stats.put("currentTasks", Map.of(
                "textToVideo", Map.of("total", totalTextTasks, "completed", completedTextTasks, "failed", failedTextTasks),
                "imageToVideo", Map.of("total", totalImageTasks, "completed", completedImageTasks, "failed", failedImageTasks),
                "taskQueue", Map.of("total", totalQueueTasks, "completed", completedQueueTasks, "failed", failedQueueTasks)
            ));
            
            stats.put("config", Map.of(
                "retentionDays", retentionDays
            ));
            
        } catch (Exception e) {
            logger.error("获取清理统计信息失败", e);
            stats.put("error", e.getMessage());
        }
        
        return stats;
    }
    
    /**
     * 手动清理指定用户的失败任务
     */
    public Map<String, Object> cleanupUserTasks(String username) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            int textCleaned = 0;
            int imageCleaned = 0;
            
            // 清理用户的失败文生视频任务
            List<TextToVideoTask> userTextTasks = textToVideoTaskRepository.findByUsernameOrderByCreatedAtDesc(username);
            List<TextToVideoTask> failedTextTasks = userTextTasks.stream()
                .filter(t -> t.getStatus() == TextToVideoTask.TaskStatus.FAILED)
                .toList();
            
            for (TextToVideoTask task : failedTextTasks) {
                logFailedTaskCleanup(task.getUsername(), task.getTaskId(), "TEXT_TO_VIDEO", task.getErrorMessage());
                textCleaned++;
            }
            if (!failedTextTasks.isEmpty()) {
                textToVideoTaskRepository.deleteAll(failedTextTasks);
            }
            
            // 清理用户的失败图生视频任务
            List<ImageToVideoTask> userImageTasks = imageToVideoTaskRepository.findByUsernameOrderByCreatedAtDesc(username);
            List<ImageToVideoTask> failedImageTasks = userImageTasks.stream()
                .filter(t -> t.getStatus() == ImageToVideoTask.TaskStatus.FAILED)
                .toList();
            
            for (ImageToVideoTask task : failedImageTasks) {
                logFailedTaskCleanup(task.getUsername(), task.getTaskId(), "IMAGE_TO_VIDEO", task.getErrorMessage());
                imageCleaned++;
            }
            if (!failedImageTasks.isEmpty()) {
                imageToVideoTaskRepository.deleteAll(failedImageTasks);
            }
            
            result.put("success", true);
            result.put("message", "用户失败任务清理完成");
            result.put("textToVideo", Map.of("failedCleaned", textCleaned));
            result.put("imageToVideo", Map.of("failedCleaned", imageCleaned));
            
            logger.info("用户{}失败任务清理完成: 文生视频清理{}个, 图生视频清理{}个", 
                       username, textCleaned, imageCleaned);
            
        } catch (Exception e) {
            logger.error("清理用户{}任务失败", username, e);
            result.put("success", false);
            result.put("message", "清理用户任务失败: " + e.getMessage());
        }
        
        return result;
    }
}
