package com.red.circle.external.inner.service.aichat.tts.impl;

import com.alibaba.fastjson.JSON;
import com.red.circle.component.oss.OssService;
import com.red.circle.external.infra.props.TtsProperties;
import com.red.circle.external.inner.service.aichat.tts.TtsClientService;
import com.red.circle.tool.core.text.StringUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.*;

/**
 * TTS  实现.
 *
 * @author pengliang on 2023/7/12
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class TtsClientServiceImpl implements TtsClientService {

    private final OssService ossService;
    private final TtsProperties ttsProperties;

    @Override
    public String chat(String userMessage, String voiceId) {
        log.warn("TTS 请求:{}", userMessage);
        log.warn("ttsProperties 配置信息= {}", JSON.toJSONString(ttsProperties));

        long ttsStartTime = System.currentTimeMillis();
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String url = ttsProperties.getUrl();
        String model = ttsProperties.getModel();
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "application/json");
        try {
            StringEntity jsonEntity = new StringEntity(
                    JSON.toJSONString(getStringObjectMap(userMessage, voiceId, model)),
                    "UTF-8"
            );
            httpPost.setEntity(jsonEntity);
            CloseableHttpResponse response = httpClient.execute(httpPost);
            long ttsEndTime = System.currentTimeMillis();
            long ttsExecutionTime = ttsEndTime - ttsStartTime;
            log.info("用户消息 = {} 请求tts耗时 = {} ms", userMessage, ttsExecutionTime);
            try {
                int statusCode = response.getStatusLine().getStatusCode();
                log.warn("TTS 状态码:{}", statusCode);
                long ossStartTime = System.currentTimeMillis();
                if (statusCode == HttpStatus.SC_OK) {
                    HttpEntity entity = response.getEntity();
                    InputStream inputStream = entity.getContent();
                    String fileName = "ai/tts/" + UUID.randomUUID() + ".wav";
                    log.warn("TTS 保存文件路径:{}", fileName);
                    try {
                        ossService.uploadInputStream(inputStream, fileName);
                    } catch (Exception e) {
                        log.warn("TTS上传OSS失败:{}", e.getMessage());
                    }
                    long ossEndTime = System.currentTimeMillis();
                    long ossExecutionTime = ossEndTime - ossStartTime;
                    log.info("用户消息 = {} 请求oss耗时 = {} ms", userMessage, ossExecutionTime);
                    return ossService.getAccessUrl(fileName);
                } else { // 失败（如 500）
                    String errorBody = EntityUtils.toString(response.getEntity());
                    log.warn("请求失败，响应体: {}", errorBody);
                }
            } catch (Exception e) {
                log.warn("TTS 请求异常111:{}", e.getMessage());
            } finally {
                response.close();
            }

        } catch (Exception e) {
            log.warn("TTS 请求异常222:{}", e.getMessage());
        } finally {
            try {
                httpClient.close();
            } catch (IOException ignored) {

            }
        }
        return "";

    }

    @NotNull
    private static Map<String, Object> getStringObjectMap(String userMessage, String voiceId, String model) {
        if (StringUtils.isBlank(voiceId)) {
            voiceId = "Luna_moan_1";
        }
        Map<String, Object> sendMap = new HashMap<>();
        sendMap.put("model", model);
        sendMap.put("voice_id", voiceId);
        sendMap.put("language", "en");
        sendMap.put("api_key", "en");
        sendMap.put("text", userMessage);
        sendMap.put("sample_rate", 32000);
        return sendMap;
    }


    public static void main(String[] args) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String apiUrl = "http://116.148.216.100:9880/tts/stream";
        HttpPost httpPost = new HttpPost(apiUrl);
        httpPost.addHeader("Content-Type", "application/json");
        httpPost.addHeader("Accept", "audio/wav");

        try {
            // 准备请求参数
            StringEntity jsonEntity = new StringEntity(
                    JSON.toJSONString(getStringObjectMap("Hello,How are you ? I miss you,dear", "Luna_moan_1", "cloudsway_tts")),
                    "UTF-8"
            );
            httpPost.setEntity(jsonEntity);

            // 执行请求
            System.out.println("发送请求到: " + apiUrl);
            CloseableHttpResponse response = httpClient.execute(httpPost);

            try {
                int statusCode = response.getStatusLine().getStatusCode();
                System.out.println("响应状态码: " + statusCode);

                if (statusCode == HttpStatus.SC_OK) {
                    // 获取响应内容
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        byte[] audioData = EntityUtils.toByteArray(entity);
                        System.out.println("已获取音频数据，大小: " + audioData.length + " 字节");

                        // 保存音频文件（使用自定义WAV头部）
                        saveAudioWithCustomHeader(audioData, "output.wav");
                    }
                } else {
                    System.err.println("请求失败，状态码: " + statusCode);
                    String errorBody = EntityUtils.toString(response.getEntity());
                    System.err.println("错误响应: " + errorBody);
                }
            } finally {
                response.close();
            }
        } catch (Exception e) {
            System.err.println("发生异常: " + e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    // 使用自定义WAV头部保存音频数据
    private static void saveAudioWithCustomHeader(byte[] audioData, String fileName) {
        try (FileOutputStream fos = new FileOutputStream(fileName)) {
            // 设置WAV文件参数（根据实际音频调整）
            int sampleRate = 32000;    // 采样率，Hz
            int bitsPerSample = 16;    // 位深度，位
            int channels = 1;          // 声道数
            int dataSize = audioData.length; // 音频数据大小

            // 写入WAV文件头部
            writeWavHeader(fos, dataSize, sampleRate, bitsPerSample, channels);

            // 写入音频数据
            fos.write(audioData);

            log.info("音频已成功保存到: {}", fileName);
            log.info("文件大小: {} 字节", (36 + dataSize));
        } catch (IOException e) {
            log.error("保存音频文件失败: {}", e.getMessage());
        }
    }

    // 写入WAV文件头部
    private static void writeWavHeader(
            FileOutputStream fos,
            int dataSize,
            int sampleRate,
            int bitsPerSample,
            int channels) throws IOException {

        // RIFF头
        fos.write("RIFF".getBytes());
        writeInt(fos, 36 + dataSize);
        fos.write("WAVE".getBytes());

        // fmt块
        fos.write("fmt ".getBytes());
        writeInt(fos, 16);
        writeShort(fos, (short) 1);
        writeShort(fos, (short) channels);
        writeInt(fos, sampleRate);
        writeInt(fos, sampleRate * channels * bitsPerSample / 8);
        writeShort(fos, (short) (channels * bitsPerSample / 8));
        writeShort(fos, (short) bitsPerSample);

        // data块
        fos.write("data".getBytes());
        writeInt(fos, dataSize);
    }

    // 写入int（小端序）
    private static void writeInt(FileOutputStream fos, int value) throws IOException {
        fos.write(value & 0xFF);
        fos.write((value >> 8) & 0xFF);
        fos.write((value >> 16) & 0xFF);
        fos.write((value >> 24) & 0xFF);
    }

    // 写入short（小端序）
    private static void writeShort(FileOutputStream fos, short value) throws IOException {
        fos.write(value & 0xFF);
        fos.write((value >> 8) & 0xFF);
    }

    public static File generateAudioFile(String userMessage) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String apiUrl = "http://116.148.216.100:9880/tts/stream";
        HttpPost httpPost = new HttpPost(apiUrl);
        httpPost.addHeader("Content-Type", "application/json");
        httpPost.addHeader("Accept", "audio/wav");
        File tempFile = null;

        try {
            StringEntity jsonEntity = new StringEntity(
                    JSON.toJSONString(getStringObjectMap(userMessage, "Luna_moan_1", "cloudsway_tts")),
                    "UTF-8"
            );
            httpPost.setEntity(jsonEntity);

            // 执行请求
            log.info("发送请求到: {}", apiUrl);
            CloseableHttpResponse response = httpClient.execute(httpPost);

            try {
                int statusCode = response.getStatusLine().getStatusCode();
                log.info("响应状态码: {}", statusCode);

                if (statusCode == HttpStatus.SC_OK) {
                    // 获取响应内容
                    HttpEntity entity = response.getEntity();
                    if (entity != null) {
                        byte[] audioData = EntityUtils.toByteArray(entity);
                        log.info("已获取音频数据，大小: {} 字节", audioData.length);

                        // 创建临时文件
                        tempFile = createTempAudioFile(audioData);
                    }
                } else {
                    log.error("请求失败，状态码: {}", statusCode);
                    String errorBody = EntityUtils.toString(response.getEntity());
                    log.error("错误响应: {}", errorBody);
                }
            } finally {
                response.close();
            }
        } catch (Exception e) {
            log.error("发生异常: {}", e.getMessage(), e);
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                log.error("关闭HTTP客户端失败", e);
            }
        }
        return tempFile;
    }

    private static File createTempAudioFile(byte[] audioData) throws IOException {
        // 创建临时文件
        File tempFile = File.createTempFile("tts-audio-", ".wav");
        tempFile.deleteOnExit(); // 程序退出时自动删除

        try (FileOutputStream fos = new FileOutputStream(tempFile)) {
            // 设置WAV文件参数（根据实际音频调整）
            int sampleRate = 32000;
            int bitsPerSample = 16;
            int channels = 1;
            int dataSize = audioData.length;

            // 写入WAV文件头部
            writeWavHeader(fos, dataSize, sampleRate, bitsPerSample, channels);

            // 写入音频数据
            fos.write(audioData);

            log.info("音频已成功保存到临时文件: {}", tempFile.getAbsolutePath());
            log.info("文件大小: {} 字节", (36 + dataSize));
        } catch (IOException e) {
            log.error("保存音频临时文件失败: {}", e.getMessage());
            // 如果写入失败，删除临时文件
            if (tempFile.exists() && !tempFile.delete()) {
                log.warn("无法删除临时文件: {}", tempFile.getAbsolutePath());
            }
            throw e;
        }
        return tempFile;
    }

}
