package com.yanzhu.module.ai.service.write;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.yanzhu.framework.dict.core.DictFrameworkUtils;
import com.yanzhu.module.ai.enums.model.AiModelTypeEnum;
import com.yanzhu.module.ai.enums.model.AiPlatformEnum;
import com.yanzhu.module.ai.util.AiUtils;
import com.yanzhu.framework.common.pojo.CommonResult;
import com.yanzhu.framework.common.pojo.PageResult;
import com.yanzhu.framework.common.util.object.BeanUtils;
import com.yanzhu.framework.tenant.core.util.TenantUtils;
import com.yanzhu.module.ai.controller.admin.write.vo.AiWriteGenerateReqVO;
import com.yanzhu.module.ai.controller.admin.write.vo.AiWritePageReqVO;
import com.yanzhu.module.ai.dal.dataobject.model.AiChatRoleDO;
import com.yanzhu.module.ai.dal.dataobject.model.AiModelDO;
import com.yanzhu.module.ai.dal.dataobject.write.AiWriteDO;
import com.yanzhu.module.ai.dal.mysql.write.AiWriteMapper;
import com.yanzhu.module.ai.enums.AiChatRoleEnum;
import com.yanzhu.module.ai.enums.DictTypeConstants;
import com.yanzhu.module.ai.enums.ErrorCodeConstants;
import com.yanzhu.module.ai.enums.write.AiWriteTypeEnum;
import com.yanzhu.module.ai.service.model.AiChatRoleService;
import com.yanzhu.module.ai.service.model.AiModelService;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.output.Response;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import java.util.List;
import dev.langchain4j.data.message.AiMessage;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.yanzhu.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yanzhu.framework.common.pojo.CommonResult.error;
import static com.yanzhu.framework.common.pojo.CommonResult.success;
import static com.yanzhu.module.ai.enums.ErrorCodeConstants.*;

/**
 * AI 写作 Service 实现类
 *
 * @author xiaoxin
 */
@Service
@Slf4j
public class AiWriteServiceImpl implements AiWriteService {

    @Resource
    private AiModelService modalService;
    @Resource
    private AiChatRoleService chatRoleService;

    @Resource
    private AiWriteMapper writeMapper;

    @Override
    public Flux<CommonResult<String>> generateWriteContent(AiWriteGenerateReqVO generateReqVO, Long userId) {
        // 1 获取写作模型。尝试获取写作助手角色，没有则使用默认模型
        AiChatRoleDO writeRole = CollUtil.getFirst(
                chatRoleService.getChatRoleListByName(AiChatRoleEnum.AI_WRITE_ROLE.getName()));
        // 1.1 获取写作执行模型
        AiModelDO model = getModel(writeRole);
        // 1.2 获取角色设定消息
        String systemMessage = Objects.nonNull(writeRole) && StrUtil.isNotBlank(writeRole.getSystemMessage())
                ? writeRole.getSystemMessage() : AiChatRoleEnum.AI_WRITE_ROLE.getSystemMessage();
        // 1.3 校验平台
        AiPlatformEnum platform = AiPlatformEnum.validatePlatform(model.getPlatform());
        ChatLanguageModel chatModel = modalService.getChatModel(model.getId());

        // 2. 插入写作信息
        AiWriteDO writeDO = BeanUtils.toBean(generateReqVO, AiWriteDO.class, write -> write.setUserId(userId)
                        .setPlatform(platform.getPlatform()).setModelId(model.getId()).setModel(model.getModel()));
        writeMapper.insert(writeDO);

        // 3.1 构建消息，并进行调用
        List<ChatMessage> messages = buildMessages(generateReqVO, systemMessage);
        // 暂时注释掉流式调用，因为chatModel可能没有stream方法
        // 后续需要使用正确的方法调用
        // Flux<Response<AiMessage>> streamResponse = chatModel.stream(messages);

        // 3.2 暂时返回空的Flux
        return Flux.empty();
    }

    private AiModelDO getModel(AiChatRoleDO writeRole) {
        AiModelDO model = null;
        if (Objects.nonNull(writeRole) && Objects.nonNull(writeRole.getModelId())) {
            model = modalService.getModel(writeRole.getModelId());
        }
        if (model == null) {
            model = modalService.getRequiredDefaultModel(AiModelTypeEnum.CHAT.getType());
        }
        // 校验模型存在、且合法
        if (model == null) {
            throw exception(MODEL_NOT_EXISTS);
        }
        if (ObjUtil.notEqual(model.getType(), AiModelTypeEnum.CHAT.getType())) {
            throw exception(MODEL_USE_TYPE_ERROR);
        }
        return model;
    }



    private List<ChatMessage> buildMessages(AiWriteGenerateReqVO generateReqVO, String systemMessage) {
        List<ChatMessage> chatMessages = new ArrayList<>();
        if (StrUtil.isNotBlank(systemMessage)) {
            // 1.1 角色设定
            chatMessages.add(new SystemMessage(systemMessage));
        }
        // 1.2 用户输入
        chatMessages.add(new UserMessage(buildUserMessage(generateReqVO)));
        return chatMessages;
    }

    private String buildUserMessage(AiWriteGenerateReqVO generateReqVO) {
        String format = DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.AI_WRITE_FORMAT, generateReqVO.getFormat());
        String tone = DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.AI_WRITE_TONE, generateReqVO.getTone());
        String language = DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.AI_WRITE_LANGUAGE, generateReqVO.getLanguage());
        String length = DictFrameworkUtils.parseDictDataLabel(DictTypeConstants.AI_WRITE_LENGTH, generateReqVO.getLength());
        // 格式化 prompt
        String prompt = generateReqVO.getPrompt();
        if (Objects.equals(generateReqVO.getType(), AiWriteTypeEnum.WRITING.getType())) {
            return StrUtil.format(AiWriteTypeEnum.WRITING.getPrompt(), prompt, format, tone, language, length);
        } else {
            return StrUtil.format(AiWriteTypeEnum.REPLY.getPrompt(), generateReqVO.getOriginalContent(), prompt, format, tone, language, length);
        }
    }

    @Override
    public void deleteWrite(Long id) {
        // 校验存在
        validateWriteExists(id);
        // 删除
        writeMapper.deleteById(id);
    }

    private void validateWriteExists(Long id) {
        if (writeMapper.selectById(id) == null) {
            throw exception(WRITE_NOT_EXISTS);
        }
    }

    @Override
    public PageResult<AiWriteDO> getWritePage(AiWritePageReqVO pageReqVO) {
        return writeMapper.selectPage(pageReqVO);
    }

}
