package com.usky.ai.controller.web;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.usky.ai.mapper.AiQuestionMapper;
import com.usky.ai.mapper.AiSessionMapper;
import com.usky.ai.domain.AiQuestion;
import com.usky.ai.domain.AiQuestionItem;
import com.usky.ai.domain.AiSession;
import com.usky.ai.service.vo.AiStreamOutputVO;
import com.usky.common.security.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/ai")
public class AiChatController {

    @Value("${ai.api.key}")
    private String apiKey;

    @Value("${airole}")
    private String aiRole;

    @Value("${aliTyqw.model}")
    private String tyqwModel;

    @Value("${aliDpsk.model}")
    private String dpskModel;

    @Value("${ai.historyLimit}")
    private int Limit;

    @Value("${ai.millis}")
    private int millis;

    @Resource
    private Generation generation;

    @Autowired
    private AiQuestionMapper aiQuestionMapper;

    @Autowired
    private AiSessionMapper aiSessionMapper;

    private final ObjectMapper objectMapper = new ObjectMapper();

    // 阿里百炼通义千问大模型（修改后）
    @PostMapping(value = "/aliTyqw", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public ResponseEntity<StreamingResponseBody> send1(@RequestBody JSONObject object) throws NoApiKeyException, InputRequiredException {
        // 获取当前登录用户的信息
        Long userId = SecurityUtils.getUserId();
        String userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
        String sessionId = null;
        String content = object.get("content").toString();

        // 如果没有传入 sessionId，则创建一个新的会话ID
        if (object.containsKey("sessionId")) {
            sessionId = object.get("sessionId").toString();
        } else {
            sessionId = java.util.UUID.randomUUID().toString();
        }

        // 解析 JSON 并提取 "content" 字段的值
        String questionText = content;

        // 检查是否已经存在相同的 sessionId
        boolean exists = aiSessionMapper.existsBySessionId(sessionId);

        if (!exists) {
            // 创建新的 AiSession 实体并存入数据库
            AiSession aiSession = new AiSession();
            aiSession.setSessionId(sessionId);
            aiSession.setUserId(userId);
            aiSession.setUserName(userName);
            aiSession.setQuestion(questionText);
            aiSession.setAskTime(LocalDateTime.now());
            aiSessionMapper.save(aiSession);
        }

        // 构建消息列表，包含角色定义、历史对话记录和用户新消息
        List<Message> messages = new ArrayList<>();

        // 插入角色定义（在对话历史的开头）
        Message roleDefinition = Message.builder()
                .role(Role.SYSTEM.getValue()) // 使用系统角色
                .content(aiRole) // 定义角色的行为和风格
                .build();
        messages.add(roleDefinition); // 将角色定义插入到对话历史的开头

        // 从数据库中获取历史对话记录
        List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);

        // 如果历史记录超过限制，则只取最近的记录
        if (questions.size() > Limit) {
            questions = questions.subList(questions.size() - Limit, questions.size());
        }

        // 将历史对话记录转换为 AiQuestionItem 列表
        List<AiQuestionItem> itemList = new ArrayList<>();
        for (AiQuestion question : questions) {
            AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
            userItem.setId(question.getId());
            userItem.setSessionId(question.getSessionId());
            userItem.setUserId(question.getUserId());
            userItem.setUserName(question.getUserName());
            userItem.setAskTime(question.getAskTime());

            AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
            assistantItem.setId(question.getId());
            assistantItem.setSessionId(question.getSessionId());
            assistantItem.setUserId(question.getUserId());
            assistantItem.setUserName(question.getUserName());
            assistantItem.setAskTime(question.getAskTime());

            itemList.add(userItem);
            itemList.add(assistantItem);
        }

        // 将 AiQuestionItem 列表转换为消息列表
        for (AiQuestionItem item : itemList) {
            Message message = Message.builder()
                    .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
                    .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
                    .build();
            messages.add(message);
        }

        // 添加用户的新消息
        Message userMessage = Message.builder()
                .role(Role.USER.getValue())
                .content(questionText) // 使用提取的文本
                .build();
        messages.add(userMessage);

        // 构建模型调用参数
        GenerationParam param = GenerationParam.builder()
                .model(tyqwModel)
                .messages(messages)
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .topP(0.8)
                .apiKey(apiKey)
                .incrementalOutput(true) // 开启增量输出
                .enableSearch(true)  // 联网搜索
                .build();

        String finalSessionId = sessionId;
        StringBuilder completeAnswer = new StringBuilder(); // 用于收集完整的回答内容
        return ResponseEntity.ok()
                .contentType(MediaType.TEXT_EVENT_STREAM)
                .body(outputStream -> {
                    try {
// 调用流式接口
                        generation.streamCall(param).blockingForEach(chunk -> {
                            try {
                                // 获取每次生成的内容
                                String partialAnswer = chunk.getOutput().getChoices().get(0).getMessage().getContent();

                                // 检查内容是否为空，如果为空则跳过
                                if (partialAnswer == null || partialAnswer.trim().isEmpty()) {
                                    return; // 如果内容为空，直接返回，不进行后续操作
                                }

                                // 构建输出对象
                                AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
                                aiStreamOutputVO.setSessionId(finalSessionId);
                                aiStreamOutputVO.setReasoningContent(partialAnswer);

                                // 转换为 JSON 字符串
                                String newString = objectMapper.writeValueAsString(aiStreamOutputVO);

                                // 写入输出流
                                outputStream.write(("data: " + newString + "\n\n").getBytes(StandardCharsets.UTF_8));
                                outputStream.flush(); // 确保立即发送到前端

                                // 累加到完整回答内容中
                                completeAnswer.append(partialAnswer);

                                // 添加延迟
                                try {
                                    Thread.sleep(millis); // 延迟*毫秒
                                } catch (InterruptedException e) {
                                    Thread.currentThread().interrupt();
                                    log.error("Thread interrupted", e);
                                }

                            } catch (Exception e) {
                                log.error("Error processing chunk", e);
                                outputStream.write(("data: Error processing chunk\n\n").getBytes(StandardCharsets.UTF_8));
                                outputStream.flush();
                            }
                        });

                        // 流式接口调用完成后，将完整回答存入数据库
                        AiQuestion aiQuestion = new AiQuestion();
                        aiQuestion.setModel(tyqwModel);
                        aiQuestion.setSessionId(finalSessionId);
                        aiQuestion.setUserId(userId);
                        aiQuestion.setUserName(userName);
                        aiQuestion.setQuestion(questionText);
                        aiQuestion.setAnswer(completeAnswer.toString());
                        aiQuestion.setAskTime(LocalDateTime.now());
                        aiQuestionMapper.save(aiQuestion);

                    } catch (ApiException e) {
                        log.error("Error processing request", e);
                        outputStream.write(("data: Error processing request\n\n").getBytes(StandardCharsets.UTF_8));
                        outputStream.flush();
                    } catch (NoApiKeyException | InputRequiredException e) {
                        throw new RuntimeException(e);
                    }
                });
    }

    // 阿里百炼DeepSeek大模型
    @PostMapping(value = "/aliDeepSeek", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public ResponseEntity<StreamingResponseBody> send2(@RequestBody JSONObject object )throws NoApiKeyException, InputRequiredException {
        // 获取当前登录用户的信息
        Long userId = SecurityUtils.getUserId();
        String userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
        String sessionId = null;
        String content = object.get("content").toString();

        // 如果没有传入 sessionId，则创建一个新的会话ID
        if (object.containsKey("sessionId")) {
            sessionId = object.get("sessionId").toString();
        } else {
            sessionId = java.util.UUID.randomUUID().toString();
        }

        // 解析 JSON 并提取 "content" 字段的值
        String questionText = content;

        // 检查是否已经存在相同的 sessionId
        boolean exists = aiSessionMapper.existsBySessionId(sessionId);

        if (!exists) {
            // 创建新的 AiSession 实体并存入数据库
            AiSession aiSession = new AiSession();
            aiSession.setSessionId(sessionId);
            aiSession.setUserId(userId);
            aiSession.setUserName(userName);
            aiSession.setQuestion(questionText);
            aiSession.setAskTime(LocalDateTime.now());
            aiSessionMapper.save(aiSession);
        }

        // 构建消息列表，包含角色定义、历史对话记录和用户新消息
        List<Message> messages = new ArrayList<>();

        // 插入角色定义（在对话历史的开头）
        Message roleDefinition = Message.builder()
                .role(Role.SYSTEM.getValue()) // 使用系统角色
                .content(aiRole) // 定义角色的行为和风格
                .build();
        messages.add(roleDefinition); // 将角色定义插入到对话历史的开头

        // 从数据库中获取历史对话记录
        List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);

        // 如果历史记录超过限制，则只取最近的记录
        if (questions.size() > Limit) {
            questions = questions.subList(questions.size() - Limit, questions.size());
        }

        // 将历史对话记录转换为 AiQuestionItem 列表
        List<AiQuestionItem> itemList = new ArrayList<>();
        for (AiQuestion question : questions) {
            AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
            userItem.setId(question.getId());
            userItem.setSessionId(question.getSessionId());
            userItem.setUserId(question.getUserId());
            userItem.setUserName(question.getUserName());
            userItem.setAskTime(question.getAskTime());

            AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
            assistantItem.setId(question.getId());
            assistantItem.setSessionId(question.getSessionId());
            assistantItem.setUserId(question.getUserId());
            assistantItem.setUserName(question.getUserName());
            assistantItem.setAskTime(question.getAskTime());

            itemList.add(userItem);
            itemList.add(assistantItem);
        }

        // 将 AiQuestionItem 列表转换为消息列表
        for (AiQuestionItem item : itemList) {
            Message message = Message.builder()
                    .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
                    .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
                    .build();
            messages.add(message);
        }

        // 添加用户的新消息
        Message userMessage = Message.builder()
                .role(Role.USER.getValue())
                .content(questionText) // 使用提取的文本
                .build();
        messages.add(userMessage);

        // 构建模型调用参数
        GenerationParam param = GenerationParam.builder()
                .model(dpskModel)
                .messages(messages)
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .apiKey(apiKey)
                .incrementalOutput(true) // 开启增量输出[^1^]
                .build();

        String finalSessionId = sessionId;
        StringBuilder completeAnswer = new StringBuilder(); // 用于收集完整的回答内容
        return ResponseEntity.ok()
                .contentType(MediaType.TEXT_EVENT_STREAM)
                .body(outputStream -> {
                    try {
                        // 调用流式接口
                        generation.streamCall(param).blockingForEach(chunk -> {
                            try {
                                // 获取每次生成的内容
                                String partialAnswer = chunk.getOutput().getChoices().get(0).getMessage().getContent();

                                // 检查内容是否为空，如果为空则跳过
                                if (partialAnswer == null || partialAnswer.trim().isEmpty()) {
                                    return; // 如果内容为空，直接返回，不进行后续操作
                                }

                                // 构建输出对象
                                AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
                                aiStreamOutputVO.setSessionId(finalSessionId);
                                aiStreamOutputVO.setReasoningContent(partialAnswer);

                                // 转换为 JSON 字符串
                                String newString = objectMapper.writeValueAsString(aiStreamOutputVO);

                                // 写入输出流
                                outputStream.write(("data: " + newString + "\n\n").getBytes(StandardCharsets.UTF_8));
                                outputStream.flush(); // 确保立即发送到前端

                                // 累加到完整回答内容中
                                completeAnswer.append(partialAnswer);

                                // 添加延迟
                                try {
                                    Thread.sleep(millis); // 延迟*毫秒
                                } catch (InterruptedException e) {
                                    Thread.currentThread().interrupt();
                                    log.error("Thread interrupted", e);
                                }

                            } catch (Exception e) {
                                log.error("Error processing chunk", e);
                                outputStream.write(("data: Error processing chunk\n\n").getBytes(StandardCharsets.UTF_8));
                                outputStream.flush();
                            }
                        });

                        // 流式接口调用完成后，将完整回答存入数据库
                        AiQuestion aiQuestion = new AiQuestion();
                        aiQuestion.setModel(dpskModel);
                        aiQuestion.setSessionId(finalSessionId);
                        aiQuestion.setUserId(userId);
                        aiQuestion.setUserName(userName);
                        aiQuestion.setQuestion(questionText);
                        aiQuestion.setAnswer(completeAnswer.toString());
                        aiQuestion.setAskTime(LocalDateTime.now());
                        aiQuestionMapper.save(aiQuestion);

                    } catch (ApiException e) {
                        log.error("Error processing request", e);
                        outputStream.write(("data: Error processing request\n\n").getBytes(StandardCharsets.UTF_8));
                        outputStream.flush();
                    } catch (NoApiKeyException | InputRequiredException e) {
                        throw new RuntimeException(e);
                    }
                });
    }

    @PostMapping(value = "/aliTyqw-test")
    public ResponseEntity<AiStreamOutputVO> send3(@RequestBody JSONObject object) throws NoApiKeyException, InputRequiredException {
        // 获取当前登录用户的信息
        Long userId = SecurityUtils.getUserId();
        String userName = SecurityUtils.getLoginUser().getSysUser().getNickName();
        String sessionId = null;
        String content = object.get("content").toString();

        // 如果没有传入 sessionId，则创建一个新的会话ID
        if (object.containsKey("sessionId")) {
            sessionId = object.get("sessionId").toString();
        } else {
            sessionId = java.util.UUID.randomUUID().toString();
        }

        // 解析 JSON 并提取 "content" 字段的值
        String questionText = content;

        // 检查是否已经存在相同的 sessionId
        boolean exists = aiSessionMapper.existsBySessionId(sessionId);

        if (!exists) {
            // 创建新的 AiSession 实体并存入数据库
            AiSession aiSession = new AiSession();
            aiSession.setSessionId(sessionId);
            aiSession.setUserId(userId);
            aiSession.setUserName(userName);
            aiSession.setQuestion(questionText);
            aiSession.setAskTime(LocalDateTime.now());
            aiSessionMapper.save(aiSession);
        }

        // 构建消息列表，包含角色定义、历史对话记录和用户新消息
        List<Message> messages = new ArrayList<>();

        // 插入角色定义（在对话历史的开头）
        Message roleDefinition = Message.builder()
                .role(Role.SYSTEM.getValue()) // 使用系统角色
                .content(aiRole) // 定义角色的行为和风格
                .build();
        messages.add(roleDefinition); // 将角色定义插入到对话历史的开头

        // 从数据库中获取历史对话记录
        List<AiQuestion> questions = aiQuestionMapper.findQuestionsBySessionId(sessionId);

        // 如果历史记录超过限制，则只取最近的记录
        if (questions.size() > Limit) {
            questions = questions.subList(questions.size() - Limit, questions.size());
        }

        // 将历史对话记录转换为 AiQuestionItem 列表
        List<AiQuestionItem> itemList = new ArrayList<>();
        for (AiQuestion question : questions) {
            AiQuestionItem userItem = new AiQuestionItem("user", question.getQuestion());
            userItem.setId(question.getId());
            userItem.setSessionId(question.getSessionId());
            userItem.setUserId(question.getUserId());
            userItem.setUserName(question.getUserName());
            userItem.setAskTime(question.getAskTime());

            AiQuestionItem assistantItem = new AiQuestionItem("assistant", question.getAnswer());
            assistantItem.setId(question.getId());
            assistantItem.setSessionId(question.getSessionId());
            assistantItem.setUserId(question.getUserId());
            assistantItem.setUserName(question.getUserName());
            assistantItem.setAskTime(question.getAskTime());

            itemList.add(userItem);
            itemList.add(assistantItem);
        }

        // 将 AiQuestionItem 列表转换为消息列表
        for (AiQuestionItem item : itemList) {
            Message message = Message.builder()
                    .role(item.getRole().equals("user") ? Role.USER.getValue() : Role.ASSISTANT.getValue())
                    .content(item.getContent() != null ? item.getContent() : item.getReasoningContent())
                    .build();
            messages.add(message);
        }

        // 添加用户的新消息
        Message userMessage = Message.builder()
                .role(Role.USER.getValue())
                .content(questionText) // 使用提取的文本
                .build();
        messages.add(userMessage);

        // 构建模型调用参数
        GenerationParam param = GenerationParam.builder()
                .model(tyqwModel)
                .messages(messages)
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .topP(0.8)
                .apiKey(apiKey)
                .incrementalOutput(false) // 关闭增量输出
                .enableSearch(true)  // 联网搜索
                .build();

        try {
            // 调用非流式接口
            String completeAnswer = generation.call(param).getOutput().getChoices().get(0).getMessage().getContent();

            // 将完整回答存入数据库
            AiQuestion aiQuestion = new AiQuestion();
            aiQuestion.setModel(tyqwModel);
            aiQuestion.setSessionId(sessionId);
            aiQuestion.setUserId(userId);
            aiQuestion.setUserName(userName);
            aiQuestion.setQuestion(questionText);
            aiQuestion.setAnswer(completeAnswer);
            aiQuestion.setAskTime(LocalDateTime.now());
            aiQuestionMapper.save(aiQuestion);

            // 构建返回对象
            AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
            aiStreamOutputVO.setSessionId(sessionId);
            aiStreamOutputVO.setReasoningContent(completeAnswer);

            // 返回完整回答给前端
            return ResponseEntity.ok(aiStreamOutputVO);
        } catch (ApiException e) {
            log.error("Error processing request", e);

            // 构建错误返回对象
            AiStreamOutputVO aiStreamOutputVO = new AiStreamOutputVO();
            aiStreamOutputVO.setSessionId(sessionId);
            aiStreamOutputVO.setReasoningContent("Error processing request");

            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(aiStreamOutputVO);
        } catch (NoApiKeyException | InputRequiredException e) {
            throw new RuntimeException(e);
        }
    }
}
