package com.sonic.cow.client.impl;

import com.alibaba.fastjson.JSON;
import com.mashape.unirest.http.Headers;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import com.sonic.cow.client.TtsV2Client;
import com.sonic.cow.client.TtsV3Client;
import com.sonic.cow.client.config.TtsConfig;
import com.sonic.cow.domain.input.VoiceTtsV2Input;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.SocketConfig;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.pool.PoolStats;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.Base64;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class TtsV3ClientImpl implements TtsV3Client {

    @Autowired
    private TtsConfig ttsConfig;
    /**
     * 资源ID
     */
    private static final String resourceId = "volc.megatts.default";
    /**
     * 请求地址
     */
    private static final String url = "https://voice.ap-southeast-1.bytepluses.com/api/v3/tts/unidirectional";

    // 静态初始化：连接池和客户端
    private static final PoolingHttpClientConnectionManager connectionManager;
    private static final CloseableHttpClient httpClient;

    static {
        // 连接池配置
        connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(10);
        connectionManager.setDefaultMaxPerRoute(10);

        // Socket 配置：读写超时
        SocketConfig socketConfig = SocketConfig.custom()
                .setSoTimeout(30000)  // 读超时 30s（TTS 流式响应）
                .build();
        connectionManager.setDefaultSocketConfig(socketConfig);

        // 请求配置：连接请求超时 + 其他超时
        RequestConfig defaultConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(5000)  // 从池获取连接超时 5s
                .setConnectTimeout(5000)            // 建立新连接超时 5s
                .setSocketTimeout(30000)            // 读超时 30s
                .build();

        // 构建客户端，应用默认配置
        httpClient = HttpClients.custom()
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(defaultConfig)
                .setConnectionTimeToLive(30, TimeUnit.SECONDS)  // 连接最大存活 30s，过期自动清理
                .build();
    }

    @Override
    public String tts(String userId, VoiceTtsV2Input input) {
        CloseableHttpResponse response = null;
        try {
            // additions
            JSONObject additions = new JSONObject();
            additions.put("disable_markdown_filter", true);
            additions.put("enable_language_detector", true);
            additions.put("enable_latex_tn", true);
            additions.put("disable_default_bit_rate", true);
            additions.put("max_length_to_filter_parenthesis", 0);
            JSONObject cacheConfig = new JSONObject();
            cacheConfig.put("text_type", 1);
            cacheConfig.put("use_cache", false);
            additions.put("cache_config", cacheConfig);
            String additionsJson = additions.toString();

            // payload
            JSONObject payload = new JSONObject();
            JSONObject user = new JSONObject();
            user.put("uid", userId);
            payload.put("user", user);
            JSONObject reqParams = new JSONObject();
            reqParams.put("text", input.getText());
            reqParams.put("speaker", input.getVoiceType());
            reqParams.put("additions", additionsJson);
            JSONObject audioParams = new JSONObject();
            audioParams.put("format", "mp3");
            audioParams.put("sample_rate", 24000);
            //设置语速
            audioParams.put("speech_rate", input.getSpeechRate());

            //设置音高
            JSONObject postProcess = new JSONObject();
            postProcess.put("pitch", input.getPitchRate());
            audioParams.put("post_process", postProcess);

            reqParams.put("audio_params", audioParams);
            payload.put("req_params", reqParams);

            log.info("===> tts param : {}", payload);

            //获取连接状态
            PoolStats totalStats = connectionManager.getTotalStats();
            int totalConnections = connectionManager.getMaxTotal();  // 总数（上限）
            int leasedConnections = totalStats.getLeased();         // 已使用
            int availableConnections = totalStats.getAvailable();   // 空闲
            int pendingConnections = totalStats.getPending();       // 等待中
            int createdTotal = leasedConnections + availableConnections;  // 当前已创建总数
            log.info("===> http pool 总数上限: {}, 已创建: {}, 已使用: {}, 空闲: {}, 等待: {}",
                    totalConnections, createdTotal, leasedConnections, availableConnections, pendingConnections);

            // 构建 POST 请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("X-Api-App-Id", ttsConfig.getTtsAppId());
            httpPost.setHeader("X-Api-Access-Key", ttsConfig.getTtsAccessToken());
            httpPost.setHeader("X-Api-Resource-Id", resourceId);
            httpPost.setHeader("X-Api-App-Key", "aGjiRDfUWi");
            httpPost.setHeader("Content-Type", "application/json");
            httpPost.setHeader("Connection", "close");

            StringEntity entity = new StringEntity(payload.toString(), "UTF-8");
            httpPost.setEntity(entity);

            // 执行请求
            response = httpClient.execute(httpPost);

            // 日志响应 headers（类似原代码）
            Header[] headers = response.getAllHeaders();
            log.info("===> tts response headers: {}", JSON.toJSONString(headers));  // 需调整为数组格式，如果 JSON 需要

            // 处理流式响应
            try (InputStream is = response.getEntity().getContent();
                 BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"))) {

                ByteArrayOutputStream audioData = new ByteArrayOutputStream();
                int totalAudioSize = 0;
                String line;
                boolean endOfStream = false;
                while ((line = reader.readLine()) != null) {
                    if (line.isEmpty()) continue;
                    JSONObject data = new JSONObject(line);
                    log.info("json data:{}", JSON.toJSONString(data));

                    int code = data.optInt("code", 0);
                    if (code == 0) {
                        if (data.has("data") && !data.isNull("data") && !data.getString("data").isEmpty()) {
                            byte[] chunkAudio = Base64.getDecoder().decode(data.getString("data"));
                            totalAudioSize += chunkAudio.length;
                            audioData.write(chunkAudio);
                        }
                    } else if (code == 20000000) {
                        endOfStream = true;  // 流结束信号
                        break;
                    } else if (code > 0) {
                        log.info("error response:" + data);
                        break;
                    }
                }
                if (!endOfStream) {
                    log.warn("Stream may not be fully consumed, forcing EOF check");
                }

                if (audioData.size() > 0) {
                    String audioDataBase64 = Base64.getEncoder().encodeToString(audioData.toByteArray());
                    log.info("==================================");
                    log.info(audioDataBase64);
                    log.info("==================================");
                    return audioDataBase64;
                }
            }

        } catch (IOException e) {  // HttpClient 异常主要是 IOException
            log.error("===> request error: ", e);
        } finally {
            // 关闭响应（自动释放 entity）
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    log.error("Error closing response", e);
                }
            }
        }
        return null;
    }

}
