package org.dromara.talk.service.impl;

import java.util.HashMap;
import java.util.Map;

import cn.hutool.json.JSONObject;
import okhttp3.*;
import org.dromara.talk.config.DifyConfig;
import org.dromara.talk.service.IDifyService;
import org.springframework.stereotype.Service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
public class DifyServiceImpl implements IDifyService {
    private final DifyConfig difyConfig;
    private final OkHttpClient httpClient = new OkHttpClient.Builder()
        .connectTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
        .readTimeout(60, java.util.concurrent.TimeUnit.SECONDS)
        .writeTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
        .build();

    @Override
    public void callWorkflowStream(String userMessage, String agentGender,
                                   java.util.List<java.util.Map<String, String>> ttsVcnList,
                                   org.dromara.talk.domain.vo.TalkAgentVo agentConfig,
                                   Long userId, String conversationId, String customerPhone, Integer type,
                                   java.util.function.Consumer<String> onTextChunk,
                                   IDifyService.SentenceCallback onSentence) {
        try {
            log.info("流式调用 Dify 工作流 - userId: {}, conversationId: {}", userId, conversationId);

            // 构建请求体
            Map<String, Object> inputs = new HashMap<>();
            inputs.put("agentGender", agentGender);
            inputs.put("ttsVcnList", ttsVcnList);
            inputs.put("currentVcn", agentConfig != null ? agentConfig.getTtsVcn() : null);
            if (customerPhone != null && !customerPhone.isEmpty()) {
                inputs.put("customerPhone", customerPhone);
            }
            if (type != null) {
                inputs.put("type", type);
            }

            JSONObject requestBody = new JSONObject();
            requestBody.set("inputs", inputs);
            requestBody.set("query", userMessage);
            requestBody.set("response_mode", "streaming");
            requestBody.set("user", "user-" + userId);

            if (conversationId != null && !conversationId.isEmpty()) {
                requestBody.set("conversation_id", conversationId);
            }

            Request request = new Request.Builder()
                .url(difyConfig.getApiUrl() + "/chat-messages")
                .post(RequestBody.create(
                    requestBody.toString(),
                    MediaType.parse("application/json")))
                .addHeader("Authorization", "Bearer " + difyConfig.getApiKey())
                .addHeader("Content-Type", "application/json")
                .build();

            Response response = httpClient.newCall(request).execute();

            log.info("Dify API 响应状态码: {}", response.code());

            if (!response.isSuccessful()) {
                String errorBody = response.body() != null ? response.body().string() : "无响应体";
                log.error("Dify API 调用失败，状态码: {}, 响应: {}", response.code(), errorBody);
                throw new RuntimeException("Dify API 调用失败: " + response.code());
            }

            StringBuilder currentSentence = new StringBuilder();
            String newConversationId = null;

            try (ResponseBody responseBody = response.body()) {
                if (responseBody == null) {
                    throw new RuntimeException("响应体为空");
                }

                java.io.BufferedReader reader = new java.io.BufferedReader(
                    new java.io.InputStreamReader(responseBody.byteStream(), java.nio.charset.StandardCharsets.UTF_8)
                );

                String line;
                while ((line = reader.readLine()) != null) {
                    if (line.startsWith("data: ")) {
                        String jsonData = line.substring(6);

                        try {
                            JSONObject event = new JSONObject(jsonData);
                            String eventType = event.getStr("event");

                            if ("message".equals(eventType)) {
                                String answer = event.getStr("answer");
                                if (answer != null) {
                                    currentSentence.append(answer);
                                    onTextChunk.accept(answer);

                                    // 检查是否包含句子结束符
                                    String sentenceText = currentSentence.toString();
                                    if (sentenceText.matches(".*[。！？.!?]\\s*$")) {
                                        // 发现句子结束，触发回调
                                        onSentence.onSentence(sentenceText.trim(), newConversationId, false);
                                        currentSentence.setLength(0);
                                    }
                                }
                            } else if ("message_end".equals(eventType)) {
                                newConversationId = event.getStr("conversation_id");

                                // 处理最后剩余的文本（如果有）
                                if (currentSentence.length() > 0) {
                                    onSentence.onSentence(currentSentence.toString().trim(), newConversationId, true);
                                } else {
                                    // 没有剩余文本，直接标记完成
                                    onSentence.onSentence("", newConversationId, true);
                                }
                            } else if ("error".equals(eventType)) {
                                String errorMessage = event.getStr("message");
                                log.error("Dify API 返回错误: {}", errorMessage);
                                throw new RuntimeException("Dify API 错误: " + errorMessage);
                            }
                        } catch (Exception e) {
                            log.warn("解析 SSE 事件失败: {}", line, e);
                        }
                    }
                }
            }

        } catch (Exception e) {
            log.error("流式调用 Dify 工作流失败", e);
            throw new RuntimeException("AI 服务调用失败", e);
        }
    }
}
