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 TtsHttpStreamV2 {
    // ------------- 客户需要填写参数 ----------------
    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 = "你好我有一个帽衫";

    // --------------- 请求 URL ----------------------
    private static final String URL = "https://voice.ap-southeast-1.bytepluses.com/api/v3/tts/unidirectional";

    // Gson 实例用于 JSON 解析
    private static final Gson GSON = new Gson();

    // 并发控制：Semaphore 限制最大并发数（根据配额调整，例如 1 为安全）
    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 = 20;
        for (int i = 1; i <= totalRequests; i++) {
            System.out.println("========== 第" + i + "次请求开始 ==========");
            ttsHttpStream(i);
            System.out.println("========== 第" + i + "次请求结束 ==========");
            Thread.sleep(2000); // 每请求后延时 2s，避免率限
        }
    }

    public static void ttsHttpStream(int requestId) {
        // 为每个请求创建独立的 OkHttpClient，确保不复用连接（强制关闭后无复用）
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)
                .build();

        // 获取信号量，确保不超过并发限
        try {
            SEMAPHORE.acquire();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            client.dispatcher().executorService().shutdownNow(); // 强制关闭客户端
            return;
        }

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

        while (retryCount < maxRetries && !success) {
            try {
                // 构建 headers（添加 "Connection": "close" 进一步确保服务器端关闭连接）
                Headers.Builder headersBuilder = 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", "close"); // 强制关闭连接，不 keep-alive

                Headers headers = headersBuilder.build();

                // 构建 additions 和 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();

                response = client.newCall(request).execute();
                System.out.println("===> tts response X-Tt-Logid: " +  response.headers().get("X-Tt-Logid"));
                if (!response.isSuccessful()) {
                    System.out.println("HTTP 错误: " + response);
                    retryCount++;
                    continue;
                }

                // 流式读取（同原代码）
                ByteArrayOutputStream audioData = new ByteArrayOutputStream();
                long totalAudioSize = 0;
                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);
                            totalAudioSize += chunkAudio.length;
                            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_test_v2_" + 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; // 2s, 4s, 8s
                    System.out.println("等待 " + backoff + "ms 后重试...");
                    Thread.sleep(backoff);
                }

            } catch (Exception e) {
                System.out.println("请求异常: " + e.getMessage());
                e.printStackTrace();
                retryCount++;
            } finally {
                if (response != null) {
                    response.close();
                }
            }
        }

        // 释放信号量
        SEMAPHORE.release();

        // 强制关闭客户端实例，确保连接不复用
        client.dispatcher().executorService().shutdownNow();
        client.connectionPool().evictAll(); // 驱逐所有连接

        if (!success) {
            System.out.println("请求 " + requestId + " 最终失败，已达最大重试次数。请检查配额。");
        }
    }
}