package com.cmvr.test.flow.runtime.operator.edge.vi;

import cmvr.api.SpeakerCommand;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.edge.client.model.EdgeCommonVO;
import com.cmvr.edge.client.service.EdgeBioHeadService;
import com.cmvr.edge.client.service.EdgeSpeakerService;
import com.cmvr.test.enums.ActionEnum;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
import com.cmvr.test.flow.runtime.operator.edge.EdgeOperateService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import java.io.File;

@Slf4j
@Service
@RequiredArgsConstructor
public class ViPlayOperateService implements EdgeOperateService {

    private final EdgeSpeakerService edgeSpeakerService;
    private final EdgeBioHeadService edgeBioHeadService;

    @Override
    public boolean supports(ActionEnum action) {
        return action.name().startsWith("VI_PLAY");
    }

    @Override
    public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) {
        ActionEnum action = message.getAction();
        if (!action.equals(ActionEnum.VI_PLAY_CORPUS)) {
            throw new GlobalException("播放语料的action不是VI_PLAY_CORPUS");
        }

        JSONObject inputParams = message.getInputParams();
        String deviceId = inputParams.getString("deviceId");
        String bioId = inputParams.getString("bioId");
        String audioPath = inputParams.getString("audioPath");
        String terminalId = message.getTerminalId();

        // 仅当 bioId 不为空时才构造 VO
        EdgeCommonVO edgeCommonVO = null;
        boolean needBioSpeak = StrUtil.isNotEmpty(bioId);
        if (needBioSpeak) {
            edgeCommonVO = new EdgeCommonVO();
            edgeCommonVO.setDeviceId(bioId);
            edgeCommonVO.setTerminalId(terminalId);
        }

        log.info("语料播放成功，audioPath={}", audioPath);

        /*try {
            // 播放音频
            edgeSpeakerService.playAudio(terminalId, deviceId, audioPath);

            // 播放开始时，若 bioId 存在才张嘴
            if (needBioSpeak) {
                try {
                    Thread.sleep(500);
                    edgeBioHeadService.speakStart(edgeCommonVO);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }

            // 等待播放完成
            while (true) {
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                SpeakerCommand.GetSpeakerStateCommand.Feedback status =
                        edgeSpeakerService.getStatus(terminalId, deviceId);

                if (!status.getState().getIsRunning()) {
                    break;
                }
            }

        } finally {
            // 播放完成后，若 bioId 存在才闭嘴
            if (needBioSpeak) {
                edgeBioHeadService.speakStop(edgeCommonVO);
            }
        }*/

        return TaskNodeExecuteResult.success();
    }


    /**
     * 播放一个音频文件（阻塞直到播完）
     */
    private void playAudio(String filePath) {
        try (AudioInputStream sourceStream = AudioSystem.getAudioInputStream(new File(filePath))) {
            AudioFormat baseFormat = sourceStream.getFormat();
            AudioFormat targetFormat = new AudioFormat(
                    AudioFormat.Encoding.PCM_SIGNED,
                    baseFormat.getSampleRate(),
                    16,
                    baseFormat.getChannels(),
                    baseFormat.getChannels() * 2,
                    baseFormat.getSampleRate(),
                    false
            );

            try (AudioInputStream pcmStream = AudioSystem.getAudioInputStream(targetFormat, sourceStream)) {
                DataLine.Info info = new DataLine.Info(SourceDataLine.class, targetFormat);
                try (SourceDataLine line = (SourceDataLine) AudioSystem.getLine(info)) {
                    line.open(targetFormat);
                    line.start();

                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = pcmStream.read(buffer, 0, buffer.length)) != -1) {
                        line.write(buffer, 0, bytesRead);
                    }

                    // 确保缓冲区播完
                    line.drain();
                    line.stop();
                }
            }

            log.info("播放完成: {}", filePath);

        } catch (Exception e) {
            throw new GlobalException("播放失败: ", e);
        }
    }

}
