package com.rj.service.impl;

import com.alibaba.dashscope.audio.asr.transcription.*;
import com.rj.entity.TtsRequestLog;
import com.rj.mapper.TtsRequestLogMapper;
import com.rj.service.ITtsRequestLogService;
import com.rj.service.MinIOService;
import com.rj.utils.MinIOUrlGenerator;
import com.rj.dto.AsrRequest;
import com.rj.dto.AsrResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.mock.web.MockMultipartFile;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

import java.io.File;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * TTS请求日志服务实现类
 * 
 * @author rj
 * @date 2025-01-02
 */
@Slf4j
@Service
public class TtsRequestLogServiceImpl implements ITtsRequestLogService {
    
    @Autowired
    private TtsRequestLogMapper ttsRequestLogMapper;
    
    @Autowired
    private MinIOUrlGenerator urlGenerator;
    
    @Autowired
    private MinIOService minIOService;
    
    @Value("${dashscope.api.key}")
    private String apiKey;
    
    @Value("${asr.enabled:true}")
    private boolean asrEnabled;
    
    @Value("${asr.default-model:paraformer-v2}")
    private String defaultAsrModel;
    
    @Override
    public boolean saveTtsRequestLog(TtsRequestLog requestLog) {
        try {
            int result = ttsRequestLogMapper.insert(requestLog);
            log.info("TTS请求日志保存成功: {}", requestLog.getId());
            return result > 0;
        } catch (Exception e) {
            log.error("TTS请求日志保存失败: {}", e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public TtsRequestLog getTtsRequestLogById(String id) {
        try {
            return ttsRequestLogMapper.selectById(id);
        } catch (Exception e) {
            log.error("查询TTS请求日志失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    @Override
    public boolean setShortUrlByAudioName(MinIOUrlGenerator.UrlInfo urlInfo ) {
        try {
            if (urlInfo == null || urlInfo.getFileName() == null || urlInfo.getFileName().trim().isEmpty()) {
                log.error("音频名称不能为空");
                return false;
            }
            
            // 根据音频名称查询日志记录
            LambdaQueryWrapper<TtsRequestLog> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(TtsRequestLog::getAudioName, urlInfo.getFileName());
            TtsRequestLog requestLog = ttsRequestLogMapper.selectOne(queryWrapper);
            
            if (requestLog == null) {
                log.error("未找到音频名称为 {} 的日志记录", urlInfo.getFileName());
                return false;
            } 
            
                // 更新日志记录的短链接信息
                requestLog.setShortUrl(urlInfo.getUrl());
                requestLog.setShortUrlExpireTime(urlInfo.getExpiresAt());
                requestLog.setUpdateTime(LocalDateTime.now());
                
                int result = ttsRequestLogMapper.updateById(requestLog);
                if (result > 0) {
                    log.info("成功为音频 {} 设置短链接: {}, 过期时间: {}",
                            urlInfo.getFileName(), urlInfo.getUrl(), urlInfo.getFormattedExpiresAt());
                    return true;
                } else {
                    log.error("更新音频 {} 的短链接失败", urlInfo.getFileName());
                    return false;
                } 
            
        } catch (Exception e) {
            log.error("根据音频名称设置短链接失败: 音频名称={}, 错误={}", urlInfo.getFileName(), e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public boolean setShortUrlByAudioName(String audioName) {
        return false;
    }
    
    /**
     * 音频转文本的公共方法
     * 支持本地文件路径或URL
     * 
     * @param audioPathOrUrl 音频文件路径（本地路径）或URL
     * @return 转换后的文本内容，失败时返回null
     */
    public String transcribeAudioToText(String audioPathOrUrl) {
        return transcribeAudioToText(audioPathOrUrl, defaultAsrModel);
    }
    
    /**
     * 音频转文本的公共方法
     * 支持本地文件路径或URL
     * 
     * @param audioPathOrUrl 音频文件路径（本地路径）或URL
     * @param model ASR模型名称，如果为null则使用默认模型
     * @return 转换后的文本内容，失败时返回null
     */
    public String transcribeAudioToText(String audioPathOrUrl, String model) {
        if (audioPathOrUrl == null || audioPathOrUrl.trim().isEmpty()) {
            log.error("音频文件路径或URL不能为空");
            return null;
        }
        
        if (!isAsrServiceAvailable()) {
            log.error("ASR服务不可用，请检查配置");
            return null;
        }
        
        try {
            // 判断是URL还是本地文件路径
            String audioUrl = audioPathOrUrl;
            
            // 判断是否为URL（以http://或https://开头）
            if (!audioPathOrUrl.startsWith("http://") && !audioPathOrUrl.startsWith("https://")) {
                log.info("检测到本地文件路径: {}", audioPathOrUrl);
                
                // 检查文件是否存在
                File file = new File(audioPathOrUrl);
                if (!file.exists() || !file.isFile()) {
                    log.error("本地文件不存在或不是文件: {}", audioPathOrUrl);
                    return null;
                }
                
                // 上传本地文件到MinIO获取URL
                try {
                    String fileName = file.getName();
                    String contentType = getContentType(fileName);
                    
                    // 读取文件内容
                    byte[] fileBytes = Files.readAllBytes(file.toPath());
                    
                    // 创建MultipartFile对象
                    MultipartFile multipartFile = new MockMultipartFile(
                            "file",
                            fileName,
                            contentType,
                            fileBytes
                    );
                    
                    // 上传到MinIO
                    audioUrl = minIOService.uploadFile(multipartFile);
                    log.info("本地文件已上传到MinIO，URL: {}", audioUrl);
                } catch (Exception e) {
                    log.error("上传本地文件到MinIO失败: {}", e.getMessage(), e);
                    return null;
                }
            } else {
                log.info("使用音频URL: {}", audioUrl);
            }
            
            // 使用默认模型或指定模型
            String asrModel = (model != null && !model.trim().isEmpty()) ? model : defaultAsrModel;
            
            log.info("开始语音识别 - 音频URL: {}, 模型: {}", audioUrl, asrModel);
            
            // 创建转写请求参数
            TranscriptionParam param = TranscriptionParam.builder()
                    .apiKey(apiKey)
                    .model(asrModel)
                    .fileUrls(Arrays.asList(audioUrl))
                    .build();
            
            // 创建转写对象
            Transcription transcription = new Transcription();
            
            // 提交转写请求
            TranscriptionResult result = transcription.asyncCall(param);
            String taskId = result.getTaskId();
            log.info("ASR任务已提交 - TaskId: {}", taskId);
            
            // 等待任务完成
            TranscriptionQueryParam queryParam = TranscriptionQueryParam.FromTranscriptionParam(param, taskId);
            result = transcription.wait(queryParam);
            log.info("语音识别完成 - TaskId: {}", taskId);
            
            if (result.getResults() != null && !result.getResults().isEmpty()) {
                // 解析识别结果
                StringBuilder fullText = new StringBuilder();
                
                // 遍历所有结果，获取transcriptionUrl并下载识别文本
                for (TranscriptionTaskResult taskResult : result.getResults()) {
                    if (taskResult.getTranscriptionUrl() != null) {
                        try {
                            // 从transcriptionUrl下载识别结果
                            String transcriptionResult = downloadTranscriptionResult(taskResult.getTranscriptionUrl());
                            
                            if (transcriptionResult != null && !transcriptionResult.trim().isEmpty()) {
                                // 解析transcription结果JSON
                                String extractedText = parseTranscriptionResult(transcriptionResult);
                                if (extractedText != null && !extractedText.trim().isEmpty()) {
                                    if (fullText.length() > 0) {
                                        fullText.append(" ");
                                    }
                                    fullText.append(extractedText);
                                }
                            }
                        } catch (Exception e) {
                            log.warn("下载transcription结果失败: {}", e.getMessage());
                        }
                    }
                }
                
                String resultText = fullText.toString().trim();
                if (resultText.isEmpty()) {
                    log.warn("ASR识别结果为空 - TaskId: {}", taskId);
                    return null;
                }
                
                log.info("语音识别完成 - 识别文本长度: {}, TaskId: {}", resultText.length(), taskId);
                return resultText;
            } else {
                log.warn("ASR识别结果为空 - TaskId: {}", taskId);
                return null;
            }
            
        } catch (Exception e) {
            log.error("语音识别失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 根据文件名获取Content-Type
     */
    private String getContentType(String fileName) {
        if (fileName == null) {
            return "application/octet-stream";
        }
        String lowerName = fileName.toLowerCase();
        if (lowerName.endsWith(".mp3")) {
            return "audio/mpeg";
        } else if (lowerName.endsWith(".wav")) {
            return "audio/wav";
        } else if (lowerName.endsWith(".m4a")) {
            return "audio/mp4";
        } else if (lowerName.endsWith(".aac")) {
            return "audio/aac";
        } else if (lowerName.endsWith(".ogg")) {
            return "audio/ogg";
        } else if (lowerName.endsWith(".flac")) {
            return "audio/flac";
        } else if (lowerName.endsWith(".wma")) {
            return "audio/x-ms-wma";
        }
        return "application/octet-stream";
    }
    
    @Override
    public AsrResponse speechToText(AsrRequest request) {
        long startTime = System.currentTimeMillis();
        
        try {
            if (!isAsrServiceAvailable()) {
                return AsrResponse.error("ASR服务不可用，请检查配置");
            }
            
            if (request.getAudioUrl() == null || request.getAudioUrl().trim().isEmpty()) {
                return AsrResponse.error("音频文件URL不能为空");
            }
            
            // 设置默认值
            if (request.getModel() == null || request.getModel().trim().isEmpty()) {
                request.setModel(defaultAsrModel);
            }
            if (request.getFormat() == null || request.getFormat().trim().isEmpty()) {
                request.setFormat("wav");
            }
            if (request.getSampleRate() == null) {
                request.setSampleRate(16000);
            }
            if (request.getEnablePunctuation() == null) {
                request.setEnablePunctuation(true);
            }
            if (request.getEnableNumberConversion() == null) {
                request.setEnableNumberConversion(true);
            }
            if (request.getEnableSpeakerDiarization() == null) {
                request.setEnableSpeakerDiarization(false);
            }
            if (request.getSpeakerCount() == null) {
                request.setSpeakerCount(1);
            }
            
            log.info("开始语音识别 - 音频URL: {}, 模型: {}, 格式: {}, 采样率: {}", 
                    request.getAudioUrl(), request.getModel(), request.getFormat(), request.getSampleRate());
            
            // 创建转写请求参数
            TranscriptionParam param = TranscriptionParam.builder()
                    .apiKey(apiKey)
                    .model(request.getModel())
                    .fileUrls(Arrays.asList(request.getAudioUrl()))
                    .build();
            
            // 创建转写对象
            Transcription transcription = new Transcription();
            
            // 提交转写请求
            TranscriptionResult result = transcription.asyncCall(param);
            String taskId = result.getTaskId();
            String requestId = result.getRequestId();
            
            log.info("ASR任务已提交 - TaskId: {}, RequestId: {}", taskId, requestId);
            
            // 等待任务完成
            TranscriptionQueryParam queryParam = TranscriptionQueryParam.FromTranscriptionParam(param, taskId);
            result = transcription.wait(queryParam);
            log.info("语音识别完成 - result: {} ", result);
            long processingTime = System.currentTimeMillis() - startTime;
            
            if (result.getResults() != null && !result.getResults().isEmpty()) {
                // 解析识别结果 - 从results中获取transcriptionUrl并下载识别结果
                String fullText = "";
                Double duration = 0.0;
                List<AsrResponse.AsrResult> asrResults = new ArrayList<>();
                
                try {
                    // 从usage中获取时长信息
                    if (result.getUsage() != null) {
                        // 从usage对象中获取duration，usage通常是一个JsonObject
                        try {
                            String usageStr = result.getUsage().toString();
                            if (usageStr.contains("\"duration\"")) {
                                int durationStart = usageStr.indexOf("\"duration\":") + 11;
                                int durationEnd = usageStr.indexOf(",", durationStart);
                                if (durationEnd == -1) {
                                    durationEnd = usageStr.indexOf("}", durationStart);
                                }
                                if (durationStart > 10 && durationEnd > durationStart) {
                                    duration = Double.parseDouble(usageStr.substring(durationStart, durationEnd).trim());
                                }
                            }
                        } catch (Exception e) {
                            log.warn("解析usage中的duration失败: {}", e.getMessage());
                        }
                    }
                    
                    // 遍历所有结果，获取transcriptionUrl并下载识别文本
                    for (TranscriptionTaskResult taskResult : result.getResults()) {
                        if (taskResult.getTranscriptionUrl() != null) {
                            try {
                                // 从transcriptionUrl下载识别结果
                                String transcriptionResult = downloadTranscriptionResult(taskResult.getTranscriptionUrl());
                               // log.info("transcriptionResult: {}" , transcriptionResult);

                                if (transcriptionResult != null && !transcriptionResult.trim().isEmpty()) {
                                    // 解析transcription结果JSON
                                    String extractedText = parseTranscriptionResult(transcriptionResult);
                                    if (extractedText != null && !extractedText.trim().isEmpty()) {
                                        fullText += extractedText;
                                        
                                        // 输出识别文本到控制台
                                        System.out.println("=== 语音识别结果 ===");
                                        System.out.println("任务ID: " + taskId);
                                        System.out.println("识别文本: " + extractedText);
                                        System.out.println("==================");
                                        
                                        // 创建结果对象
                                        AsrResponse.AsrResult asrResult = new AsrResponse.AsrResult();
                                        asrResult.setText(extractedText);
                                        asrResult.setStartTime(0.0);
                                        asrResult.setEndTime(duration);
                                        asrResults.add(asrResult);
                                    }
                                }
                            } catch (Exception e) {
                                log.warn("下载transcription结果失败: {}", e.getMessage());
                            }
                        }
                    }
                    
                } catch (Exception e) {
                    log.warn("解析ASR结果时出错: {}", e.getMessage());
                }
                
                if (fullText.trim().isEmpty()) {
                    log.warn("ASR识别结果为空 - TaskId: {}", taskId);
                    return AsrResponse.error("语音识别结果为空");
                }
                
                log.info("语音识别完成 - 识别文本长度: {}, 处理时间: {}ms", fullText.length(), processingTime);
                
                // 如果提供了TTS日志ID，则保存识别文本到数据库
                if (request.getId() != null && !request.getId().trim().isEmpty()) {
                    saveRecognizedTextToDatabase(request.getId(), fullText);
                }
                
                return AsrResponse.success(fullText, asrResults, duration, processingTime, taskId, requestId);
            } else {
                log.warn("ASR识别结果为空 - TaskId: {}", taskId);
                return AsrResponse.error("语音识别结果为空");
            }
            
        } catch (Exception e) {
            log.error("语音识别失败: {}", e.getMessage(), e);
            return AsrResponse.error("语音识别失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean isAsrServiceAvailable() {
        return asrEnabled && apiKey != null && !apiKey.trim().isEmpty();
    }
    
    /**
     * 下载transcription结果
     */
    private String downloadTranscriptionResult(String transcriptionUrl) {
        try {
            log.info("开始下载transcription结果，URL: {}", transcriptionUrl);
            
            // 使用简单的URL连接下载transcription结果，避免HttpClient依赖问题
            java.net.URL url = new java.net.URL(transcriptionUrl);
            java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
            
            // 设置请求头
            connection.setRequestMethod("GET");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
            connection.setRequestProperty("Accept", "application/json");
            connection.setConnectTimeout(30000); // 30秒连接超时
            connection.setReadTimeout(60000);   // 60秒读取超时
            
            int responseCode = connection.getResponseCode();
            if (responseCode == 200) {
                // 读取响应内容
                StringBuilder result = new StringBuilder();
                try (java.io.BufferedReader reader = new java.io.BufferedReader(
                        new java.io.InputStreamReader(connection.getInputStream(), java.nio.charset.StandardCharsets.UTF_8))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        result.append(line).append("\n");
                    }
                }
                
                String responseBody = result.toString().trim();
                log.info("成功下载transcription结果，长度: {} 字符", responseBody.length());
                return responseBody;
            } else {
                log.warn("下载transcription结果失败，状态码: {}", responseCode);
                return null;
            }
        } catch (Exception e) {
            log.error("下载transcription结果异常: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 解析transcription结果JSON，提取识别文本
     */
    private String parseTranscriptionResult(String transcriptionJson) {
        try {
            // 使用Jackson解析JSON
            ObjectMapper mapper = new ObjectMapper();
            JsonNode rootNode = mapper.readTree(transcriptionJson);
            
            log.info("开始解析transcription JSON");
            
            // 根据阿里云ASR返回的JSON结构解析
            // 阿里云返回的结构: {"transcripts": [{"text": "识别的文本", "sentences": [...]}]}
            JsonNode transcriptsNode = rootNode.get("transcripts");
            if (transcriptsNode != null && transcriptsNode.isArray() && transcriptsNode.size() > 0) {
                JsonNode firstTranscript = transcriptsNode.get(0);
                JsonNode textNode = firstTranscript.get("text");
                if (textNode != null && !textNode.isNull()) {
                    String text = textNode.asText();
                    log.info("成功提取识别文本: {}", text);
                    return text;
                }
            }
            
            // 如果没有transcripts字段，尝试其他可能的字段结构
            JsonNode resultsNode = rootNode.get("results");
            if (resultsNode != null && resultsNode.isArray()) {
                StringBuilder textBuilder = new StringBuilder();
                for (JsonNode resultNode : resultsNode) {
                    JsonNode textNode = resultNode.get("text");
                    if (textNode != null && !textNode.isNull()) {
                        String text = textNode.asText();
                        textBuilder.append(text).append(" ");
                        log.info("提取到文本片段: {}", text);
                    }
                }
                String fullText = textBuilder.toString().trim();
                if (!fullText.isEmpty()) {
                    log.info("完整识别文本: {}", fullText);
                    return fullText;
                }
            }
            
            // 如果没有results字段，尝试直接获取text字段
            JsonNode textNode = rootNode.get("text");
            if (textNode != null && !textNode.isNull()) {
                String text = textNode.asText();
                log.info("直接获取文本: {}", text);
                return text;
            }
            
            // 如果都没有，记录JSON结构用于调试
            log.warn("未找到预期的文本字段，JSON结构: {}", rootNode.toString());
            return null;
        } catch (Exception e) {
            log.error("解析transcription结果JSON失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 保存识别文本到数据库
     */
    private void saveRecognizedTextToDatabase(String ttsLogId, String recognizedText) {
        try {
            // 根据ID查询TTS请求日志
            TtsRequestLog ttsLog = ttsRequestLogMapper.selectById(ttsLogId);
            if (ttsLog != null) {
                // 将识别文本保存到inputText字段
                ttsLog.setInputText(recognizedText);
                ttsLog.setInputLength(recognizedText.length());
                ttsLog.setUpdateTime(LocalDateTime.now());
                
                // 保存到数据库
                int updateResult = ttsRequestLogMapper.updateById(ttsLog);
                if (updateResult > 0) {
                    log.info("成功保存识别文本到数据库，TTS日志ID: {}, 文本长度: {}", ttsLogId, recognizedText.length());
                } else {
                    log.warn("保存识别文本到数据库失败，TTS日志ID: {}", ttsLogId);
                }
            } else {
                log.warn("未找到对应的TTS请求日志，ID: {}", ttsLogId);
            }
        } catch (Exception e) {
            log.error("保存识别文本到数据库异常: {}", e.getMessage(), e);
        }
    }
}
