package com.template.controller;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.template.annotation.PassToken;
import com.template.api.DeepseekControllerAPI;
import com.template.model.pojo.DeepSeekRequest;
import com.template.model.pojo.DeepSeekResponse;
import com.template.model.result.CommonResult;
import okhttp3.*;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

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

/**
 * @Author: xwt
 * @Date: 2025/2/20 星期四 9:16
 * @Description: com.template.controller
 * @Version: 1.0
 */
@RestController
public class DeepseekControl implements DeepseekControllerAPI {

    private Integer integerValue = -1;

    //windows本地化部署：https://blog.csdn.net/weixin_43025151/article/details/145392970
    //linux部署：https://blog.csdn.net/2302_80252080/article/details/145713651

    private final OkHttpClient client = new OkHttpClient.Builder()
            .readTimeout(6000, TimeUnit.SECONDS)
            .writeTimeout(6000, TimeUnit.SECONDS)
            .connectTimeout(6000, TimeUnit.SECONDS)
            .build();
    private static final String API_URL = "https://api.deepseek.com/chat/completions";
    private static final String API_KEY = "sk-7cace8abd0724c959dbea3aefae9fb96"; // 替换为你的 API Key
    private final RestTemplate restTemplate = new RestTemplate(); //用resttemplate构建请求


    //region 流式消息
    //deepseek-reasoner：深度模式
    //deepseek-chat：普通模式
    @Override
    @PassToken
    public SseEmitter askDeepSeek(String userMessage, String uniqueStr) throws IOException {
        SseEmitter emitter = new SseEmitter(); // 创建一个新的SseEmitter实例用于异步事件流传输。

        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "{\n  \"messages\": [\n   {\n      \"content\": \"从现在起你是南昌交通学院小助手，回答的时候请回答我校\",\n      \"role\": \"system\"\n ,\n \"name\": \"南昌交通学院\"\n    }\n,\n    {\n      \"content\": \"" + userMessage + "\",\n      \"role\": \"user\"\n ,\n \"name\": \"南昌交通学院\"\n}\n  ],\n  \"model\": \"deepseek-reasoner\",\n  \"frequency_penalty\": 0,\n  \"max_tokens\": 2048,\n  \"presence_penalty\": 0,\n  \"response_format\": {\n    \"type\": \"text\"\n  },\n  \"stop\": null,\n  \"stream\": true,\n  \"stream_options\": null,\n  \"temperature\": 1,\n  \"top_p\": 1,\n  \"tools\": null,\n  \"tool_choice\": \"none\",\n  \"logprobs\": false,\n  \"top_logprobs\": null\n}");
        Request request = new Request.Builder()
                .url("https://api.deepseek.com/chat/completions")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer " + API_KEY)
                .build();


        // 异步执行HTTP请求，并注册回调处理响应或错误。
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) { // 请求失败时调用此方法。
                handleError(emitter, e); // 调用handleError处理错误。
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException { // 请求成功时调用此方法。
                if (!response.isSuccessful()) { // 检查响应是否成功。
                    handleError(emitter, new IOException("Unexpected code " + response)); // 如果不成功，则处理错误。
                    return;
                }

                try (ResponseBody responseBody = response.body()) { // 获取响应体。
                    if (responseBody != null) { // 确保响应体非空。
                        processResponseStream(responseBody.byteStream(), emitter); // 处理响应流。
                    }
                } catch (Exception e) { // 捕获可能的异常。
                    handleError(emitter, e); // 出现异常时处理错误。
                }
            }
        });

        return emitter; // 返回SseEmitter实例，开始向客户端发送事件流。
    }

    private void processResponseStream(java.io.InputStream inputStream, SseEmitter emitter) {
        try {
            StringBuilder contentValue = new StringBuilder();
            byte[] buffer = new byte[2048]; // 创建一个1024字节的缓冲区。
            int bytesRead; // 存储每次读取的字节数。
            while ((bytesRead = inputStream.read(buffer)) != -1) { // 循环读取输入流直到结束。
                String data = new String(buffer, 0, bytesRead); // 将读取的字节转换为字符串。
                //System.out.println(data);
                // 假设每条消息是以换行符分隔的JSON对象。
                for (String line : data.split("\n")) { // 分割字符串，按行处理。
                    if (!line.trim().isEmpty()) { // 忽略空行。
                        emitter.send(SseEmitter.event().data(line)); // 发送每一行数据作为事件。
                        if (line.contains("data:")) {
                            String dealValue = line.trim().substring(5);
                            if (!dealValue.contains("[DONE]")) {
                                System.out.println("内容：" + dealValue);
                                ObjectMapper objectMapper = new ObjectMapper();
                                JsonNode jsonNode = objectMapper.readTree(dealValue);
                                String content = jsonNode.get("choices").get(0).get("delta").get("content").asText();
                                if (StringUtils.hasText(content.trim()) && !content.trim().equals("null")) {
                                    contentValue.append(content);
                                    System.out.print(content);
                                }
                            }
                        }
                    }
                }
            }
            System.out.println("最终内容：" + contentValue.toString());
            emitter.complete(); // 完成SseEmitter，表示所有数据已发送完毕。
        } catch (IOException e) { // 捕获可能的IO异常。
            handleError(emitter, e); // 出现异常时处理错误。
        }
    }

    private void handleError(SseEmitter emitter, Exception e) {
        try {
            emitter.send(SseEmitter.event().id("error").data(e.getMessage())); // 发送错误事件。
            emitter.completeWithError(e); // 完成SseEmitter，并附带错误。
        } catch (IOException ex) { // 捕获可能的IO异常。
            ex.printStackTrace(); // 打印堆栈跟踪。
        }
    }
    //endregion

    //region 普通模式
    @Override
    @PassToken
    public CommonResult askNDeepSeek(String userMessage) throws IOException {
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/json");
        headers.set("Authorization", "Bearer " + API_KEY);

        // 构建请求体
        DeepSeekRequest request = new DeepSeekRequest();
        request.setModel("deepseek-reasoner");//深度模式
        List<DeepSeekRequest.Message> lists = new ArrayList<>();
        lists.add(new DeepSeekRequest.Message("system", "我是南昌交通学院", "南昌交通学院"));
        lists.add(new DeepSeekRequest.Message("user", userMessage, "南昌交通学院"));
        request.setMessages(lists);

        // 构建请求
        HttpEntity<DeepSeekRequest> entity = new HttpEntity<>(request, headers);
        // 参数依次为：请求路径、请求方法、请求、返参格式
        ResponseEntity<DeepSeekResponse> response = restTemplate.exchange(
                API_URL, HttpMethod.POST, entity, DeepSeekResponse.class);

        // 解析响应
        if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
            return CommonResult.ok(response.getBody().getChoices().get(0).getMessage().getContent());
        } else {
            return CommonResult.fail("Failed to call DeepSeek API: " + response.getStatusCode());
        }
    }
    //endregion


}
