package com.rj.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rj.entity.DetectVideoTemplate;
import com.rj.mapper.DetectVideoTemplateMapper;
import com.rj.service.IDetectVideoTemplateService;
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.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 检测视频模板日志服务实现
 */
@Slf4j
@Service
public class DetectVideoTemplateServiceImpl extends ServiceImpl<DetectVideoTemplateMapper, DetectVideoTemplate> implements IDetectVideoTemplateService {

    private static final String API_URL = "https://dashscope.aliyuncs.com/api/v1/services/aigc/image2video/aa-template-generation";

    @Value("${dashscope.api.key:}")
    private String apiKey;
    
    @Autowired
    private MinIOService minioService;
    
    @Autowired
    private MinIOUrlGenerator urlGenerator;
    
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;
    
    public DetectVideoTemplateServiceImpl() {
        this.restTemplate = new RestTemplate();
        this.objectMapper = new ObjectMapper();
    }

    @Override
    public boolean saveDetectVideoTemplateLog(DetectVideoTemplate detectVideoTemplate) {
        try {
            return save(detectVideoTemplate);
        } catch (Exception e) {
            log.error("保存检测视频模板日志失败: {}", e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 执行视频模板检测并保存日志
     */
    public DetectVideoTemplate detectVideoTemplateAndSave(String videoUrl, String ownerName, String ownerPhone, String templateName, String model) {

        if (apiKey == null || apiKey.trim().isEmpty()) {
            log.error("DASHSCOPE_API_KEY未配置");
            return createErrorLog(videoUrl, "DASHSCOPE_API_KEY未配置", ownerName, ownerPhone, templateName);
        }
        
        // 创建日志记录
        DetectVideoTemplate detectVideoTemplate = new DetectVideoTemplate();
        String requestId = UUID.randomUUID().toString();
        LocalDateTime requestTime = LocalDateTime.now();
        
        detectVideoTemplate.setRequestId(requestId);
        // 设置模型名称，如果未提供则使用默认值
        String modelName = (model != null && !model.trim().isEmpty()) ? model : "animate-anyone-template-gen2";
        detectVideoTemplate.setModel(modelName);
        log.info("使用模型: {}", modelName);
        detectVideoTemplate.setVideoUrl(videoUrl);
        detectVideoTemplate.setOwnerName(ownerName);
        detectVideoTemplate.setOwnerPhone(ownerPhone);
        detectVideoTemplate.setTemplateName(templateName);
        detectVideoTemplate.setRequestTime(requestTime);
        
        long startTime = System.currentTimeMillis();
        
        try {
            // 创建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("model", modelName);

            Map<String, String> input = new HashMap<>();
            input.put("video_url", videoUrl);
            requestBody.put("input", input);
            
            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setBearerAuth(apiKey);
            // 添加异步调用请求头
            headers.set("X-DashScope-Async", "enable");
            log.info("发送视频模板检测请求，requestBody : {}, 请求参数headers: {}", requestBody , headers);
            
            // 创建请求实体
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

            // 发送请求
            ResponseEntity<String> response = restTemplate.postForEntity(API_URL, requestEntity, String.class);



            log.info("发送视频模板检测请求，response: {}, 视频URL: {}", response, videoUrl);

            // 计算处理时间
            long endTime = System.currentTimeMillis();
            long processingTime = endTime - startTime;
            
            // 更新日志记录
            detectVideoTemplate.setResponseTime(LocalDateTime.now());
            detectVideoTemplate.setStatusCode(response.getStatusCode().value());
            detectVideoTemplate.setProcessingTimeMs(processingTime);
            detectVideoTemplate.setResponseData(response.getBody());
            
            // 处理响应
            log.info("视频模板检测响应，状态码: {}, 处理时间: {}ms", response.getStatusCode(), processingTime);
            
            // 解析JSON响应
            if (response.getStatusCode() == HttpStatus.OK) {
                JsonNode jsonResponse = objectMapper.readTree(response.getBody());
                
                // 解析响应数据
                if (jsonResponse.has("output")) {
                    JsonNode output = jsonResponse.get("output");
                    
                    // 解析任务ID
                    if (output.has("task_id")) {
                        String taskId = output.get("task_id").asText();
                        detectVideoTemplate.setTaskId(taskId);
                        log.info("任务ID: {}", taskId);
                    }
                    
                    // 解析任务状态
                    if (output.has("task_status")) {
                        String taskStatus = output.get("task_status").asText();
                        detectVideoTemplate.setTaskStatus(taskStatus);
                        log.info("任务状态: {}", taskStatus);
                        
                        // 根据任务状态判断是否成功
                        boolean isSuccess = "SUCCESS".equalsIgnoreCase(taskStatus) || "COMPLETED".equalsIgnoreCase(taskStatus);
                        detectVideoTemplate.setSuccess(isSuccess);
                    }

                }
                // 记录message信息
                if (jsonResponse.has("request_id")) {
                    String request_id = jsonResponse.get("request_id").asText();
                    detectVideoTemplate.setRequestId(request_id);
                }

            } else {
                // HTTP状态码不是200，直接标记为失败
                detectVideoTemplate.setSuccess(false);
            }
            
            // 保存到数据库
            boolean saved = saveDetectVideoTemplateLog(detectVideoTemplate);
            if (saved) {
                log.info("视频模板检测日志已保存，请求ID: {}", requestId);
            } else {
                log.error("保存视频模板检测日志失败，请求ID: {}", requestId);
            }
            
            return detectVideoTemplate;
            
        } catch (HttpClientErrorException e) {
            return handleError(detectVideoTemplate, e, "客户端错误 (4xx): " + e.getStatusCode(), startTime);
        } catch (HttpServerErrorException e) {
            return handleError(detectVideoTemplate, e, "服务器错误 (5xx): " + e.getStatusCode(), startTime);
        } catch (Exception e) {
            return handleError(detectVideoTemplate, e, "视频模板检测请求失败: " + e.getMessage(), startTime);
        }
    }
    
    /**
     * 处理错误并保存到数据库
     */
    private DetectVideoTemplate handleError(DetectVideoTemplate detectVideoTemplate, Exception e, String errorMessage, long startTime) {
        long endTime = System.currentTimeMillis();
        long processingTime = endTime - startTime;
        
        detectVideoTemplate.setResponseTime(LocalDateTime.now());
        detectVideoTemplate.setSuccess(false);
        detectVideoTemplate.setProcessingTimeMs(processingTime);
        detectVideoTemplate.setErrorMessage(errorMessage);
        
        if (e instanceof HttpClientErrorException) {
            detectVideoTemplate.setStatusCode(((HttpClientErrorException) e).getStatusCode().value());
            detectVideoTemplate.setResponseData(((HttpClientErrorException) e).getResponseBodyAsString());
        } else if (e instanceof HttpServerErrorException) {
            detectVideoTemplate.setStatusCode(((HttpServerErrorException) e).getStatusCode().value());
            detectVideoTemplate.setResponseData(((HttpServerErrorException) e).getResponseBodyAsString());
        }
        
        log.error("视频模板检测失败: {}", errorMessage);
        log.error("错误详情: {}", e.getMessage());
        
        // 保存错误日志到数据库
        try {
            saveDetectVideoTemplateLog(detectVideoTemplate);
            log.info("错误日志已保存，请求ID: {}", detectVideoTemplate.getRequestId());
        } catch (Exception saveException) {
            log.error("保存错误日志失败: {}", saveException.getMessage());
        }
        
        return detectVideoTemplate;
    }
    
    /**
     * 创建错误日志
     */
    private DetectVideoTemplate createErrorLog(String videoUrl, String errorMessage, String ownerName, String ownerPhone, String templateName) {
        DetectVideoTemplate detectVideoTemplate = new DetectVideoTemplate();
        detectVideoTemplate.setRequestId(UUID.randomUUID().toString());
        detectVideoTemplate.setModel("video-template-detect");
        detectVideoTemplate.setVideoUrl(videoUrl);
        detectVideoTemplate.setOwnerName(ownerName);
        detectVideoTemplate.setOwnerPhone(ownerPhone);
        detectVideoTemplate.setTemplateName(templateName);
        detectVideoTemplate.setRequestTime(LocalDateTime.now());
        detectVideoTemplate.setResponseTime(LocalDateTime.now());
        detectVideoTemplate.setSuccess(false);
        detectVideoTemplate.setErrorMessage(errorMessage);
        
        try {
            saveDetectVideoTemplateLog(detectVideoTemplate);
        } catch (Exception e) {
            log.error("保存错误日志失败: {}", e.getMessage());
        }
        
        return detectVideoTemplate;
    }
    
    /**
     * 分页查询检测视频模板日志
     */
    @Override
    public com.baomidou.mybatisplus.extension.plugins.pagination.Page<DetectVideoTemplate> getPageList(
            Integer current, Integer size, Boolean success, String startTime, String endTime, 
            String ownerName, String ownerPhone, String templateName) {
        
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<DetectVideoTemplate> page = 
            new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(current, size);
        
        com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<DetectVideoTemplate> queryWrapper = 
            new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
        
        // 添加查询条件
        if (success != null) {
            queryWrapper.eq(DetectVideoTemplate::getSuccess, success);
        }
        if (startTime != null && !startTime.trim().isEmpty()) {
            queryWrapper.ge(DetectVideoTemplate::getRequestTime, startTime);
        }
        if (endTime != null && !endTime.trim().isEmpty()) {
            queryWrapper.le(DetectVideoTemplate::getRequestTime, endTime);
        }
        if (ownerName != null && !ownerName.trim().isEmpty()) {
            queryWrapper.like(DetectVideoTemplate::getOwnerName, ownerName);
        }
        if (ownerPhone != null && !ownerPhone.trim().isEmpty()) {
            queryWrapper.like(DetectVideoTemplate::getOwnerPhone, ownerPhone);
        }
        if (templateName != null && !templateName.trim().isEmpty()) {
            queryWrapper.like(DetectVideoTemplate::getTemplateName, templateName);
        }
        
        // 按请求时间倒序排列
        queryWrapper.orderByDesc(DetectVideoTemplate::getRequestTime);
        
        return page(page, queryWrapper);
    }
    
    /**
     * 获取统计信息
     */
    @Override
    public Map<String, Object> getStatistics(String startTime, String endTime) {
        Map<String, Object> statistics = new HashMap<>();
        
        // 构建查询条件
        com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<DetectVideoTemplate> queryWrapper = 
            new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
        
        // 时间范围筛选
        if (startTime != null && !startTime.trim().isEmpty()) {
            queryWrapper.ge(DetectVideoTemplate::getRequestTime, startTime);
        }
        if (endTime != null && !endTime.trim().isEmpty()) {
            queryWrapper.le(DetectVideoTemplate::getRequestTime, endTime);
        }
        
        // 查询总数
        long totalCount = count(queryWrapper);
        
        // 查询成功数
        com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<DetectVideoTemplate> successWrapper = 
            new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
        
        // 时间范围筛选
        if (startTime != null && !startTime.trim().isEmpty()) {
            successWrapper.ge(DetectVideoTemplate::getRequestTime, startTime);
        }
        if (endTime != null && !endTime.trim().isEmpty()) {
            successWrapper.le(DetectVideoTemplate::getRequestTime, endTime);
        }
        successWrapper.eq(DetectVideoTemplate::getSuccess, true);
        long successCount = count(successWrapper);
        
        // 查询失败数
        long failureCount = totalCount - successCount;
        
        // 计算成功率
        double successRate = totalCount > 0 ? (double) successCount / totalCount * 100 : 0;
        
        // 查询平均处理时间
        java.util.List<DetectVideoTemplate> logs = list(queryWrapper);
        double avgProcessingTime = logs.stream()
            .filter(log -> log.getProcessingTimeMs() != null)
            .mapToLong(DetectVideoTemplate::getProcessingTimeMs)
            .average()
            .orElse(0.0);
        
        // 构建统计结果
        statistics.put("totalCount", totalCount);
        statistics.put("successCount", successCount);
        statistics.put("failureCount", failureCount);
        statistics.put("successRate", Math.round(successRate * 100.0) / 100.0);
        statistics.put("avgProcessingTimeMs", Math.round(avgProcessingTime));
        
        log.info("统计信息查询完成，总数: {}, 成功数: {}, 失败数: {}, 成功率: {}%", 
            totalCount, successCount, failureCount, successRate);
        
        return statistics;
    }
    
    /**
     * 上传视频模板文件并进行检测
     */
    @Override
    public DetectVideoTemplate uploadAndDetectVideoTemplate(MultipartFile file, String userId, String ownerName, 
                                                          String ownerPhone, String templateName, String model, int expiresInSeconds) {
        try {
            log.info("开始处理视频模板上传，文件名: {}, 大小: {} bytes, 用户ID: {}", 
                    file.getOriginalFilename(), file.getSize(), userId);
            
            // 1. 验证文件
            if (file.isEmpty()) {
                return createErrorLog("", "文件不能为空", ownerName, ownerPhone, templateName);
            }
            
            // 验证文件类型
            String contentType = file.getContentType();
            if (contentType == null || (!contentType.startsWith("video/"))) {
                return createErrorLog("", "只支持视频文件格式", ownerName, ownerPhone, templateName);
            }
            
            // 验证文件大小（限制为100MB）
            if (file.getSize() > 100 * 1024 * 1024) {
                return createErrorLog("", "文件大小不能超过100MB", ownerName, ownerPhone, templateName);
            }
            
            // 2. 上传文件到MinIO
            log.info("开始上传视频文件到MinIO...");
            String fileUrl = minioService.uploadFile(file);
            log.info("视频文件上传成功，URL: {}", fileUrl);
            
            // 3. 生成短链接（临时访问URL）
            log.info("开始生成短链接，有效期: {}秒", expiresInSeconds);
            String fileName = extractFileNameFromUrl(fileUrl);
            MinIOUrlGenerator.UrlInfo urlInfo = urlGenerator.generateTempUrl(fileName, expiresInSeconds);
            
            if (!urlInfo.isSuccess()) {
                return createErrorLog(fileUrl, "生成短链接失败: " + urlInfo.getErrorMessage(), ownerName, ownerPhone, templateName);
            }
            
            String shortUrl = urlInfo.getUrl();
            log.info("短链接生成成功: {}", shortUrl);
            
            // 4. 进行视频模板检测
            log.info("开始进行视频模板检测，使用模型: {}", model != null ? model : "默认模型");
            DetectVideoTemplate detectLog = detectVideoTemplateAndSave(shortUrl, ownerName, ownerPhone, templateName, model);
            
            // 5. 更新日志记录，添加文件信息和临时链接信息
            detectLog.setVideoUrl(fileUrl);
            detectLog.setRequestId(detectLog.getRequestId()); // 保持原有的requestId
            detectLog.setTempUrl(shortUrl);
            detectLog.setTempUrlExpiresAt(urlInfo.getExpiresAt());
            // 如果检测日志中有task_id，也保存到数据库
            if (detectLog.getTaskId() != null) {
                detectLog.setTaskId(detectLog.getTaskId());
            }
            
            // 保存更新后的日志
            saveDetectVideoTemplateLog(detectLog);
            
            log.info("视频模板上传和检测处理完成，文件URL: {}, 短链接: {}", fileUrl, shortUrl);
            return detectLog;
            
        } catch (Exception e) {
            log.error("视频模板上传和检测失败: {}", e.getMessage(), e);
            return createErrorLog("", "视频模板上传和检测失败: " + e.getMessage(), ownerName, ownerPhone, templateName);
        }
    }
    
    /**
     * 从URL中提取文件名
     */
    private String extractFileNameFromUrl(String fileUrl) {
        if (fileUrl == null || fileUrl.trim().isEmpty()) {
            return null;
        }
        
        // 从URL中提取文件名
        // 例如: http://101.35.52.237:19005/car/20251009_105616_48320fc2d8e24f7bb4be66cbb54a6512.jpg
        // 提取: 20251009_105616_48320fc2d8e24f7bb4be66cbb54a6512.jpg
        String[] parts = fileUrl.split("/");
        if (parts.length > 0) {
            return parts[parts.length - 1];
        }
        
        return null;
    }
}
