package com.rj.service;

import com.rj.config.SiliconFlowConfig;
import com.rj.dto.SiliconFlowTtsRequest;
import com.rj.dto.SiliconFlowTtsResponse;
import com.rj.entity.TtsRequestLog;
import com.rj.utils.MinIOUrlGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;

/**
 * SiliconFlow TTS 服务类
 * 
 * @author rj
 * @date 2025-01-02
 */
@Slf4j
@Service
public class SiliconFlowTtsService {
    
    @Autowired
    private SiliconFlowConfig config;
    
    @Autowired
    private RestTemplate restTemplate;
    
    @Autowired
    private com.rj.service.MinIOService minioService;
    
    @Autowired
    private ITtsRequestLogService ttsRequestLogService;
    
    @Autowired
    private MinIOUrlGenerator urlGenerator;
    
    private static final String TTS_ENDPOINT = "/audio/speech";
    
    /**
     * 文本转语音
     * 
     * @param request TTS请求
     * @return TTS响应
     */
    public SiliconFlowTtsResponse textToSpeech(SiliconFlowTtsRequest request) {
        long startTime = System.currentTimeMillis();
        TtsRequestLog requestLog = new TtsRequestLog();
        
        try {
            if (!config.isEnabled()) {
                return SiliconFlowTtsResponse.error("SiliconFlow服务未启用");
            }
            
            if (request.getModel() == null || request.getModel().trim().isEmpty()) {
                request.setModel(config.getDefaultTtsModel());
            }
            
            // 确保voice参数正确设置
            if (request.getVoice() == null || request.getVoice().trim().isEmpty()) {
                // 根据模型设置默认voice参数  FunAudioLLM/CosyVoice2-0.5B:claire
                String model = request.getModel();
                if (model != null && model.contains("fnlp/MOSS-TTSD-v0.5")) {
                    request.setVoice("fnlp/MOSS-TTSD-v0.5:claire");
                } else {
                    request.setVoice("FunAudioLLM/CosyVoice2-0.5B:claire"); // 默认使用claire
                }
            }
            
            if (request.getInput() == null || request.getInput().trim().isEmpty()) {
                return SiliconFlowTtsResponse.error("输入文本不能为空");
            }
            
            String url = config.getBaseUrl() + TTS_ENDPOINT;
            
            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setBearerAuth(config.getApiKey());
            
            // 创建请求实体
            HttpEntity<SiliconFlowTtsRequest> requestEntity = new HttpEntity<>(request, headers);
            
            // 详细记录请求参数
            log.info("发送TTS请求到: {}", url);
            log.info("TTS请求参数 - 模型: {}, 输入文本: {}, 输入长度: {}, 语音: {}, 语速: {}, 音调: {}, 音量: {}, 格式: {}, 采样率: {}", 
                request.getModel(), 
                request.getInput(), 
                request.getInput().length(),
                request.getVoice(),
                request.getSpeed(),
                request.getPitch(),
                request.getVolume(),
                request.getFormat(),
                request.getSampleRate()
            );
            
            // 发送请求 - SiliconFlow API返回音频流，不是JSON
            ResponseEntity<byte[]> response = restTemplate.exchange(
                url,
                HttpMethod.POST,
                requestEntity,
                byte[].class
            );
            
            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                byte[] audioBytes = response.getBody();
                String audioBase64 = Base64.getEncoder().encodeToString(audioBytes);
                
                // 估算音频时长（MP3格式）
                double estimatedDuration = calculateAudioDuration(audioBytes.length, "mp3");
                
                // 上传到MinIO
                String fileName = uploadAudioToMinIO(audioBytes, request.getInput());
                
                // 生成MinIO直接访问URL
                String minioUrl = null;
                if (fileName != null) {
                    minioUrl = minioService.getFileUrl(fileName);
                }
                
                // 生成临时访问URL（15分钟有效）
                MinIOUrlGenerator.UrlInfo tempUrlInfo = null;
                if (fileName != null) {
                    tempUrlInfo = urlGenerator.generateShortTermUrl(fileName);
                }
                
                SiliconFlowTtsResponse ttsResponse = new SiliconFlowTtsResponse();
                ttsResponse.setSuccess(true);
                ttsResponse.setAudio(audioBase64);
                ttsResponse.setFormat("mp3"); // SiliconFlow默认返回mp3格式
                ttsResponse.setSampleRate(44100); // 默认采样率
                ttsResponse.setDuration(estimatedDuration);
                ttsResponse.setMinioUrl(minioUrl); // 直接MinIO访问URL
                
                // 添加临时访问URL（短链）
                if (tempUrlInfo != null) {
                    ttsResponse.setShortUrl(tempUrlInfo.getUrl());
                    ttsResponse.setShortUrlExpireTime(tempUrlInfo.getExpiresAt());
                }
                
                // 保存请求日志到数据库
                saveTtsRequestLog(requestLog, request, ttsResponse, startTime, null, fileName);
                
                log.info("TTS请求成功，音频数据长度: {} bytes, 估算时长: {:.2f}秒, MinIO URL: {}, 临时URL: {}", 
                    audioBytes.length, estimatedDuration, minioUrl, tempUrlInfo != null ? tempUrlInfo.getUrl() : "无");
                return ttsResponse;
            } else {
                log.error("TTS请求失败，状态码: {}", response.getStatusCode());
                return SiliconFlowTtsResponse.error("TTS请求失败，状态码: " + response.getStatusCode());
            }
            
        } catch (Exception e) {
            log.error("TTS请求异常: {}", e.getMessage(), e);
            

            // 保存错误日志到数据库
            SiliconFlowTtsResponse errorResponse = SiliconFlowTtsResponse.error("TTS请求异常: " + e.getMessage());
            saveTtsRequestLog(requestLog, request, errorResponse, startTime, e.getMessage(), null);
            
            return errorResponse;
        }
    }
    
    /**
     * 简单文本转语音
     * 
     * @param text 要转换的文本
     * @return TTS响应
     */
    public SiliconFlowTtsResponse textToSpeech(String text) {
        SiliconFlowTtsRequest request = new SiliconFlowTtsRequest();
        request.setModel(config.getDefaultTtsModel());
        request.setInput(text);
        // voice参数会在textToSpeech方法中自动设置
        return textToSpeech(request);
    }
    
    /**
     * 文本转语音并返回音频字节数组
     * 
     * @param request TTS请求
     * @return 音频字节数组
     */
    public byte[] textToSpeechBytes(SiliconFlowTtsRequest request) {
        SiliconFlowTtsResponse response = textToSpeech(request);
        if (response.isSuccess() && response.getAudio() != null) {
            try {
                return Base64.getDecoder().decode(response.getAudio());
            } catch (Exception e) {
                log.error("Base64解码失败: {}", e.getMessage());
                return null;
            }
        }
        return null;
    }
    
    /**
     * 简单文本转语音并返回音频字节数组
     * 
     * @param text 要转换的文本
     * @return 音频字节数组
     */
    public byte[] textToSpeechBytes(String text) {
        SiliconFlowTtsRequest request = new SiliconFlowTtsRequest();
        request.setModel(config.getDefaultTtsModel());
        request.setInput(text);
        // voice参数会在textToSpeech方法中自动设置
        return textToSpeechBytes(request);
    }
    
    /**
     * 检查服务状态
     * 
     * @return 是否可用
     */
    public boolean isServiceAvailable() {
        return config.isEnabled() && config.getApiKey() != null && !config.getApiKey().trim().isEmpty();
    }
    
    /**
     * 计算音频时长
     * 
     * @param audioSizeBytes 音频文件大小（字节）
     * @param format 音频格式
     * @return 估算的音频时长（秒）
     */
    private double calculateAudioDuration(long audioSizeBytes, String format) {
        if (audioSizeBytes <= 0) {
            return 0.0;
        }
        
        // 根据格式和文件大小估算时长
        // 这是一个粗略的估算，实际时长可能因编码参数而异
        double estimatedDuration;
        
        switch (format.toLowerCase()) {
            case "mp3":
                // MP3 128kbps 大约 16KB/秒，但实际可能因编码而异
                // 使用更保守的估算：约 20KB/秒
                estimatedDuration = audioSizeBytes / 20000.0;
                break;
            case "wav":
                // WAV 44.1kHz 16bit 立体声 = 176KB/秒
                estimatedDuration = audioSizeBytes / 176000.0;
                break;
            case "opus":
                // Opus 通常 64kbps，约 8KB/秒
                estimatedDuration = audioSizeBytes / 8000.0;
                break;
            default:
                // 默认估算
                estimatedDuration = audioSizeBytes / 20000.0;
                break;
        }
        
        // 确保时长在合理范围内
        return Math.max(0.1, Math.min(estimatedDuration, 3600.0)); // 0.1秒到1小时
    }
    
    /**
     * 上传音频到MinIO
     * 
     * @param audioBytes 音频字节数组
     * @param inputText 输入文本（用于生成文件名）
     * @return 文件名
     */
    private String uploadAudioToMinIO(byte[] audioBytes, String inputText) {
        try {
            // 生成文件名：tts_时间戳_文本hash.mp3
            String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
            String textHash = String.valueOf(inputText.hashCode()).replace("-", "");
            String fileName = String.format("tts_%s_%s.mp3", timestamp, textHash);
            
            // 上传到MinIO
            minioService.uploadFile(audioBytes, fileName, "audio/mpeg");
            
            log.info("音频上传到MinIO成功: {}, 大小: {} bytes", fileName, audioBytes.length);
            return fileName;
            
        } catch (Exception e) {
            log.error("音频上传到MinIO失败: {}", e.getMessage(), e);
            return null; // 上传失败不影响TTS功能
        }
    }
    
    /**
     * 保存TTS请求日志到数据库
     * 
     * @param requestLog 请求日志对象
     * @param request TTS请求
     * @param response TTS响应
     * @param startTime 开始时间
     * @param errorMessage 错误信息
     * @param audioFileName 音频文件名
     */
    private void saveTtsRequestLog(TtsRequestLog requestLog, SiliconFlowTtsRequest request, 
                                 SiliconFlowTtsResponse response, long startTime, String errorMessage, String audioFileName) {
        try {
            long processingTime = System.currentTimeMillis() - startTime;
            
            // 设置请求参数
            requestLog.setRequestTime(LocalDateTime.now());
            requestLog.setModel(request.getModel());
            requestLog.setInputText(request.getInput());
            requestLog.setInputLength(request.getInput() != null ? request.getInput().length() : 0);
            requestLog.setVoice(request.getVoice());
            requestLog.setSpeed(request.getSpeed());
            requestLog.setPitch(request.getPitch());
            requestLog.setVolume(request.getVolume());
            requestLog.setFormat(request.getFormat());
            requestLog.setSampleRate(request.getSampleRate());
            requestLog.setCreatorName(request.getCreatorName());
            requestLog.setCreatorPhone(request.getCreatorPhone());
            requestLog.setAudioName(request.getAudioName());
            
            // 设置响应信息
            requestLog.setStatus(response.isSuccess() ? "SUCCESS" : "FAILED");
            requestLog.setDuration(response.getDuration());
            requestLog.setMinioUrl(response.getMinioUrl()); // 临时访问URL
            requestLog.setAudioName(audioFileName); // 音频文件名
            requestLog.setShortUrl(response.getShortUrl()); // 短链URL（与MinIO URL相同）
            requestLog.setShortUrlExpireTime(response.getShortUrlExpireTime());
            requestLog.setProcessingTimeMs(processingTime);
            requestLog.setCreateTime(LocalDateTime.now());
            requestLog.setUpdateTime(LocalDateTime.now());
            
            // 设置音频文件大小
            if (response.getAudio() != null) {
                try {
                    byte[] audioBytes = Base64.getDecoder().decode(response.getAudio());
                    requestLog.setAudioSizeBytes((long) audioBytes.length);
                } catch (Exception e) {
                    log.warn("计算音频文件大小失败: {}", e.getMessage());
                }
            }
            
            // 设置错误信息
            if (errorMessage != null) {
                requestLog.setErrorMessage(errorMessage);
            } else if (!response.isSuccess()) {
                requestLog.setErrorMessage(response.getMessage());
                requestLog.setErrorCode(response.getErrorCode());
            }
            
            // 保存到数据库
            ttsRequestLogService.saveTtsRequestLog(requestLog);
            
            log.info("TTS请求日志已保存: ID={}, 状态={}, 处理时间={}ms", 
                requestLog.getId(), requestLog.getStatus(), processingTime);
                
        } catch (Exception e) {
            log.error("保存TTS请求日志失败: {}", e.getMessage(), e);
        }
    }
}
