package cn.iocoder.byzs.module.ai.util.tts;

import cn.iocoder.byzs.module.ai.dal.dataobject.tts.AiTtsDO;
import com.alibaba.nls.client.AccessToken;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.OutputFormatEnum;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.tts.StreamInputTts;
import com.alibaba.nls.client.protocol.tts.StreamInputTtsListener;
import com.alibaba.nls.client.protocol.tts.StreamInputTtsResponse;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.function.Consumer;

@Service
@Slf4j
@Scope("prototype")  // 原型作用域，每次注入都会创建新实例
public class StreamTtsService {

    @Value("${ai.tts.appKey:4SUOF4LfaU7FekyW}")
    private String appKey;

    @Value("${ai.tts.token:20aa8ae2577b414db6c3cbbfcdc287be}")
    private String token;

    @Value("${ai.tts.url:wss://nls-gateway-cn-beijing.aliyuncs.com/ws/v1}")
    private String url;


    @Value("${ai.tts.ALIYUN_AK_ID:LTAI5tQhMPLXtSgXiPiWbw6D}")
    private String ALIYUN_AK_ID;
    @Value("${ai.tts.ALIYUN_AK_SECRET:HCXpFYjl4swk0qwfIKa9s2bXx0AWcG}")
    private String ALIYUN_AK_SECRET;

    private NlsClient client;
    private Thread playbackThread;
    private StreamInputTts synthesizer;
    // ==== 添加音频数据回调 ====
    private Consumer<byte[]> audioDataCallback;
    // 添加完成回调接口
    private Runnable onCompleteCallback;

    @PostConstruct
    public void init() {
        getToken();
        // 初始化NlsClient
        client = new NlsClient(url, token);
    }

    public String getToken(){
        AccessToken accessToken = new AccessToken(ALIYUN_AK_ID, ALIYUN_AK_SECRET);
        try {
            accessToken.apply();
            token = accessToken.getToken();
            long expireTime = accessToken.getExpireTime();
            log.info("token: {}, expireTime: {}", token, expireTime);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return token;
    }

    /**
     * 开始TTS语音合成
     */
    public void startTts(AiTtsDO aiTtsDO) {
        // 创建TTS实例
        try {
            synthesizer = new StreamInputTts(client, getSynthesizerListener());
        } catch (Exception e) {
            log.error("创建TTS实例", e);
            throw new RuntimeException("创建TTS实例", e);
        }
        synthesizer.setAppKey(appKey);
        synthesizer.setFormat(OutputFormatEnum.PCM); // 确保输出PCM格式
        synthesizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K); // 24000Hz采样率
        synthesizer.setVoice(aiTtsDO.getModel());
        synthesizer.setVolume(aiTtsDO.getVolume());
        synthesizer.setPitchRate(aiTtsDO.getPitchRate());
        synthesizer.setSpeechRate(aiTtsDO.getSpeechRate());
        // ==== 启用文本拆分禁用配置 ====
//        synthesizer.setSplitText(false); // 禁用文本自动拆分
//        synthesizer.setEnableSplit(false); // 禁用文本拆分，确保整句合成


        try {
            synthesizer.startStreamInputTts();
        } catch (Exception e) {
            log.error("启动TTS失败", e);
            throw new RuntimeException("启动TTS失败", e);
        }
    }

    /**
     * 发送文本到TTS服务进行语音合成
     */
    public void sendText(String text) {
        if (synthesizer == null) {
            throw new IllegalStateException("TTS服务尚未启动，请先调用startTts()");
        }
        try {
            synthesizer.sendStreamInputTts(text);
        } catch (Exception e) {
            log.error("发送文本到TTS服务失败", e);
            throw new RuntimeException("发送文本到TTS服务失败", e);
        }
    }

    /**
     * 结束TTS语音合成
     */
    public void stopTts() {
        try {
            if (synthesizer != null) {
                synthesizer.stopStreamInputTts();
                synthesizer.close();
            }
            if (playbackThread != null) {
                playbackThread.join();
            }
        } catch (Exception e) {
            log.error("停止TTS服务失败", e);
        } finally {
            synthesizer = null;
            playbackThread = null;
            setAudioDataCallback(null);
        }
    }

    private StreamInputTtsListener getSynthesizerListener() {
        return new StreamInputTtsListener() {
            private boolean firstRecvBinary = true;

            @Override
            public void onSynthesisStart(StreamInputTtsResponse response) {
                log.info("TTS合成开始: name={}, status={}", response.getName(), response.getStatus());
            }

            @Override
            public void onSentenceBegin(StreamInputTtsResponse response) {
                log.info("句子开始合成: name={}, status={}", response.getName(), response.getStatus());
            }

            @Override
            public void onSentenceEnd(StreamInputTtsResponse response) {
                log.info("句子合成结束: name={}, status={}", response.getName(), response.getStatus());
            }

            @Override
            public void onSynthesisComplete(StreamInputTtsResponse response) {
                log.info("TTS合成完成: name={}, status={}", response.getName(), response.getStatus());
                // 调用完成回调
                if (onCompleteCallback != null) {
                    onCompleteCallback.run();
                }
            }

            @Override
            public void onAudioData(ByteBuffer message) {
                if (firstRecvBinary) {
                    firstRecvBinary = false;
                    log.info("收到第一包语音数据");
                }
                byte[] bytesArray = new byte[message.remaining()];
                message.get(bytesArray, 0, bytesArray.length);

                // ==== 调用回调传递音频数据 ====
                log.info("生成音频数据: 长度={} bytes", bytesArray.length);
                if (audioDataCallback != null) {
                    try {
                        audioDataCallback.accept(bytesArray);
                        log.info("音频数据已发送到SSE流");
                    } catch (Exception e) {
                        log.error("音频数据回调失败", e);
                    }
                } else {
                    log.warn("音频数据回调未设置，无法发送音频数据");
                }
            }

            @Override
            public void onSentenceSynthesis(StreamInputTtsResponse response) {
                log.info("句子合成进度: name={}, status={}", response.getName(), response.getStatus());
            }

            @Override
            public void onFail(StreamInputTtsResponse response) {
                log.error("TTS合成失败: session_id={}, task_id={}, status={}, message={}",
                        getStreamInputTts().getCurrentSessionId(),
                        response.getTaskId(),
                        response.getStatus(),
                        response.getStatusText());
            }
        };
    }

    public void setAudioDataCallback(Consumer<byte[]> callback) {
        this.audioDataCallback = callback;
    }

    @PreDestroy
    public void destroy() {
        if (client != null) {
            client.shutdown();
        }
        stopTts();
    }

    public void setOnCompleteCallback(Runnable callback) {
        this.onCompleteCallback = callback;
    }

}
