package com.ruoyi.aicall.llm.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.aicall.domain.CcLlmAgentAccount;
import com.ruoyi.aicall.llm.AbstractLlmCapability;
import com.ruoyi.aicall.llm.model.LlmAccount;
import com.ruoyi.aicall.model.ChatRequest;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UuidGenerator;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.BufferedSource;
import org.apache.http.HttpStatus;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;

@Slf4j
public class Dify extends AbstractLlmCapability {
    @Override
    public String getIntentionByTips(CcLlmAgentAccount ccLlmAgentAccount, JSONArray dialogueContents) {
        String intentionTips = ccLlmAgentAccount.getIntentionTips();
        return null;
    }

    @Override
    public void getStreamingChatContent(SseEmitter emitter, ChatRequest chatRequest) throws IOException {

        String requestId = chatRequest.getRequestId();
        String question = chatRequest.getQuestion();
        String conversationId = chatRequest.getConversationId();

        JSONObject userMessage = new JSONObject();
        userMessage.put("role",  "user");
        userMessage.put("content",  question);
        userMessage.put("content_type", "text");
        chatRequest.getMessages().add(userMessage);

        JSONObject requestBody = new JSONObject();
        JSONObject inputs = new JSONObject();
        requestBody.put("inputs", inputs);
        requestBody.put("query", question);
        requestBody.put("response_mode", "streaming");
        if (!StringUtils.isEmpty(conversationId)) {
            requestBody.put("conversation_id", conversationId);
            log.info("{} set Dify chat_id = {}", requestId, conversationId);
        }
        requestBody.put("user", requestId);

        RequestBody body = RequestBody.create(
                MediaType.parse("application/json"),
                requestBody.toJSONString()
        );

        Request request = new Request.Builder()
                .url(getAccount().serverUrl)
                .post(body)
                .addHeader("Authorization", "Bearer " +  ((LlmAccount)getAccount()).getApiKey())
                .build();

        try (Response response = CLIENT.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                log.error("Dify api error: http-code={}, msg={}, url={}",
                        response.code(),
                        response.message(),
                        getAccount().serverUrl
                );
                if(response.code() == HttpStatus.SC_UNAUTHORIZED || response.code() >= HttpStatus.SC_INTERNAL_SERVER_ERROR) {
                    throw new IOException("Unexpected code " + response);
                }else{
                    return ;
                }
            }

            BufferedSource source = response.body().source();
            StringBuilder responseBuilder = new StringBuilder();

//   data: {"event": "message", "message_id": "5ad4cb98-f0c7-4085-b384-88c403be6290", "conversation_id": "45701982-8118-4bc5-8e9b-64562b4555f2", "answer": " I", "created_at": 1679586595}
            while (!source.exhausted()) {
                String line = source.readUtf8Line();
                if (line != null && line.startsWith("data: ")) {
                    String jsonData = line.substring(6).trim(); // 去掉 "data: " 前缀
                    JSONObject jsonResponse = JSON.parseObject(jsonData);
                    if ("message".equalsIgnoreCase(jsonResponse.getString("event"))) {
                        String conversation_id = jsonResponse.getString("conversation_id");
                        if (!StringUtils.isEmpty(conversation_id)) {
                            conversationId = conversation_id;
                            log.info("{} successfully get Dify chat_id = {}", requestId, conversationId);
                        }
                        String speechContent = jsonResponse.getString("answer");
                        if (StringUtils.isEmpty(speechContent)) {
                            continue;
                        }

                        if (!StringUtils.isEmpty(speechContent)) {

                            responseBuilder.append(speechContent);
                            JSONObject rsponseData = new JSONObject();
                            rsponseData.put("requestId", requestId);
                            rsponseData.put("code", "200");
                            rsponseData.put("content", speechContent);
                            chatRequest.setConversationId(conversationId);
                            rsponseData.put("messages", chatRequest.getMessages());
                            rsponseData.put("conversationId", chatRequest.getConversationId());
                            rsponseData.put("msgType", "streamMsgSlice");
                            log.info(JSONObject.toJSONString(rsponseData));
                            emitter.send(SseEmitter.event()
                                    .name("streamMsgSlice")
                                    .data(JSONObject.toJSONString(rsponseData)));

                        }
                    }
                }
            }


            JSONObject rsponseData = new JSONObject();
            rsponseData.put("requestId", requestId);
            rsponseData.put("code", "200");
            rsponseData.put("content", responseBuilder.toString());
            JSONObject assistantMessage = new JSONObject();
            assistantMessage.put("role",  "assistant");
            assistantMessage.put("content",  responseBuilder.toString());
            assistantMessage.put("content_type", "text");
            chatRequest.getMessages().add(assistantMessage);
            chatRequest.setConversationId(conversationId);
            rsponseData.put("messages", chatRequest.getMessages());
            rsponseData.put("conversationId", chatRequest.getConversationId());
            rsponseData.put("msgType", "message");
            log.info(JSONObject.toJSONString(rsponseData));
            emitter.send(SseEmitter.event()
                    .name("message")
                    .data(JSONObject.toJSONString(rsponseData)));
        }
    }
}
