package com.rj.scheduler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rj.config.AliyunConfig;
import com.rj.entity.VideoSynthesisLog;
import com.rj.mapper.VideoSynthesisLogMapper;
import com.rj.service.MinIOService;
import com.rj.utils.MinIOUrlGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 视频合成任务状态检查定时器
 * 每5分钟检查一次PENDING状态的任务，调用阿里云API查询任务状态并更新数据库
 * 
 * @author rj
 * @date 2025-01-30
 */
@Slf4j
@Component
public class VideoSynthesisStatusScheduler {

    @Autowired
    private VideoSynthesisLogMapper videoSynthesisLogMapper;

    @Autowired
    private AliyunConfig aliyunConfig;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private MinIOService minIOService;

    @Autowired
    MinIOUrlGenerator urlGenerator;

    /**
     * 每5分钟执行一次任务状态检查
     */
//    @Scheduled(fixedRate = 5 * 60 * 1000) // 5分钟 = 5 * 60 * 1000毫秒
    public void checkVideoSynthesisStatus() {
        try {
            log.info("开始执行视频合成任务状态检查...");
            
            // 查询所有PENDING或RUNNING状态的任务
            List<VideoSynthesisLog> pendingTasks = getPendingTasks();
            
            if (pendingTasks.isEmpty()) {
                log.info("没有找到PENDING或RUNNING状态的任务");
                return;
            }
            
            log.info("找到{}个PENDING或RUNNING状态的任务，开始检查状态", pendingTasks.size());
            
            // 遍历每个任务，检查状态
            for (VideoSynthesisLog task : pendingTasks) {
                try {
                    checkAndUpdateTaskStatus(task);
                } catch (Exception e) {
                    log.error("检查任务状态失败，任务ID: {}, 错误: {}", task.getTaskId(), e.getMessage(), e);
                }
            }
            
            log.info("视频合成任务状态检查完成");
            
        } catch (Exception e) {
            log.error("视频合成任务状态检查执行失败", e);
        }
    }

    /**
     * 查询所有PENDING或RUNNING状态的任务
     */
    private List<VideoSynthesisLog> getPendingTasks() {
        QueryWrapper<VideoSynthesisLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("task_status", "PENDING", "RUNNING");
        
        return videoSynthesisLogMapper.selectList(queryWrapper);
    }

    /**
     * 检查并更新单个任务状态
     */
    private void checkAndUpdateTaskStatus(VideoSynthesisLog task) {
        try {

            log.info("检查任务状态，任务ID: {}", task.getTaskId());
            if (task == null || task.getTaskId() == null || task.getTaskId().isEmpty()) return;
            // 调用阿里云API检查任务状态
            String apiUrl = "https://dashscope.aliyuncs.com/api/v1/tasks/" + task.getTaskId();
            
            HttpHeaders headers = new HttpHeaders();
            headers.set("Authorization", "Bearer " + aliyunConfig.getApiKey());
            headers.set("Content-Type", "application/json");
            
            HttpEntity<String> entity = new HttpEntity<>(headers);
            
            ResponseEntity<String> response = restTemplate.exchange(
                apiUrl, 
                HttpMethod.GET, 
                entity, 
                String.class
            );
            
            if (response.getStatusCode().is2xxSuccessful()) {
                String responseBody = response.getBody();
                log.info("API响应: {}", responseBody);
                
                // 解析响应并更新数据库
                updateTaskFromResponse(task, responseBody);
            } else {
                log.error("API调用失败，状态码: {}, 任务ID: {}", response.getStatusCode(), task.getTaskId());
            }
            
        } catch (Exception e) {
            log.error("检查任务状态异常，任务ID: {}, 错误: {}", task.getTaskId(), e.getMessage(), e);
        }
    }

    /**
     * 根据API响应更新任务状态
     */
    private void updateTaskFromResponse(VideoSynthesisLog task, String responseBody) {
        try {
            JSONObject responseJson = JSON.parseObject(responseBody);
            
            if (responseJson.containsKey("output")) {
                JSONObject output = responseJson.getJSONObject("output");
                
                // 更新任务状态
                String taskStatus = output.getString("task_status");
                task.setTaskStatus(taskStatus);
                task.setUpdatedAt(LocalDateTime.now());
                
                // 如果任务成功完成，处理视频文件
                if ("SUCCEEDED".equals(taskStatus)) {
                    JSONObject results = output.getJSONObject("results");
                    if (output != null && output.containsKey("video_url")) {
                        String originalVideoUrl = output.getString("video_url");
                        log.info("任务成功完成，原始视频URL: {}", originalVideoUrl);
                        
                        // 从阿里云OSS下载视频并上传到MinIO
                        String minioVideoUrl = downloadAndUploadToMinIO(originalVideoUrl, task);
                        if (minioVideoUrl != null) {
                            task.setVideoUrl(minioVideoUrl);
                            log.info("视频已成功转存到MinIO: {}", minioVideoUrl);
                        } else {
                            // 如果转存失败，保留原始URL
                            task.setVideoUrl(originalVideoUrl);
                            log.warn("视频转存到MinIO失败，保留原始URL: {}", originalVideoUrl);
                        }
                        log.info("任务成功完成，视频URL: {}", task.getVideoUrl());
                        log.info("任务成功完成，临时访问URL: {}", task.getVideoTempUrl());
                        log.info("任务成功完成，视频模板URL: {}", task.getVideoTemplateUrl());

                        task.setSuccess(true);
                        task.setResponseTime(LocalDateTime.now());
                        
                        // 更新临时访问URL（使用MinIO的预签名URL）
                        log.info("临时访问URL: {}", task.getVideoTempUrl());

                    }else if (results != null && results.containsKey("video_url")) {
                        String videoUrl = results.getString("video_url");
                        task.setVideoUrl(videoUrl);
                        log.info("任务成功完成，视频URL: {}", videoUrl);

                        // 从阿里云OSS下载视频并上传到MinIO
                         downloadAndUploadToMinIO(videoUrl, task);
                        log.info("任务成功完成，视频URL: {}", task.getVideoUrl());
                        log.info("任务成功完成，临时访问URL: {}", task.getVideoTempUrl());
                        log.info("任务成功完成，视频模板URL: {}", task.getVideoTemplateUrl());
                    }

                } else if ("FAILED".equals(taskStatus)) {
//                    task.setSuccess(false);
                    String message = output.getString("message");
                    task.setErrorMessage(message);
                    task.setResponseTime(LocalDateTime.now());
                }
                
                // 更新usage信息
                if (responseJson.containsKey("usage")) {
                    JSONObject usage = responseJson.getJSONObject("usage");
                    if (usage.containsKey("video_duration")) {
                        task.setVideoDuration(usage.getBigDecimal("video_duration"));
                    }
                    if (usage.containsKey("video_ratio")) {
                        task.setVideoRatio(usage.getString("video_ratio"));
                    }
                }
                
                // 解析图像区域坐标
                if (output.containsKey("face_bbox")) {
                    String faceBbox = output.getString("face_bbox");
                    if (faceBbox != null && !faceBbox.trim().isEmpty()) {
                        task.setFaceBbox(faceBbox);
                        log.info("更新图像区域坐标: {}", faceBbox);
                    }
                }
                
                // 解析动态区域坐标
                if (output.containsKey("ext_bbox")) {
                    String extBbox = output.getString("ext_bbox");
                    if (extBbox != null && !extBbox.trim().isEmpty()) {
                        task.setExtBbox(extBbox);
                        log.info("更新动态区域坐标: {}", extBbox);
                    }
                }
                
                // 保存到数据库
                int updateResult = videoSynthesisLogMapper.updateById(task);
                if (updateResult > 0) {
                    log.info("任务状态更新成功，任务ID: {}, 新状态: {}", task.getTaskId(), taskStatus);
                } else {
                    log.error("任务状态更新失败，任务ID: {}", task.getTaskId());
                }
                
            } else {
                log.error("API响应格式异常，任务ID: {}, 响应: {}", task.getTaskId(), responseBody);
            }
            
        } catch (Exception e) {
            log.error("解析API响应失败，任务ID: {}, 响应: {}, 错误: {}", task.getTaskId(), responseBody, e.getMessage(), e);
        }
    }


    /**
     * 从阿里云OSS下载视频并上传到MinIO
     * 
     * @param ossVideoUrl 阿里云OSS视频URL
     * @return MinIO中的视频URL，失败时返回null
     */
    private String downloadAndUploadToMinIO(String ossVideoUrl, VideoSynthesisLog videoSynthesisLog) {
        try {
            log.info("开始从阿里云OSS下载视频: {}", ossVideoUrl);
            
            // 从阿里云OSS下载视频
            byte[] videoData = downloadVideoFromOSS(ossVideoUrl);
            if (videoData == null || videoData.length == 0) {
                log.error("从阿里云OSS下载视频失败，数据为空");
                return null;
            }
            
            log.info("视频下载成功，大小: {} bytes", videoData.length);
            
            // 生成MinIO文件名
            String fileName = "video_synthesis/" + videoSynthesisLog.getVideoName()+videoSynthesisLog.getTaskId() + ".mp4";

            // 上传到MinIO
            String minioUrl = minIOService.uploadFile(
                new ByteArrayInputStream(videoData), 
                fileName, 
                "video/mp4"
            );
            String tempUrl = urlGenerator.generateTempUrl(fileName,7, TimeUnit.DAYS).getUrl();
            videoSynthesisLog.setVideoTempUrl(tempUrl);
            videoSynthesisLog.setVideoUrl(minioUrl);
            log.info("视频已成功上传到MinIO: {}", minioUrl);

            return minioUrl;
            
        } catch (Exception e) {
            log.error("下载并上传视频到MinIO失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 从阿里云OSS下载视频文件
     * 
     * @param videoUrl 视频URL
     * @return 视频字节数组
     */
    private byte[] downloadVideoFromOSS(String videoUrl) {
        try {
            log.info("开始下载视频: {}", videoUrl);
            
            // 方法1: 使用HttpURLConnection下载视频，避免RestTemplate的URL编码问题
            byte[] videoData = downloadWithHttpURLConnection(videoUrl);
            if (videoData != null) {
                return videoData;
            }
            
            // 方法2: 如果HttpURLConnection失败，尝试使用RestTemplate但禁用URL编码
            log.warn("HttpURLConnection下载失败，尝试使用RestTemplate备用方案");
            return downloadWithRestTemplate(videoUrl);
            
        } catch (Exception e) {
            log.error("下载视频异常: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 使用HttpURLConnection下载视频
     */
    private byte[] downloadWithHttpURLConnection(String videoUrl) {
        try {
            URL url = new URL(videoUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            
            // 设置请求头
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(30000); // 30秒连接超时
            connection.setReadTimeout(300000);   // 5分钟读取超时
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
            connection.setRequestProperty("Accept", "*/*");
            connection.setRequestProperty("Accept-Encoding", "identity"); // 禁用压缩
            
            int responseCode = connection.getResponseCode();
            if (responseCode == 200) {
                try (InputStream inputStream = connection.getInputStream();
                     ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                    
                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                    
                    byte[] videoData = outputStream.toByteArray();
                    log.info("HttpURLConnection视频下载成功，大小: {} bytes", videoData.length);
                    return videoData;
                }
            } else {
                log.error("HttpURLConnection下载失败，HTTP状态码: {}", responseCode);
                // 读取错误信息
                try (InputStream errorStream = connection.getErrorStream()) {
                    if (errorStream != null) {
                        byte[] errorBytes = new byte[1024];
                        int errorBytesRead = errorStream.read(errorBytes);
                        if (errorBytesRead > 0) {
                            String errorMessage = new String(errorBytes, 0, errorBytesRead);
                            log.error("错误响应内容: {}", errorMessage);
                        }
                    }
                }
                return null;
            }
            
        } catch (Exception e) {
            log.error("HttpURLConnection下载异常: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 使用RestTemplate下载视频（备用方案）
     */
    private byte[] downloadWithRestTemplate(String videoUrl) {
        try {
            // 创建自定义的RestTemplate，禁用URL编码
            RestTemplate customRestTemplate = new RestTemplate();
            
            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
            headers.set("Accept", "*/*");
            headers.set("Accept-Encoding", "identity");
            
            HttpEntity<String> entity = new HttpEntity<>(headers);
            
            ResponseEntity<byte[]> response = customRestTemplate.exchange(
                videoUrl, 
                HttpMethod.GET, 
                entity, 
                byte[].class
            );
            
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                log.info("RestTemplate视频下载成功，大小: {} bytes", response.getBody().length);
                return response.getBody();
            } else {
                log.error("RestTemplate下载失败，状态码: {}", response.getStatusCode());
                return null;
            }
            
        } catch (Exception e) {
            log.error("RestTemplate下载异常: {}", e.getMessage(), e);
            return null;
        }
    }



}
