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.domain.CcLlmKb;
import com.ruoyi.aicall.llm.AbstractLlmCapability;
import com.ruoyi.aicall.llm.model.LlmAccount;
import com.ruoyi.aicall.model.ChatRequest;
import com.ruoyi.aicall.service.ICcLlmKbService;
import com.ruoyi.common.utils.ExceptionUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.UuidGenerator;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okio.BufferedSource;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class DeepSeekChat extends AbstractLlmCapability {
    @Override
    public String getIntentionByTips(CcLlmAgentAccount ccLlmAgentAccount, JSONArray dialogueContents) {
        try {
            log.info("进入DeepSeekChat处理逻辑");
            // 构造请求体
            JSONObject params = new JSONObject();
            params.put("model", ((LlmAccount)getAccount()).getModelName());
            params.put("enable_thinking", false);
            JSONArray messages = new JSONArray();
            JSONObject message1 = new JSONObject();
            message1.put("role", "system");
            message1.put("content", ccLlmAgentAccount.getIntentionTips());
            messages.add(message1);
            JSONObject message2 = new JSONObject();
            message2.put("role", "user");
            message2.put("content", JSONObject.toJSONString(dialogueContents));
            messages.add(message2);
            params.put("messages", messages);

            RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8"), JSONObject.toJSONString(params));
            Request request = new Request.Builder()
                    .post(requestBody)
                    .header("Authorization", "Bearer " + ((LlmAccount)getAccount()).getApiKey())
                    .header("Content-Type", "application/json")
                    .url(getAccount().serverUrl).build();

            Response response = null;
            try {
                response = CLIENT.newCall(request).execute();
                String responseBody = response.body().string();
                log.info("Response: " + responseBody);
                if (response.isSuccessful() && response.body() != null) {
                    return JSONObject.parseObject(responseBody).getJSONArray("choices").getJSONObject(0).getJSONObject("message").getString("content");
                } else {
                    log.error("Request failed: " + response.code());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";

        } catch (Exception e) {
            log.error("DeepSeekChat处理客户意向异常" + ExceptionUtil.getExceptionMessage(e));
        }
        return null;
    }

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

        String requestId = chatRequest.getRequestId();
        String llmTips = ((LlmAccount) getAccount()).getLlmTips();
        Long catId = llmAccountInfo.kbCatId;
        String topicsVar = "${kbTopicList}";
        if(catId != -1) {
            if (llmTips.contains(topicsVar)) {
                List<CcLlmKb> kbList = SpringUtils.getBean(ICcLlmKbService.class).selectCcLlmKbList(new CcLlmKb().setCatId(catId));
                StringBuilder topics = new StringBuilder();
                for (CcLlmKb llmKb : kbList) {
                    topics.append("*").append(llmKb.getTitle()).append("\r\n");
                }
                topics.append("\r\n");
                llmTips = llmTips.replace(topicsVar, topics.toString());
                log.info("{} topic list: {}", requestId, topics.toString());
            } else {
                log.warn("{} {} tag not found, the knowledge base function will be unavailable. ", requestId, topicsVar);
            }
        }else {
            log.warn("{} The current model {} doesn’t have a knowledge base linked to it. ", requestId, ((LlmAccount) getAccount()).getModelName());
        }

        String tips = llmTips  + "\r\n\r\n" + ((LlmAccount) getAccount()).getFaqContext();

        JSONObject requestBody = new JSONObject();
        requestBody.put("model", ((LlmAccount)getAccount()).getModelName());
        requestBody.put("stream", true);
        JSONArray messagesArray = new JSONArray();
        JSONObject systemMessage = new JSONObject();
        systemMessage.put("role",  "system");
        systemMessage.put("content", tips);
        systemMessage.put("content_type", "text");
        messagesArray.add(systemMessage);
        if (CollectionUtils.isEmpty(chatRequest.getMessages())) {
            chatRequest.setMessages(new ArrayList<>());
        }
        JSONObject userMessage = new JSONObject();
        userMessage.put("role",  "user");
        userMessage.put("content", chatRequest.getQuestion());
        userMessage.put("content_type", "text");
        chatRequest.getMessages().add(userMessage);
        messagesArray.addAll(chatRequest.getMessages());
        requestBody.put("messages", messagesArray);

        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("Model 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 ;
                }
            }

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

            while (!source.exhausted()) {
                String line = source.readUtf8Line();
                if (line != null && line.startsWith("data: ")) {
                    String jsonData = line.substring(6).trim(); // 去掉 "data: " 前缀
                    if (jsonData.equals("[DONE]")) {
                        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);
                        rsponseData.put("messages", chatRequest.getMessages());
                        rsponseData.put("msgType", "message");
                        log.info(JSONObject.toJSONString(rsponseData));
                        emitter.send(SseEmitter.event()
                                .name("message")
                                .data(JSONObject.toJSONString(rsponseData)));
                        break; // 流式响应结束
                    }

                    JSONObject jsonResponse = JSON.parseObject(jsonData);
                    JSONObject message = jsonResponse.getJSONArray("choices")
                            .getJSONObject(0)
                            .getJSONObject("delta"); // 注意：流式响应中消息在 "delta" 字段中

                    if (message.containsKey("content")) {
                        String speechContent = message.getString("content");
                        responseBuilder.append(speechContent);
                        JSONObject rsponseData = new JSONObject();
                        rsponseData.put("requestId", requestId);
                        rsponseData.put("code", "200");
                        rsponseData.put("content", speechContent);
                        rsponseData.put("messages", chatRequest.getMessages());
                        rsponseData.put("msgType", "streamMsgSlice");
                        log.info(JSONObject.toJSONString(rsponseData));
                        emitter.send(SseEmitter.event()
                                .name("streamMsgSlice")
                                .data(JSONObject.toJSONString(rsponseData)));

                    }
                }
            }
        }
    }
}
