package cn.iocoder.yudao.module.llm.service.conversation;

import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.llm.dal.dataobject.basemodel.BaseModelDO;
import cn.iocoder.yudao.module.llm.service.basemodel.BaseModelService;
import cn.iocoder.yudao.module.llm.service.http.ModelService;
import cn.iocoder.yudao.module.llm.service.http.vo.ModelCompletionsReqVO;
import cn.iocoder.yudao.module.llm.service.http.vo.ModelCompletionsRespVO;
import com.alibaba.excel.util.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;

import cn.iocoder.yudao.module.llm.controller.admin.conversation.vo.*;
import cn.iocoder.yudao.module.llm.dal.dataobject.conversation.ConversationDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.llm.dal.mysql.conversation.ConversationMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.llm.enums.ErrorCodeConstants.*;

/**
 * 大模型对话记录 Service 实现类
 *
 * @author 华大大模型
 */
@Service
@Validated
public class ConversationServiceImpl implements ConversationService {

    @Resource
    private ConversationMapper conversationMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private ModelService modelService;
    @Resource
    private BaseModelService baseModelService;

    // 聊天会话历史记录缓存Key
    private final static String CHAT_HIStORY_REDIS_KEY = "llm:chat:history";
    // 聊天会话历史记录缓存时间
    private final static Long CHAT_HISTORY_REDIS_EXPIRE_SECONDS = 60 * 60 * 24L;

    @Override
    public Integer createConversation(ConversationSaveReqVO createReqVO) {
        // 插入
        ConversationDO conversation = BeanUtils.toBean(createReqVO, ConversationDO.class);
        conversationMapper.insert(conversation);
        // 返回
        return conversation.getId();
    }

    @Override
    public void updateConversation(ConversationSaveReqVO updateReqVO) {
        // 校验存在
        validateConversationExists(updateReqVO.getId());
        // 更新
        ConversationDO updateObj = BeanUtils.toBean(updateReqVO, ConversationDO.class);
        conversationMapper.updateById(updateObj);
    }

    @Override
    public void deleteConversation(Integer id) {
        // 校验存在
        validateConversationExists(id);
        // 删除
        conversationMapper.deleteById(id);
    }

    private void validateConversationExists(Integer id) {
        if (conversationMapper.selectById(id) == null) {
            throw exception(CONVERSATION_NOT_EXISTS);
        }
    }

    @Override
    public ConversationDO getConversation(Integer id) {
        return conversationMapper.selectById(id);
    }

    @Override
    public PageResult<ConversationDO> getConversationPage(ConversationPageReqVO pageReqVO) {
        return conversationMapper.selectPage(pageReqVO);
    }

    @Override
    public ChatRespVO chat(ChatReqVO chatReqVO) {
        if (StringUtils.isBlank(chatReqVO.getUuid())) {
            // 如果没有uuid，就生成一个
            chatReqVO.setUuid(UUID.randomUUID().toString());
        }
        String model = null;
        if (Objects.equals(1, chatReqVO.getModelType())) {
            // 预制模型
            BaseModelDO baseModelDO = baseModelService.getBaseModel(chatReqVO.getModelId());
            if (baseModelDO == null) {
                throw exception(BASE_MODEL_NOT_EXISTS);
            }
            model = baseModelDO.getModelName();
        }
        ModelCompletionsReqVO.ModelCompletionsMessage message = new ModelCompletionsReqVO.ModelCompletionsMessage();
        message.setRole("user");
        message.setContent(chatReqVO.getPrompt());
        // TODO: 聊天推理
        List<String> messageHistoryList = stringRedisTemplate.opsForList().range(CHAT_HIStORY_REDIS_KEY + ":" + chatReqVO.getUuid(), 0, -1);
        List<ModelCompletionsReqVO.ModelCompletionsMessage> messages = new ArrayList<>();
        if (messageHistoryList != null && !messageHistoryList.isEmpty()) {
            for (String messageHistory : messageHistoryList) {
                messages.add(JsonUtils.parseObject(messageHistory, ModelCompletionsReqVO.ModelCompletionsMessage.class));
            }
        }
        messages.add(message);
        ModelCompletionsReqVO modelCompletionsReqVO = new ModelCompletionsReqVO();
        modelCompletionsReqVO.setMessages(messages);
        modelCompletionsReqVO.setModel(model);
        ModelCompletionsRespVO modelCompletionsRespVO = modelService.modelCompletions(modelCompletionsReqVO);
        if (modelCompletionsRespVO == null) {
            throw exception(MODEL_COMPLETIONS_ERROR);
        }
        stringRedisTemplate.opsForList().rightPush(CHAT_HIStORY_REDIS_KEY + ":" + chatReqVO.getUuid(), JsonUtils.toJsonString(message));
        return null;
    }
}