package com.example.demo.service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

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.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.example.demo.model.ImageToVideoTask;
import com.example.demo.repository.ImageToVideoTaskRepository;

/**
 * 图生视频服务类
 */
@Service
@Transactional
public class ImageToVideoService {

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

    @Autowired
    private ImageToVideoTaskRepository taskRepository;

    @Autowired
    private RealAIService realAIService;

    @Autowired
    private TaskQueueService taskQueueService;

    @Value("${app.upload.path:/uploads}")
    private String uploadPath;

    @Value("${app.video.output.path:/outputs}")
    private String outputPath;

    /**
     * 创建图生视频任务
     */
    public ImageToVideoTask createTask(String username, MultipartFile firstFrame, 
                                     MultipartFile lastFrame, String prompt, 
                                     String aspectRatio, int duration, boolean hdMode) {
        
        try {
            // 生成任务ID
            String taskId = generateTaskId();
            
            // 保存首帧图片
            String firstFrameUrl = saveImage(firstFrame, taskId, "first_frame");
            
            // 保存尾帧图片（如果提供）
            String lastFrameUrl = null;
            if (lastFrame != null && !lastFrame.isEmpty()) {
                lastFrameUrl = saveImage(lastFrame, taskId, "last_frame");
            }
            
            // 创建任务记录
            ImageToVideoTask task = new ImageToVideoTask(
                taskId, username, firstFrameUrl, prompt, aspectRatio, duration, hdMode
            );
            
            if (lastFrameUrl != null) {
                task.setLastFrameUrl(lastFrameUrl);
            }
            
            // 保存到数据库
            task = taskRepository.save(task);
            
            // 添加任务到队列
            taskQueueService.addImageToVideoTask(username, taskId);
            
            logger.info("创建图生视频任务成功: taskId={}, username={}", taskId, username);
            return task;
            
        } catch (Exception e) {
            logger.error("创建图生视频任务失败", e);
            throw new RuntimeException("创建任务失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户任务列表
     */
    @Transactional(readOnly = true)
    public List<ImageToVideoTask> getUserTasks(String username, int page, int size) {
        // 验证参数
        if (username == null || username.trim().isEmpty()) {
            throw new IllegalArgumentException("用户名不能为空");
        }
        if (page < 0) {
            page = 0;
        }
        if (size <= 0 || size > 100) {
            size = 10; // 默认每页10条，最大100条
        }
        
        Pageable pageable = PageRequest.of(page, size);
        Page<ImageToVideoTask> taskPage = taskRepository.findByUsernameOrderByCreatedAtDesc(username, pageable);
        return taskPage.getContent();
    }

    /**
     * 获取用户任务总数
     */
    @Transactional(readOnly = true)
    public long getUserTaskCount(String username) {
        if (username == null || username.trim().isEmpty()) {
            return 0;
        }
        return taskRepository.countByUsername(username);
    }

    /**
     * 根据任务ID获取任务
     */
    @Transactional(readOnly = true)
    public ImageToVideoTask getTaskById(String taskId) {
        if (taskId == null || taskId.trim().isEmpty()) {
            return null;
        }
        return taskRepository.findByTaskId(taskId).orElse(null);
    }

    /**
     * 取消任务
     */
    @Transactional
    public boolean cancelTask(String taskId, String username) {
        // 使用悲观锁避免并发问题
        ImageToVideoTask task = taskRepository.findByTaskId(taskId).orElse(null);
        if (task == null || task.getUsername() == null || !task.getUsername().equals(username)) {
            return false;
        }
        
        // 检查任务状态，只有PENDING和PROCESSING状态的任务才能取消
        if (task.getStatus() == ImageToVideoTask.TaskStatus.PENDING || 
            task.getStatus() == ImageToVideoTask.TaskStatus.PROCESSING) {
            
            task.updateStatus(ImageToVideoTask.TaskStatus.CANCELLED);
            task.setErrorMessage("用户取消了任务");
            taskRepository.save(task);
            
            logger.info("图生视频任务已取消: taskId={}, username={}", taskId, username);
            return true;
        }
        
        return false;
    }

    /**
     * 使用真实API处理任务
     */
    @Async
    public CompletableFuture<Void> processTaskWithRealAPI(ImageToVideoTask task, MultipartFile firstFrame) {
        try {
            logger.info("开始使用真实API处理图生视频任务: {}", task.getTaskId());
            
            // 更新任务状态为处理中
            task.updateStatus(ImageToVideoTask.TaskStatus.PROCESSING);
            taskRepository.save(task);

            // 将图片转换为Base64
            String imageBase64 = realAIService.convertImageToBase64(
                firstFrame.getBytes(), 
                firstFrame.getContentType()
            );

            // 调用真实API提交任务
            Map<String, Object> apiResponse = realAIService.submitImageToVideoTask(
                task.getPrompt(),
                imageBase64,
                task.getAspectRatio(),
                task.getDuration().toString(),
                task.getHdMode()
            );

            // 从API响应中提取真实任务ID
            // 注意：根据真实API响应，任务ID可能在不同的位置
            // 这里先记录API响应，后续根据实际响应调整
            logger.info("API响应数据: {}", apiResponse);
            
            // 尝试从不同位置提取任务ID
            String realTaskId = null;
            if (apiResponse.containsKey("data")) {
                Object data = apiResponse.get("data");
                if (data instanceof Map) {
                    // 如果data是Map，尝试获取taskNo（API返回的字段名）
                    realTaskId = (String) ((Map<?, ?>) data).get("taskNo");
                    if (realTaskId == null) {
                        // 如果没有taskNo，尝试taskId（兼容性）
                        realTaskId = (String) ((Map<?, ?>) data).get("taskId");
                    }
                } else if (data instanceof List) {
                    // 如果data是List，检查第一个元素
                    List<?> dataList = (List<?>) data;
                    if (!dataList.isEmpty()) {
                        Object firstElement = dataList.get(0);
                        if (firstElement instanceof Map) {
                            Map<?, ?> firstMap = (Map<?, ?>) firstElement;
                            realTaskId = (String) firstMap.get("taskNo");
                            if (realTaskId == null) {
                                realTaskId = (String) firstMap.get("taskId");
                            }
                        }
                    }
                }
            }
            
            // 如果找到了真实任务ID，保存到数据库
            if (realTaskId != null) {
                task.setRealTaskId(realTaskId);
                taskRepository.save(task);
                logger.info("真实任务ID已保存: {} -> {}", task.getTaskId(), realTaskId);
            } else {
                // 如果没有找到任务ID，说明任务提交失败
                logger.error("任务提交失败：未从API响应中获取到任务ID");
                task.updateStatus(ImageToVideoTask.TaskStatus.FAILED);
                task.setErrorMessage("任务提交失败：API未返回有效的任务ID");
                taskRepository.save(task);
                return CompletableFuture.completedFuture(null); // 直接返回，不进行轮询
            }

            // 开始轮询真实任务状态
            pollRealTaskStatus(task);
            
        } catch (Exception e) {
            logger.error("使用真实API处理图生视频任务失败: {}", task.getTaskId(), e);
            logger.error("异常详情: {}", e.getClass().getSimpleName() + ": " + e.getMessage());
            if (e.getCause() != null) {
                logger.error("异常原因: {}", e.getCause().getMessage());
            }
            
            try {
                // 更新状态为失败
                task.updateStatus(ImageToVideoTask.TaskStatus.FAILED);
                task.setErrorMessage(e.getMessage());
                taskRepository.save(task);
            } catch (Exception saveException) {
                logger.error("保存失败状态时出错: {}", task.getTaskId(), saveException);
            }
        }
        
        return CompletableFuture.completedFuture(null);
    }

    /**
     * 轮询真实任务状态
     */
    private void pollRealTaskStatus(ImageToVideoTask task) {
        try {
            String realTaskId = task.getRealTaskId();
            if (realTaskId == null) {
                logger.error("真实任务ID为空，无法轮询状态: {}", task.getTaskId());
                return;
            }

            // 轮询任务状态
            int maxAttempts = 450; // 最大轮询次数（15分钟）
            int attempt = 0;
            
            while (attempt < maxAttempts) {
                // 检查任务是否已被取消
                ImageToVideoTask currentTask = taskRepository.findByTaskId(task.getTaskId()).orElse(null);
                if (currentTask != null && currentTask.getStatus() == ImageToVideoTask.TaskStatus.CANCELLED) {
                    logger.info("任务 {} 已被取消，停止轮询", task.getTaskId());
                    return;
                }
                
                // 使用最新的任务状态
                if (currentTask != null) {
                    task = currentTask;
                }

                try {
                    // 查询真实任务状态
                    Map<String, Object> statusResponse = realAIService.getTaskStatus(realTaskId);
                    logger.info("任务状态查询响应: {}", 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() && dataList.get(0) instanceof Map) {
                                taskData = (Map<?, ?>) dataList.get(0);
                            }
                        }
                        
                        if (taskData != null) {
                            String status = (String) taskData.get("status");
                            Integer progress = (Integer) taskData.get("progress");
                            String resultUrl = (String) taskData.get("resultUrl");
                            String errorMessage = (String) taskData.get("errorMessage");

                            // 更新任务状态
                            if ("completed".equals(status) || "success".equals(status)) {
                                task.setResultUrl(resultUrl);
                                task.updateStatus(ImageToVideoTask.TaskStatus.COMPLETED);
                                task.updateProgress(100);
                                taskRepository.save(task);
                                logger.info("图生视频任务完成: {}", task.getTaskId());
                                return;
                            } else if ("failed".equals(status) || "error".equals(status)) {
                                task.updateStatus(ImageToVideoTask.TaskStatus.FAILED);
                                task.setErrorMessage(errorMessage);
                                taskRepository.save(task);
                                logger.error("图生视频任务失败: {}", task.getTaskId());
                                return;
                            } else if ("processing".equals(status) || "pending".equals(status) || "running".equals(status)) {
                                // 更新进度
                                if (progress != null) {
                                    task.updateProgress(progress);
                                } else {
                                    // 根据轮询次数估算进度
                                    int estimatedProgress = Math.min(90, (attempt * 100) / maxAttempts);
                                    task.updateProgress(estimatedProgress);
                                }
                                taskRepository.save(task);
                            }
                        }
                    }
                    
                } catch (Exception e) {
                    logger.warn("查询任务状态失败，继续轮询: {}", e.getMessage());
                    logger.warn("异常详情: {}", e.getClass().getSimpleName() + ": " + e.getMessage());
                }

                attempt++;
                Thread.sleep(2000); // 每2秒轮询一次
            }
            
            // 超时处理
            task.updateStatus(ImageToVideoTask.TaskStatus.FAILED);
            task.setErrorMessage("任务处理超时");
            taskRepository.save(task);
            logger.error("图生视频任务超时: {}", task.getTaskId());
            
        } catch (InterruptedException e) {
            logger.error("轮询任务状态被中断: {}", task.getTaskId(), e);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            logger.error("轮询任务状态异常: {}", task.getTaskId(), e);
            logger.error("异常详情: {}", e.getClass().getSimpleName() + ": " + e.getMessage());
            if (e.getCause() != null) {
                logger.error("异常原因: {}", e.getCause().getMessage());
            }
        }
    }

    /**
     * 处理视频生成过程
     */
    private void simulateVideoGeneration(ImageToVideoTask task) throws InterruptedException {
        // 处理时间
        int totalSteps = 10;
        for (int i = 1; i <= totalSteps; i++) {
            // 检查任务是否已被取消
            ImageToVideoTask currentTask = taskRepository.findByTaskId(task.getTaskId()).orElse(null);
            if (currentTask != null && currentTask.getStatus() == ImageToVideoTask.TaskStatus.CANCELLED) {
                logger.info("任务 {} 已被取消，停止处理", task.getTaskId());
                return;
            }
            
            Thread.sleep(2000); // 处理时间
            
            // 更新进度
            int progress = (i * 100) / totalSteps;
            task.updateProgress(progress);
            taskRepository.save(task);
            
            logger.debug("任务 {} 进度: {}%", task.getTaskId(), progress);
        }
    }

    /**
     * 保存图片文件
     */
    private String saveImage(MultipartFile file, String taskId, String type) throws IOException {
        // 确保上传目录存在
        Path uploadDir = Paths.get(uploadPath);
        if (!Files.exists(uploadDir)) {
            Files.createDirectories(uploadDir);
        }
        
        // 创建任务目录
        Path taskDir = uploadDir.resolve(taskId);
        Files.createDirectories(taskDir);
        
        // 生成文件名
        String originalFilename = file.getOriginalFilename();
        String extension = getFileExtension(originalFilename);
        String filename = type + "_" + System.currentTimeMillis() + extension;
        
        // 保存文件
        Path filePath = taskDir.resolve(filename);
        Files.copy(file.getInputStream(), filePath);
        
        // 返回相对路径，确保路径格式正确
        return uploadPath + "/" + taskId + "/" + filename;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || filename.isEmpty()) {
            return ".jpg";
        }
        
        int lastDotIndex = filename.lastIndexOf('.');
        if (lastDotIndex > 0) {
            return filename.substring(lastDotIndex);
        }
        
        return ".jpg";
    }

    /**
     * 生成任务ID
     */
    private String generateTaskId() {
        return "img2vid_" + UUID.randomUUID().toString().replace("-", "").substring(0, 16);
    }

    /**
     * 生成结果URL
     */
    private String generateResultUrl(String taskId) {
        return outputPath + "/" + taskId + "/video_" + System.currentTimeMillis() + ".mp4";
    }

    /**
     * 获取待处理任务列表
     */
    public List<ImageToVideoTask> getPendingTasks() {
        return taskRepository.findPendingTasks();
    }

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