package com.seer.teach.teacher.service.platform.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesis;
import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisParam;
import com.alibaba.dashscope.aigc.imagesynthesis.ImageSynthesisResult;
import com.alibaba.dashscope.audio.tts.SpeechSynthesisResult;
import com.alibaba.dashscope.audio.tts.timestamp.Sentence;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesisParam;
import com.alibaba.dashscope.audio.ttsv2.SpeechSynthesizer;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.seer.teach.common.enums.AiPlatformEnum;
import com.seer.teach.teacher.common.llm.sse.req.Message;
import com.seer.teach.teacher.service.platform.AiPlatformCallService;
import com.seer.teach.teacher.service.platform.AudioWord;
import com.seer.teach.teacher.service.platform.LlmRequest;
import com.seer.teach.teacher.service.platform.LlmResponse;
import com.seer.teach.teacher.service.platform.LlmTaskRequest;
import com.seer.teach.teacher.service.platform.StreamingTextToAudioResult;
import io.reactivex.Flowable;
import io.reactivex.disposables.Disposable;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
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.springframework.http.codec.ServerSentEvent;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.SignalType;
import reactor.core.publisher.Sinks;

import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 阿里云百炼平台调用服务实现
 */
@Slf4j
@Service
public class AliyunBailianPlatformCallServiceImpl implements AiPlatformCallService {


    @Override
    public Optional<LlmResponse> callTextModel(LlmRequest request) {
        try (CloseableHttpClient httpClient = HttpClients.custom().build()) {
            // 构建请求体
            String url = request.getUrl();

            log.info("调用大模型接口，URL: {}", url);
            String modelIdentifier = request.getModel();
            if (!StringUtils.hasText(modelIdentifier)) {
                modelIdentifier = "qwen-plus";
            }
            HttpPost post = new HttpPost(url);
            post.addHeader("Content-Type", "application/json");
            post.addHeader("Authorization", "Bearer " + request.getApiKey());

            // 使用ObjectMapper构建安全的JSON请求体
            ObjectMapper mapper = new ObjectMapper();
            ObjectNode requestBody = mapper.createObjectNode();
            requestBody.put("model", modelIdentifier);
            requestBody.put("stream", request.getStream() != null ? request.getStream() : false);
            // 设置模型参数
            if (request.getTemperature() != null) {
                requestBody.put("temperature", request.getTemperature());
            }
            if (request.getTopP() != null) {
                requestBody.put("top_p", request.getTopP());
            }

            ArrayNode messages = mapper.createArrayNode();
            if (CollectionUtil.isNotEmpty(request.getMessages())) {
                for (Message message : request.getMessages()) {
                    ObjectNode msg = mapper.createObjectNode();
                    msg.put("role", message.getRole());
                    Object content = message.getContent();
                    if (content instanceof String) {
                        // 如果是单个字符串
                        msg.put("content", (String) content);
                    } else if (content instanceof List) {
                        // 如果是 List<String>
                        ArrayNode contentArray = mapper.createArrayNode();
                        for (Object item : (List<?>) content) {
                            contentArray.add(String.valueOf(item));
                        }
                        msg.set("content", contentArray);
                    } else {
                        // 其他类型可以直接转 JSON
                        msg.set("content", mapper.valueToTree(content));
                    }
                    messages.add(msg);
                }
            } else {
                ObjectNode message = mapper.createObjectNode();
                message.put("role", "user");
                message.put("content", request.getPrompt());
                messages.add(message);
            }

            requestBody.set("messages", messages);
            if (request.getTemperature() != null) {
                requestBody.put("temperature", request.getTemperature());
            }

            if (request.getTopP() != null) {
                requestBody.put("top_p", request.getTopP());
            }

            String payload = mapper.writeValueAsString(requestBody);
            log.info("请求体: {}", payload);
            post.setEntity(new StringEntity(payload, StandardCharsets.UTF_8));

            HttpResponse response = httpClient.execute(post);
            HttpEntity entity = response.getEntity();
            if (response.getStatusLine().getStatusCode() == 200 && entity != null) {
                String responseBody = EntityUtils.toString(entity);
                log.info("大模型API调用成功，响应: {}", responseBody);
                LlmResponse llmResponse = parseLLMResponse(responseBody);
                return Optional.of(llmResponse);
            } else {
                log.error("大模型API调用失败，状态码: {}", response.getStatusLine().getStatusCode());
                log.info("响应: {}", response);
            }
            return Optional.empty();
        } catch (Exception e) {
            log.error("调用大模型API时发生异常", e);
            return Optional.empty();
        }
    }

    /**
     * 解析大模型响应（用于图片生成场景）
     * {
     * "output" : {
     * "choices" : [ {
     * "finish_reason" : "stop",
     * "message" : {
     * "content" : [ {
     * "image" : "https://dashscope-result-wlcb-acdr-1.oss-cn-wulanchabu-acdr-1.aliyuncs.com/7d/f9/20251031/d81d59b0/ae43f959-fedd-4c10-b5da-4aebb9893a4f-1.png?Expires=1762482961&OSSAccessKeyId=LTAI5tKPD3TMqf2Lna1fASuh&Signature=SIya9IT0HPHgG4E5fOGGyn7q6ps%3D"
     * } ],
     * "role" : "assistant"
     * }
     * } ],
     * "task_metric" : {
     * "FAILED" : 0,
     * "SUCCEEDED" : 1,
     * "TOTAL" : 1
     * }
     * },
     * "usage" : {
     * "height" : 928,
     * "image_count" : 1,
     * "width" : 1664
     * },
     * "request_id" : "ae43f959-fedd-4c10-b5da-4aebb9893a4f"
     * }
     *
     * @param taskRequest 响应体
     * @return LlmResponse对象
     */
    @Override
    public Optional<LlmResponse> getTaskResult(LlmTaskRequest taskRequest) {
        String taskId = taskRequest.getTaskId();
        log.info("获取任务结果，任务ID: {}", taskId);
        try {
            ImageSynthesis imageSynthesis = new ImageSynthesis();
            ImageSynthesisResult result = imageSynthesis.fetch(taskId, taskRequest.getApiKey());
            if (result != null && "SUCCEEDED".equalsIgnoreCase(result.getOutput().getTaskStatus())) {
                log.info("获取任务结果成功，任务ID: {}, 状态: {}", taskId, result.getOutput().getTaskStatus());

                LlmResponse llmResponse = new LlmResponse();
                llmResponse.setId(taskId);

                List<LlmResponse.Choice> choices = new ArrayList<>();
                LlmResponse.Choice choice = new LlmResponse.Choice();
                choice.setIndex(0);

                List<LlmResponse.ImageResult> imageResults = new ArrayList<>();
                for (Map<String, String> stringStringMap : result.getOutput().getResults()) {
                    LlmResponse.ImageResult imageResult = new LlmResponse.ImageResult();
                    imageResult.setUrl(stringStringMap.get("url"));
                    log.info("图片URL: {}", stringStringMap.get("url"));
                    imageResults.add(imageResult);
                }
                choice.setImageResults(imageResults);
                choices.add(choice);
                llmResponse.setChoices(choices);

                return Optional.of(llmResponse);
            } else {
                log.warn("获取任务结果失败，任务ID: {}", taskId);
                return Optional.empty();
            }
        } catch (Exception e) {
            log.error("获取任务结果时发生异常，任务ID: {}", taskId, e);
            return Optional.empty();
        }
    }

    @Override
    public Optional<String> asyncCallImageModel(LlmRequest request) {
        try {
            String modelIdentifier = request.getModel();
            if (!StringUtils.hasText(modelIdentifier)) {
                modelIdentifier = "wan2.2-t2i-flash";
            }

            String size = (request.getWidth() != null ? request.getWidth() : "683") + "*" +
                    (request.getHeight() != null ? request.getHeight() : "512");
            // 创建图像生成参数构建器
            ImageSynthesisParam.ImageSynthesisParamBuilder paramBuilder = ImageSynthesisParam.builder()
                    .apiKey(request.getApiKey())
                    .model(modelIdentifier)
                    .n(request.getN())
                    .prompt(request.getPrompt())
                    .size(size);

            // 设置可选参数
            if (request.getNegativePrompt() != null) {
                paramBuilder.negativePrompt(request.getNegativePrompt());
            }

            ImageSynthesisParam imageParam = paramBuilder.build();
            log.info("请求参数：{}",imageParam.toString());
            // 调用图像生成服务
            ImageSynthesis imageSynthesis = new ImageSynthesis();
            log.info("调用大模型，开始调用");
            ImageSynthesisResult result = imageSynthesis.call(imageParam);

            if (result != null) {
                log.info("大模型API调用成功，响应: {}", result.toString());
                return Optional.of(result.getOutput().getTaskId());
            } else {
                log.error("大模型API调用失败，返回结果为空");
                return Optional.empty();
            }
        } catch (Exception e) {
            log.error("调用大模型API时发生异常", e);
            return Optional.empty();
        }
    }

    @Override
    public String getSupportedPlatform() {
        return AiPlatformEnum.ALIYUN_BAILIAN.getCode();
    }

    /**
     * 解析大模型响应（用于题目生成场景）
     *
     * @param responseBody 响应体
     * @return LlmResponse对象
     */
    private LlmResponse parseLLMResponse(String responseBody) {
        LlmResponse llmResponse = new LlmResponse();
        try {
            // 解析JSON响应
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(responseBody);

            // 提取基本字段
            if (rootNode.has("id")) {
                llmResponse.setId(rootNode.get("id").asText());
            }

            if (rootNode.has("model")) {
                llmResponse.setModel(rootNode.get("model").asText());
            }

            // 提取choices
            JsonNode choices = rootNode.get("choices");
            if (choices != null && choices.isArray() && choices.size() > 0) {
                List<LlmResponse.Choice> choiceList = new ArrayList<>();
                for (JsonNode choiceNode : choices) {
                    LlmResponse.Choice choice = new LlmResponse.Choice();
                    if (choiceNode.has("index")) {
                        choice.setIndex(choiceNode.get("index").asInt());
                    }

                    if (choiceNode.has("finish_reason")) {
                        choice.setFinishReason(choiceNode.get("finish_reason").asText());
                    }

                    if (choiceNode.has("message")) {
                        JsonNode messageNode = choiceNode.get("message");
                        LlmResponse.Message message = new LlmResponse.Message();
                        if (messageNode.has("role")) {
                            message.setRole(messageNode.get("role").asText());
                        }
                        if (messageNode.has("content")) {
                            message.setContent(messageNode.get("content").asText());
                        }
                        choice.setMessage(message);
                    }
                    choiceList.add(choice);
                }
                llmResponse.setChoices(choiceList);
            }

            // 提取usage
            if (rootNode.has("usage")) {
                JsonNode usageNode = rootNode.get("usage");
                LlmResponse.Usage usage = new LlmResponse.Usage();
                if (usageNode.has("prompt_tokens")) {
                    usage.setPromptTokens(usageNode.get("prompt_tokens").asInt());
                }
                if (usageNode.has("completion_tokens")) {
                    usage.setCompletionTokens(usageNode.get("completion_tokens").asInt());
                }
                if (usageNode.has("total_tokens")) {
                    usage.setTotalTokens(usageNode.get("total_tokens").asInt());
                }
                llmResponse.setUsage(usage);
            }

            return llmResponse;
        } catch (Exception e) {
            log.error("解析大模型响应时发生异常", e);
            return llmResponse;
        }
    }




    @Override
    public Queue<StreamingTextToAudioResult> callText2Audio(LlmRequest request) {
        // 创建参数
        SpeechSynthesisParam param = createSpeechSynthesisParam(request);

        SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
        String textToSynthesize = request.getText();

        // 用于收集音频数据的队列
        ConcurrentLinkedQueue<StreamingTextToAudioResult> audioDataQueue = new ConcurrentLinkedQueue<>();

        try {
            Flowable<SpeechSynthesisResult> flowable = synthesizer.callAsFlowable(textToSynthesize);
            flowable.blockingSubscribe(
                result -> {
                    StreamingTextToAudioResult streamingResult = parseSpeechSynthesisResult(result);
                    // 收集音频数据
                    audioDataQueue.add(streamingResult);
                },
                error -> {
                    log.error("文本转音频过程中发生错误", error);
                },
                () -> {
                    // 完成时关闭连接
                    try {
                        synthesizer.getDuplexApi().close(1000, "bye");
                    } catch (Exception e) {
                        log.error("关闭语音合成器时发生错误", e);
                    }
                    // 添加最终标记
                    StreamingTextToAudioResult finalResult = createFinalStreamingResult();
                    audioDataQueue.add(finalResult);
                }
            );
        } catch (NoApiKeyException e) {
            log.error("API密钥缺失", e);
        }

        return audioDataQueue;
    }

    @Override
    public Flux<ServerSentEvent<StreamingTextToAudioResult>> streamText2Audio(LlmRequest request) {
        // 创建参数
        SpeechSynthesisParam param = createSpeechSynthesisParam(request);

        SpeechSynthesizer synthesizer = new SpeechSynthesizer(param, null);
        String textToSynthesize = request.getText();

        // 创建一个Sinks.Many用于发射数据
        Sinks.Many<ServerSentEvent<StreamingTextToAudioResult>> sink = Sinks.many().unicast().onBackpressureBuffer();

        try {
            Flowable<SpeechSynthesisResult> flowable = synthesizer.callAsFlowable(textToSynthesize);
            // 保存Disposable引用以防止被垃圾回收并允许取消订阅
            Disposable disposable = flowable.subscribe(
                result -> {
                    StreamingTextToAudioResult streamingResult = parseSpeechSynthesisResult(result);

                    // 发射数据，包装为ServerSentEvent
                    ServerSentEvent<StreamingTextToAudioResult> event = ServerSentEvent.builder(streamingResult).build();
                    sink.tryEmitNext(event);
                },
                error -> {
                    log.error("流式文本转音频过程中发生错误", error);
                    sink.tryEmitError(error);
                },
                () -> {
                    // 完成时关闭连接并完成发射
                    try {
                        synthesizer.getDuplexApi().close(1000, "bye");
                    } catch (Exception e) {
                        log.error("关闭语音合成器时发生错误", e);
                    }
                    // 发送最后一个数据包，标识流已完成
                    StreamingTextToAudioResult finalResult = createFinalStreamingResult();
                    ServerSentEvent<StreamingTextToAudioResult> finalEvent = ServerSentEvent.builder(finalResult).build();
                    sink.tryEmitNext(finalEvent);
                    sink.tryEmitComplete();
                }
            );
            
            // 返回flux并在取消订阅时处理资源清理
            return sink.asFlux()
                    .doFinally(signalType -> {
                        if (signalType == SignalType.CANCEL) {
                            log.info("用户取消了阿里云百炼TTS流，正在清理资源");
                            // 取消订阅
                            if (disposable != null && !disposable.isDisposed()) {
                                disposable.dispose();
                            }
                            // 关闭连接
                            try {
                                synthesizer.getDuplexApi().close(1000, "cancelled by user");
                            } catch (Exception e) {
                                log.error("关闭语音合成器时发生错误", e);
                            }
                        }
                    });
        } catch (NoApiKeyException e) {
            log.error("API密钥缺失", e);
            sink.tryEmitError(e);
            return sink.asFlux();
        }
    }

    /**
     * 创建语音合成参数
     *
     * @param request 请求参数
     * @return 语音合成参数
     */
    private SpeechSynthesisParam createSpeechSynthesisParam(LlmRequest request) {
        return SpeechSynthesisParam.builder()
                .model(request.getModel())
                .voice("longyingxiao")
                .apiKey(request.getApiKey())
                .enableWordTimestamp(true)
                .enablePhonemeTimestamp(true)
                .build();
    }

    /**
     * 解析语音合成结果
     *
     * @param result 语音合成结果
     * @return 流式文本转音频结果
     */
    private StreamingTextToAudioResult parseSpeechSynthesisResult(SpeechSynthesisResult result) {
        StreamingTextToAudioResult streamingResult = new StreamingTextToAudioResult();

        // 处理音频数据
        ByteBuffer audioFrame = result.getAudioFrame();
        if (audioFrame != null && audioFrame.hasRemaining()) {
            ByteBuffer bufferCopy = ByteBuffer.allocate(audioFrame.remaining());
            bufferCopy.put(audioFrame);
            bufferCopy.flip();
            streamingResult.setAudioData(bufferCopy);
        }
        Sentence sentence = result.getTimestamp();
        if (sentence != null) {
            streamingResult.setSentence(JSONUtil.toJsonStr(sentence));
        }
        return streamingResult;
    }

    /**
     * 创建最终的流式文本转音频结果
     *
     * @return 最终的流式文本转音频结果
     */
    private StreamingTextToAudioResult createFinalStreamingResult() {
        StreamingTextToAudioResult finalResult = new StreamingTextToAudioResult();
        AudioWord finalWord = new AudioWord();
        finalWord.setFinal(true);
        finalResult.setWord(finalWord);
        finalResult.setFinal(true);
        finalResult.setStreamingCompleted(true);
        return finalResult;
    }

    /**
     * 保存音频数据到本地文件
     * @param text 原始文本
     * @param audioDataQueue 音频数据队列
     */
    private void saveAudioDataToLocalFile(String text, ConcurrentLinkedQueue<StreamingTextToAudioResult> audioDataQueue) {
        try {
            log.info("开始保存阿里云百炼音频数据到本地文件");

            // 将队列转换为列表
            List<StreamingTextToAudioResult> audioDataList = new ArrayList<>(audioDataQueue);

            // 合并所有音频数据为一个完整的音频
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            StringBuilder subtitleBuilder = new StringBuilder();

            for (StreamingTextToAudioResult result : audioDataList) {
                // 处理音频数据
                if (result.getAudioData() != null) {
                    byte[] audioBytes = new byte[result.getAudioData().remaining()];
                    result.getAudioData().get(audioBytes);
                    outputStream.write(audioBytes);
                }

                // 处理字幕数据
                if (result.getWord() != null) {
                    subtitleBuilder.append(result.getWord().getText());
                }
            }

            // 生成文件名
            String fileNamePrefix = "aliyun_tts_" + System.currentTimeMillis();

            // 保存音频文件 (这里只是示例，实际应用中可能需要保存到特定目录)
            byte[] audioData = outputStream.toByteArray();
            String base64Audio = Base64.getEncoder().encodeToString(audioData);
            log.info("阿里云百炼音频文件大小: {} 字节", audioData.length);
            log.info("阿里云百炼音频文件Base64长度: {} 字符", base64Audio.length());

            // 保存字幕文件 (这里只是示例，实际应用中可能需要保存到特定目录)
            String subtitles = subtitleBuilder.toString();
            log.info("阿里云百炼字幕内容: {}", subtitles);

            log.info("阿里云百炼音频数据保存完成，文件名前缀: {}", fileNamePrefix);
        } catch (Exception e) {
            log.error("保存阿里云百炼音频数据到本地文件时发生错误", e);
        }
    }
}