package com.vetti.common.ai.elevenLabs;

import com.google.gson.Gson;
import com.vetti.common.ai.elevenLabs.vo.VoiceSettings;
import com.vetti.common.ai.elevenLabs.vo.VoicesResponse;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
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.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * 文本转换为语音
 */
@Component
public class ElevenLabsClient {

    @Value("${elevenLabs.baseUrl}")
    private String BASE_URL;

    @Value("${elevenLabs.apiKey}")
    private String apiKey;

    @Value("${elevenLabs.modelId}")
    private String modelId;


    /**
     * 将文本转换为语音并保存到文件
     *
     * @param text           要转换的文本
     * @param voiceId        语音ID (可从ElevenLabs网站获取)
     * @param outputFilePath 输出文件路径
     * @throws IOException 网络请求或文件操作异常
     */
    private void textToSpeech(String text, String voiceId, String outputFilePath,CloseableHttpClient httpClient) throws IOException {
        HttpPost httpPost = new HttpPost(BASE_URL + "/text-to-speech/" + voiceId);
        httpPost.setHeader("xi-api-key", apiKey);
        httpPost.setHeader("Content-Type", "application/json");

        Map<String, Object> payload = new HashMap<>();
        payload.put("text", text);
        payload.put("model_id", modelId);
        payload.put("voice_settings", new VoiceSettings(0.85, 0.5,0.1,0,0.9,1));
        Gson gson = new Gson();
        StringEntity entity = new StringEntity(gson.toJson(payload), ContentType.APPLICATION_JSON);
        httpPost.setEntity(entity);
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            HttpEntity responseEntity = response.getEntity();
            if (responseEntity != null) {
                try (InputStream inputStream = responseEntity.getContent();
                     FileOutputStream outputStream = new FileOutputStream(outputFilePath)) {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                }
            }
        }
    }

    /**
     * 获取可用的语音列表
     *
     * @return 语音列表响应
     * @throws IOException 网络请求异常
     */
    private VoicesResponse getVoices(CloseableHttpClient httpClient){
        HttpGet httpGet = new HttpGet(BASE_URL + "/voices");
        httpGet.setHeader("xi-api-key", apiKey);
        Gson gson = new Gson();
        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            HttpEntity responseEntity = response.getEntity();
            String responseBody = EntityUtils.toString(responseEntity);
            return gson.fromJson(responseBody, VoicesResponse.class);
        }catch (Exception e){
            throw new RuntimeException("获取可用的语音列表异常");
        }
    }

    /**
     * 处理文本转换成语音文件
     * @param inputText
     * @param outputFile
     * @return
     */
    public String handleTextToVoice(String inputText,String outputFile){
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            // 使用第一个可用语音进行文本转语音(澳洲本地女声)
//            String firstVoiceId = "56bWURjYFHyYyVf490Dp";
            String firstVoiceId = "56bWURjYFHyYyVf490Dp";
            textToSpeech(inputText, firstVoiceId, outputFile,httpClient);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return outputFile;
    }
}
