package com.example.demo.service;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.demo.model.ImageToVideoTask;
import com.example.demo.model.PointsFreezeRecord;
import com.example.demo.model.TaskQueue;
import com.example.demo.model.TextToVideoTask;
import com.example.demo.model.UserWork;
import com.example.demo.repository.ImageToVideoTaskRepository;
import com.example.demo.repository.TaskQueueRepository;
import com.example.demo.repository.TextToVideoTaskRepository;

/**
 * 任务队列服务类
 * 管理用户的视频生成任务队列，限制每个用户最多3个任务
 */
@Service
@Transactional
public class TaskQueueService {

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

    @Autowired
    private TaskQueueRepository taskQueueRepository;

    @Autowired
    private TextToVideoTaskRepository textToVideoTaskRepository;

    @Autowired
    private ImageToVideoTaskRepository imageToVideoTaskRepository;

    @Autowired
    private RealAIService realAIService;

    @Autowired
    private UserService userService;

    @Autowired
    private UserWorkService userWorkService;

    private static final int MAX_TASKS_PER_USER = 3;

    /**
     * 添加文生视频任务到队列
     */
    public TaskQueue addTextToVideoTask(String username, String taskId) {
        return addTaskToQueue(username, taskId, TaskQueue.TaskType.TEXT_TO_VIDEO);
    }

    /**
     * 添加图生视频任务到队列
     */
    public TaskQueue addImageToVideoTask(String username, String taskId) {
        return addTaskToQueue(username, taskId, TaskQueue.TaskType.IMAGE_TO_VIDEO);
    }

    /**
     * 添加任务到队列
     */
    private TaskQueue addTaskToQueue(String username, String taskId, TaskQueue.TaskType taskType) {
        // 检查用户是否已有3个待处理任务
        long pendingCount = taskQueueRepository.countPendingTasksByUsername(username);
        if (pendingCount >= MAX_TASKS_PER_USER) {
            throw new RuntimeException("用户 " + username + " 的队列已满，最多只能有 " + MAX_TASKS_PER_USER + " 个待处理任务");
        }

        // 检查任务是否已存在
        Optional<TaskQueue> existingTask = taskQueueRepository.findByTaskId(taskId);
        if (existingTask.isPresent()) {
            throw new RuntimeException("任务 " + taskId + " 已存在于队列中");
        }

        // 计算任务所需积分 - 降低积分要求
        Integer requiredPoints = calculateRequiredPoints(taskType);
        
        // 冻结积分
        PointsFreezeRecord.TaskType freezeTaskType = convertTaskType(taskType);
        
        userService.freezePoints(username, taskId, freezeTaskType, requiredPoints, 
            "任务提交冻结积分 - " + taskType.getDescription());

        // 创建新的队列任务
        TaskQueue taskQueue = new TaskQueue(username, taskId, taskType);
        taskQueue = taskQueueRepository.save(taskQueue);

        logger.info("任务 {} 已添加到队列，用户: {}, 类型: {}, 冻结积分: {}", taskId, username, taskType.getDescription(), requiredPoints);
        return taskQueue;
    }

    /**
     * 计算任务所需积分 - 降低积分要求
     */
    private Integer calculateRequiredPoints(TaskQueue.TaskType taskType) {
        switch (taskType) {
            case TEXT_TO_VIDEO:
                return 20; // 文生视频默认20积分
            case IMAGE_TO_VIDEO:
                return 25; // 图生视频默认25积分
            default:
                throw new IllegalArgumentException("不支持的任务类型: " + taskType);
        }
    }

    /**
     * 转换任务类型
     */
    private PointsFreezeRecord.TaskType convertTaskType(TaskQueue.TaskType taskType) {
        switch (taskType) {
            case TEXT_TO_VIDEO:
                return PointsFreezeRecord.TaskType.TEXT_TO_VIDEO;
            case IMAGE_TO_VIDEO:
                return PointsFreezeRecord.TaskType.IMAGE_TO_VIDEO;
            default:
                throw new IllegalArgumentException("不支持的任务类型: " + taskType);
        }
    }

    /**
     * 处理队列中的待处理任务
     */
    @Transactional
    public void processPendingTasks() {
        List<TaskQueue> pendingTasks = taskQueueRepository.findAllPendingTasks();
        
        for (TaskQueue taskQueue : pendingTasks) {
            try {
                processTask(taskQueue);
            } catch (Exception e) {
                logger.error("处理任务失败: {}", taskQueue.getTaskId(), e);
                taskQueue.updateStatus(TaskQueue.QueueStatus.FAILED);
                taskQueue.setErrorMessage("处理失败: " + e.getMessage());
                taskQueueRepository.save(taskQueue);
                
                // 返还冻结的积分
                try {
                    userService.returnFrozenPoints(taskQueue.getTaskId());
                } catch (Exception freezeException) {
                    logger.error("返还冻结积分失败: {}", taskQueue.getTaskId(), freezeException);
                }
            }
        }
    }

    /**
     * 处理单个任务
     */
    private void processTask(TaskQueue taskQueue) {
        logger.info("开始处理任务: {}, 类型: {}", taskQueue.getTaskId(), taskQueue.getTaskType());

        // 更新状态为处理中
        taskQueue.updateStatus(TaskQueue.QueueStatus.PROCESSING);
        taskQueueRepository.save(taskQueue);

        try {
            // 根据任务类型调用相应的API
            Map<String, Object> apiResponse;
            
            if (taskQueue.getTaskType() == TaskQueue.TaskType.TEXT_TO_VIDEO) {
                apiResponse = processTextToVideoTask(taskQueue);
            } else {
                apiResponse = processImageToVideoTask(taskQueue);
            }

            // 提取真实任务ID
            String realTaskId = extractRealTaskId(apiResponse);
            if (realTaskId != null) {
                taskQueue.setRealTaskId(realTaskId);
                taskQueueRepository.save(taskQueue);
                logger.info("任务 {} 已提交到外部API，真实任务ID: {}", taskQueue.getTaskId(), realTaskId);
            } else {
                throw new RuntimeException("API未返回有效的任务ID");
            }

        } catch (Exception e) {
            logger.error("提交任务到外部API失败: {}", taskQueue.getTaskId(), e);
            taskQueue.updateStatus(TaskQueue.QueueStatus.FAILED);
            taskQueue.setErrorMessage("API提交失败: " + e.getMessage());
            taskQueueRepository.save(taskQueue);
        }
    }

    /**
     * 处理文生视频任务
     */
    private Map<String, Object> processTextToVideoTask(TaskQueue taskQueue) {
        Optional<TextToVideoTask> taskOpt = textToVideoTaskRepository.findByTaskId(taskQueue.getTaskId());
        if (!taskOpt.isPresent()) {
            throw new RuntimeException("找不到文生视频任务: " + taskQueue.getTaskId());
        }

        TextToVideoTask task = taskOpt.get();
        return realAIService.submitTextToVideoTask(
            task.getPrompt(),
            task.getAspectRatio(),
            String.valueOf(task.getDuration()),
            task.isHdMode()
        );
    }

    /**
     * 处理图生视频任务
     */
    private Map<String, Object> processImageToVideoTask(TaskQueue taskQueue) {
        Optional<ImageToVideoTask> taskOpt = imageToVideoTaskRepository.findByTaskId(taskQueue.getTaskId());
        if (!taskOpt.isPresent()) {
            throw new RuntimeException("找不到图生视频任务: " + taskQueue.getTaskId());
        }

        ImageToVideoTask task = taskOpt.get();
        
        // 从文件系统读取图片并转换为Base64
        String imageBase64 = convertImageFileToBase64(task.getFirstFrameUrl());
        
        return realAIService.submitImageToVideoTask(
            task.getPrompt(),
            imageBase64,
            task.getAspectRatio(),
            task.getDuration().toString(),
            Boolean.TRUE.equals(task.getHdMode())
        );
    }

    /**
     * 将图片文件转换为Base64
     */
    private String convertImageFileToBase64(String imageUrl) {
        try {
            // 检查是否是相对路径
            if (!imageUrl.startsWith("http://") && !imageUrl.startsWith("https://")) {
                // 从本地文件系统读取图片
                java.nio.file.Path imagePath = java.nio.file.Paths.get(imageUrl);
                
                // 如果文件不存在，尝试使用绝对路径
                if (!java.nio.file.Files.exists(imagePath)) {
                    // 获取当前工作目录并构建绝对路径
                    String currentDir = System.getProperty("user.dir");
                    java.nio.file.Path absolutePath = java.nio.file.Paths.get(currentDir, imageUrl);
                    logger.info("当前工作目录: {}", currentDir);
                    logger.info("尝试绝对路径: {}", absolutePath);
                    
                    if (java.nio.file.Files.exists(absolutePath)) {
                        imagePath = absolutePath;
                        logger.info("找到图片文件: {}", absolutePath);
                    } else {
                        // 尝试其他可能的路径
                        java.nio.file.Path altPath = java.nio.file.Paths.get("C:\\Users\\UI\\Desktop\\AIGC\\demo", imageUrl);
                        logger.info("尝试备用路径: {}", altPath);
                        
                        if (java.nio.file.Files.exists(altPath)) {
                            imagePath = altPath;
                            logger.info("找到图片文件(备用路径): {}", altPath);
                        } else {
                            throw new RuntimeException("图片文件不存在: " + imageUrl + ", 绝对路径: " + absolutePath + ", 备用路径: " + altPath);
                        }
                    }
                }
                
                byte[] imageBytes = java.nio.file.Files.readAllBytes(imagePath);
                return realAIService.convertImageToBase64(imageBytes, "image/jpeg");
            } else {
                // 从URL读取图片内容
                kong.unirest.HttpResponse<byte[]> response = kong.unirest.Unirest.get(imageUrl)
                    .asBytes();
                
                if (response.getStatus() == 200 && response.getBody() != null) {
                    // 使用RealAIService的convertImageToBase64方法
                    return realAIService.convertImageToBase64(response.getBody(), "image/jpeg");
                } else {
                    throw new RuntimeException("无法从URL读取图片: " + imageUrl + ", 状态码: " + response.getStatus());
                }
            }
        } catch (Exception e) {
            logger.error("读取图片文件失败: {}", imageUrl, e);
            throw new RuntimeException("图片文件读取失败: " + e.getMessage());
        }
    }

    /**
     * 从API响应中提取真实任务ID
     */
    private String extractRealTaskId(Map<String, Object> apiResponse) {
        if (apiResponse == null || !apiResponse.containsKey("data")) {
            return null;
        }

        Object data = apiResponse.get("data");
        if (data instanceof Map) {
            Map<?, ?> dataMap = (Map<?, ?>) data;
            String taskNo = (String) dataMap.get("taskNo");
            if (taskNo != null) {
                return taskNo;
            }
            return (String) dataMap.get("taskId");
        } else if (data instanceof List) {
            List<?> dataList = (List<?>) data;
            if (!dataList.isEmpty()) {
                Object firstElement = dataList.get(0);
                if (firstElement instanceof Map) {
                    Map<?, ?> firstMap = (Map<?, ?>) firstElement;
                    String taskNo = (String) firstMap.get("taskNo");
                    if (taskNo != null) {
                        return taskNo;
                    }
                    return (String) firstMap.get("taskId");
                }
            }
        }
        return null;
    }

    /**
     * 检查队列中的任务状态 - 每2分钟轮询查询
     * 查询正在处理的任务，调用外部API获取最新状态
     */
    @Transactional
    public void checkTaskStatuses() {
        List<TaskQueue> tasksToCheck = taskQueueRepository.findTasksToCheck();
        
        logger.info("找到 {} 个需要检查状态的任务", tasksToCheck.size());
        
        if (tasksToCheck.isEmpty()) {
            logger.debug("当前没有需要检查状态的任务");
            return;
        }
        
        for (TaskQueue taskQueue : tasksToCheck) {
            try {
                logger.info("检查任务状态: taskId={}, realTaskId={}, status={}", 
                    taskQueue.getTaskId(), taskQueue.getRealTaskId(), taskQueue.getStatus());
                checkTaskStatusInternal(taskQueue);
            } catch (Exception e) {
                logger.error("检查任务状态失败: {}", taskQueue.getTaskId(), e);
                // 继续检查其他任务，不中断整个流程
            }
        }
        
        logger.info("任务状态检查完成，共检查 {} 个任务", tasksToCheck.size());
    }

    /**
     * 检查单个任务状态 - 公共方法
     * 供轮询查询服务调用
     */
    public void checkTaskStatus(TaskQueue taskQueue) {
        checkTaskStatusInternal(taskQueue);
    }

    /**
     * 检查单个任务状态 - 轮询查询外部API
     * 每2分钟调用一次，获取任务最新状态
     */
    private void checkTaskStatusInternal(TaskQueue taskQueue) {
        if (taskQueue.getRealTaskId() == null) {
            logger.warn("任务 {} 没有真实任务ID，跳过状态检查", taskQueue.getTaskId());
            return;
        }

        try {
            logger.info("轮询查询任务状态: taskId={}, realTaskId={}", 
                taskQueue.getTaskId(), taskQueue.getRealTaskId());
            
            // 查询外部API状态
            Map<String, Object> statusResponse = realAIService.getTaskStatus(taskQueue.getRealTaskId());
            
            // API调用成功后增加检查次数
            taskQueue.incrementCheckCount();
            taskQueueRepository.save(taskQueue);
            
            logger.info("外部API响应: {}", statusResponse);
            
            if (statusResponse != null && statusResponse.containsKey("data")) {
                Object data = statusResponse.get("data");
                Map<?, ?> taskData = null;
                
                // 处理不同的响应格式
                if (data instanceof Map) {
                    taskData = (Map<?, ?>) data;
                } else if (data instanceof List) {
                    List<?> dataList = (List<?>) data;
                    if (!dataList.isEmpty()) {
                        Object firstElement = dataList.get(0);
                        if (firstElement instanceof Map) {
                            taskData = (Map<?, ?>) firstElement;
                        }
                    }
                }
                
                if (taskData != null) {
                    String status = (String) taskData.get("status");
                    String resultUrl = (String) taskData.get("resultUrl");
                    String errorMessage = (String) taskData.get("errorMessage");

                    logger.info("任务状态更新: taskId={}, status={}, resultUrl={}, errorMessage={}", 
                        taskQueue.getTaskId(), status, resultUrl, errorMessage);

                    // 更新任务状态
                    if ("completed".equals(status) || "success".equals(status)) {
                        logger.info("任务完成: {}", taskQueue.getTaskId());
                        updateTaskAsCompleted(taskQueue, resultUrl);
                    } else if ("failed".equals(status) || "error".equals(status)) {
                        logger.warn("任务失败: {}, 错误: {}", taskQueue.getTaskId(), errorMessage);
                        updateTaskAsFailed(taskQueue, errorMessage);
                    } else {
                        logger.info("任务继续处理中: {}, 状态: {}", taskQueue.getTaskId(), status);
                    }
                } else {
                    logger.warn("无法解析任务数据: taskId={}", taskQueue.getTaskId());
                }
            } else {
                logger.warn("外部API响应格式异常: taskId={}, response={}", 
                    taskQueue.getTaskId(), statusResponse);
            }

            // 检查是否超时
            if (taskQueue.isTimeout()) {
                logger.warn("任务超时: {}", taskQueue.getTaskId());
                updateTaskAsTimeout(taskQueue);
            }

        } catch (Exception e) {
            logger.warn("查询任务状态异常: {}, 继续轮询", taskQueue.getTaskId(), e);
        }
    }

    /**
     * 更新任务为完成状态
     */
    private void updateTaskAsCompleted(TaskQueue taskQueue, String resultUrl) {
        try {
            taskQueue.updateStatus(TaskQueue.QueueStatus.COMPLETED);
            taskQueueRepository.save(taskQueue);

            // 扣除冻结的积分
            userService.deductFrozenPoints(taskQueue.getTaskId());

            // 更新原始任务状态
            updateOriginalTaskStatus(taskQueue, "COMPLETED", resultUrl, null);
            
            logger.info("任务 {} 已完成", taskQueue.getTaskId());
            
            // 创建用户作品 - 在最后执行，避免影响主要流程
            try {
                UserWork work = userWorkService.createWorkFromTask(taskQueue.getTaskId(), resultUrl);
                logger.info("创建用户作品成功: {}, 任务ID: {}", work.getId(), taskQueue.getTaskId());
            } catch (Exception workException) {
                logger.error("创建用户作品失败: {}, 但不影响任务完成状态", taskQueue.getTaskId(), workException);
                // 作品创建失败不影响任务完成状态
            }
            
        } catch (Exception e) {
            logger.error("更新任务完成状态失败: {}", taskQueue.getTaskId(), e);
            // 如果原始任务状态更新失败，至少保证队列状态正确
        }
    }

    /**
     * 更新任务为失败状态
     */
    private void updateTaskAsFailed(TaskQueue taskQueue, String errorMessage) {
        try {
            taskQueue.updateStatus(TaskQueue.QueueStatus.FAILED);
            taskQueue.setErrorMessage(errorMessage);
            taskQueueRepository.save(taskQueue);

            // 返还冻结的积分
            userService.returnFrozenPoints(taskQueue.getTaskId());

            // 更新原始任务状态
            updateOriginalTaskStatus(taskQueue, "FAILED", null, errorMessage);
            
            logger.error("任务 {} 失败: {}", taskQueue.getTaskId(), errorMessage);
        } catch (Exception e) {
            logger.error("更新任务失败状态失败: {}", taskQueue.getTaskId(), e);
            // 如果原始任务状态更新失败，至少保证队列状态正确
        }
    }

    /**
     * 更新任务为超时状态
     */
    private void updateTaskAsTimeout(TaskQueue taskQueue) {
        try {
            taskQueue.updateStatus(TaskQueue.QueueStatus.TIMEOUT);
            taskQueue.setErrorMessage("任务处理超时");
            taskQueueRepository.save(taskQueue);

            // 返还冻结的积分
            userService.returnFrozenPoints(taskQueue.getTaskId());

            // 更新原始任务状态
            updateOriginalTaskStatus(taskQueue, "FAILED", null, "任务处理超时");
            
            logger.error("任务 {} 超时", taskQueue.getTaskId());
        } catch (Exception e) {
            logger.error("更新任务超时状态失败: {}", taskQueue.getTaskId(), e);
            // 如果原始任务状态更新失败，至少保证队列状态正确
        }
    }

    /**
     * 更新原始任务状态
     */
    private void updateOriginalTaskStatus(TaskQueue taskQueue, String status, String resultUrl, String errorMessage) {
        try {
            if (taskQueue.getTaskType() == TaskQueue.TaskType.TEXT_TO_VIDEO) {
                Optional<TextToVideoTask> taskOpt = textToVideoTaskRepository.findByTaskId(taskQueue.getTaskId());
                if (taskOpt.isPresent()) {
                    TextToVideoTask task = taskOpt.get();
                    if ("COMPLETED".equals(status)) {
                        task.setResultUrl(resultUrl);
                        task.updateStatus(TextToVideoTask.TaskStatus.COMPLETED);
                        task.updateProgress(100);
                    } else if ("FAILED".equals(status) || "CANCELLED".equals(status)) {
                        task.updateStatus(TextToVideoTask.TaskStatus.FAILED);
                        task.setErrorMessage(errorMessage);
                    }
                    textToVideoTaskRepository.save(task);
                    logger.info("原始文生视频任务状态已更新: {} -> {}", taskQueue.getTaskId(), status);
                } else {
                    logger.warn("找不到原始文生视频任务: {}", taskQueue.getTaskId());
                }
            } else {
                Optional<ImageToVideoTask> taskOpt = imageToVideoTaskRepository.findByTaskId(taskQueue.getTaskId());
                if (taskOpt.isPresent()) {
                    ImageToVideoTask task = taskOpt.get();
                    if ("COMPLETED".equals(status)) {
                        task.setResultUrl(resultUrl);
                        task.updateStatus(ImageToVideoTask.TaskStatus.COMPLETED);
                        task.updateProgress(100);
                    } else if ("FAILED".equals(status) || "CANCELLED".equals(status)) {
                        task.updateStatus(ImageToVideoTask.TaskStatus.FAILED);
                        task.setErrorMessage(errorMessage);
                    }
                    imageToVideoTaskRepository.save(task);
                    logger.info("原始图生视频任务状态已更新: {} -> {}", taskQueue.getTaskId(), status);
                } else {
                    logger.warn("找不到原始图生视频任务: {}", taskQueue.getTaskId());
                }
            }
        } catch (Exception e) {
            logger.error("更新原始任务状态失败: {}", taskQueue.getTaskId(), e);
            // 重新抛出异常，让调用方知道状态更新失败
            throw new RuntimeException("更新原始任务状态失败: " + e.getMessage(), e);
        }
    }

    /**
     * 取消任务
     */
    @Transactional
    public boolean cancelTask(String taskId, String username) {
        Optional<TaskQueue> taskOpt = taskQueueRepository.findByUsernameAndTaskId(username, taskId);
        if (!taskOpt.isPresent()) {
            return false;
        }

        TaskQueue taskQueue = taskOpt.get();
        if (taskQueue.canProcess()) {
            taskQueue.updateStatus(TaskQueue.QueueStatus.CANCELLED);
            taskQueue.setErrorMessage("用户取消了任务");
            taskQueueRepository.save(taskQueue);

            // 返还冻结的积分
            userService.returnFrozenPoints(taskId);

            // 更新原始任务状态
            updateOriginalTaskStatus(taskQueue, "CANCELLED", null, "用户取消了任务");
            
            logger.info("任务 {} 已取消", taskId);
            return true;
        }
        
        return false;
    }

    /**
     * 获取用户的任务队列
     */
    @Transactional(readOnly = true)
    public List<TaskQueue> getUserTaskQueue(String username) {
        return taskQueueRepository.findPendingTasksByUsername(username);
    }

    /**
     * 获取用户任务队列统计
     */
    @Transactional(readOnly = true)
    public long getUserTaskCount(String username) {
        return taskQueueRepository.countByUsername(username);
    }

    /**
     * 清理过期任务
     */
    @Transactional
    public int cleanupExpiredTasks() {
        LocalDateTime expiredDate = LocalDateTime.now().minusDays(7);
        return taskQueueRepository.deleteExpiredTasks(expiredDate);
    }
}