package com.sonic.cow.client;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import okhttp3.*;
import org.apache.commons.codec.binary.Base64;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class TtsHttpStreamReuse {
    // ------------- 客户需要填写参数 ---------------- (同前)
    private static final String APP_ID = "7330233595";
    private static final String ACCESS_KEY = "NxFxll0gDGl3W0TWW1Fqh23PzKaaQiLu";
    private static final String RESOURCE_ID = "volc.megatts.default";
    private static final String TEXT = "你好我有一个帽衫";
    private static final String URL = "https://voice.ap-southeast-1.bytepluses.com/api/v3/tts/unidirectional";
    private static final Gson GSON = new Gson();

    // 共享的OkHttpClient：这是复用关键！默认连接池支持5个空闲连接/主机，keep-alive 5min（>服务器1min）
    private static final OkHttpClient CLIENT = new OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            // 可选：自定义连接池，最大空闲连接5，keep-alive 2min（匹配服务器）
            // .connectionPool(new ConnectionPool(5, 2, TimeUnit.MINUTES))
            .build();

    private static final Semaphore SEMAPHORE = new Semaphore(1, true); // 限并发1
    private static final int CONCURRENCY_ERROR_CODE = 45000292;

    public static void main(String[] args) throws InterruptedException {
        int totalRequests = 18;
        for (int i = 1; i <= totalRequests; i++) {
            System.out.println("========== 第" + i + "次请求开始 ==========");
            ttsHttpStream(i);
            System.out.println("========== 第" + i + "次请求结束 ==========");
            Thread.sleep(2000); // 2s延时，确保<1min复用
        }
        // 测试结束后，可选：CLIENT.dispatcher().executorService().shutdown(); // 但不强制
    }

    public static void ttsHttpStream(int requestId) {
        try {
            SEMAPHORE.acquire();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return;
        }

        Response response = null;
        int retryCount = 0;
        int maxRetries = 3;
        boolean success = false;

        while (retryCount < maxRetries && !success) {
            try {
                // Headers：添加 keep-alive（默认，但显式）
                Headers headers = new Headers.Builder()
                        .add("X-Api-App-Id", APP_ID)
                        .add("X-Api-Access-Key", ACCESS_KEY)
                        .add("X-Api-Resource-Id", RESOURCE_ID)
                        .add("X-Api-App-Key", "aGjiRDfUWi")
                        .add("Content-Type", "application/json")
                        .add("Connection", "keep-alive") // 关键：启用复用
                        .build();

                // Payload构建（同前，省略...）
                Map<String, Object> additions = new HashMap<>();
                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);
                Map<String, Object> cacheConfig = new HashMap<>();
                cacheConfig.put("text_type", 1);
                cacheConfig.put("use_cache", true);
                additions.put("cache_config", cacheConfig);
                String additionsJson = GSON.toJson(additions);

                Map<String, Object> payload = new HashMap<>();
                Map<String, Object> user = new HashMap<>();
                user.put("uid", "12345");
                payload.put("user", user);
                Map<String, Object> reqParams = new HashMap<>();
                reqParams.put("text", TEXT);
                reqParams.put("speaker", "S_vbdl9fqD1");
                reqParams.put("additions", additionsJson);
                Map<String, Object> audioParams = new HashMap<>();
                audioParams.put("format", "mp3");
                audioParams.put("sample_rate", 24000);
                reqParams.put("audio_params", audioParams);
                payload.put("req_params", reqParams);
                String payloadJson = GSON.toJson(payload);

                RequestBody requestBody = RequestBody.create(payloadJson, MediaType.get("application/json; charset=utf-8"));
                Request request = new Request.Builder().url(URL).headers(headers).post(requestBody).build();

                // 用共享CLIENT执行：这里会自动检查/复用池中连接
                response = CLIENT.newCall(request).execute();

                if (!response.isSuccessful()) {
                    System.out.println("HTTP 错误: " + response);
                    retryCount++;
                    continue;
                }

                // 流式读取（同前，省略细节...）
                ByteArrayOutputStream audioData = new ByteArrayOutputStream();
                boolean hasError = false;
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.body().byteStream()))) {
                    String chunk;
                    while ((chunk = reader.readLine()) != null) {
                        if (chunk.isEmpty()) continue;
                        System.out.println("json data: " + chunk);
                        JsonObject data = GSON.fromJson(chunk, JsonObject.class);
                        int code = data.has("code") ? data.get("code").getAsInt() : 0;

                        if (code == 0 && data.has("data") && !data.get("data").isJsonNull()) {
                            String base64Audio = data.get("data").getAsString();
                            byte[] chunkAudio = Base64.decodeBase64(base64Audio);
                            audioData.write(chunkAudio);
                        } else if (code == CONCURRENCY_ERROR_CODE) {
                            System.out.println("并发配额超限，重试 (第 " + (retryCount + 1) + " 次)");
                            hasError = true;
                            break;
                        } else if (code == 20000000) {
                            break;
                        } else if (code > 0) {
                            System.out.println("error response: " + data);
                            hasError = true;
                            break;
                        }
                    }
                }

                if (!hasError) {
                    byte[] finalAudio = audioData.toByteArray();
                    if (finalAudio.length > 0) {
                        String outputDir = "tts";
                        Files.createDirectories(Paths.get(outputDir));
                        String outputFile = Paths.get(outputDir, "tts_reuse_" + requestId + ".mp3").toString();
                        try (FileOutputStream fos = new FileOutputStream(outputFile)) {
                            fos.write(finalAudio);
                        }
                        System.out.printf("文件大小: %.2f KB (复用连接成功)%n", finalAudio.length / 1024.0);
                        success = true;
                    }
                } else {
                    retryCount++;
                }

                if (!success && retryCount < maxRetries) {
                    long backoff = (long) Math.pow(2, retryCount) * 1000;
                    System.out.println("等待 " + backoff + "ms 后重试...");
                    Thread.sleep(backoff);
                }

            } catch (Exception e) {
                System.out.println("请求异常: " + e.getMessage());
                retryCount++;
            } finally {
                if (response != null) {
                    response.close(); // 只关闭响应，不关Client（允许复用）
                }
            }
        }

        SEMAPHORE.release();
        if (!success) {
            System.out.println("请求 " + requestId + " 失败，请检查配额。");
        }
    }
}