package cn.com.poc.agent_application.utils;

import cn.com.poc.agent_application.entity.CheckPluginUseEntity;
import cn.com.poc.agent_application.entity.Variable;
import cn.com.poc.common.constant.CommonConstant;
import cn.com.poc.common.utils.DocumentLoad;
import cn.com.poc.common.utils.JsonUtils;
import cn.com.poc.common.utils.SpringUtils;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Message;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.MultiContent;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Tool;
import cn.com.poc.thirdparty.resource.demand.ai.entity.function.FunctionCallResult;
import cn.com.poc.thirdparty.resource.demand.ai.function.LargeModelFunctionEnum;
import cn.com.poc.thirdparty.resource.demand.ai.function.memory_variable_writer.MemoryVariableWriter;
import cn.com.poc.thirdparty.service.LLMService;
import cn.com.yict.framemax.core.i18n.I18nMessageException;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.*;

/**
 * @author alex.yao
 * @description agent应用配置工具类
 */
public class AgentApplicationTools {

    /**
     * 构造Agent应用 函数配置
     *
     * @param variableStructures 记忆变量
     * @param isLongMemory       是否开启长期记忆
     * @param identifier         标识符
     * @param agentId            应用id
     * @param unitIds            插件id
     * @param isDocumentParsing  是否开启文档解析
     * @return
     */
    public static List<Tool> buildFunctionConfig(List<Variable> variableStructures, String isLongMemory, String identifier, String agentId, String[] unitIds, String isDocumentParsing) {
        List<Tool> tools = new ArrayList<>();
        //开启对话变量
        if (CollectionUtils.isNotEmpty(variableStructures)) {
            String functionName = LargeModelFunctionEnum.memory_variable_writer.name();
            String llmConfig = LargeModelFunctionEnum.valueOf(functionName).getFunction().getLLMConfig(variableStructures).get(0);
            Tool tool = JsonUtils.deSerialize(llmConfig, Tool.class);
            tools.add(tool);

            //初始化变量函数
            Map<Object, Object> map = MemoryVariableWriter.get(identifier(identifier, agentId));
            if (MapUtils.isEmpty(map)) {
                List<Variable> variableStructure = variableStructures;
                for (Variable variable : variableStructure) {
                    String key = variable.getKey();
                    String variableDefault = variable.getVariableDefault();
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("key", key);
                    jsonObject.put("value", variableDefault);
                    LargeModelFunctionEnum.valueOf(functionName).getFunction().doFunction(jsonObject.toJSONString(), identifier(identifier, agentId));
                }
            }
        }
        //开启长期记忆
        if (CommonConstant.YOrN.Y.equals(isLongMemory)) {
            String functionName = LargeModelFunctionEnum.set_long_memory.name();
            String llmConfig = LargeModelFunctionEnum.valueOf(functionName).getFunction().getLLMConfig().get(0);
            Tool tool = JsonUtils.deSerialize(llmConfig, Tool.class);
            tools.add(tool);
        }

        //开启文档解析-文档理解
        if (CommonConstant.YOrN.Y.equals(isDocumentParsing)) {
            String functionName = LargeModelFunctionEnum.document_understanding.name();
            String llmConfig = LargeModelFunctionEnum.valueOf(functionName).getFunction().getLLMConfig().get(0);
            Tool tool = JsonUtils.deSerialize(llmConfig, Tool.class);
            tools.add(tool);
        }

        //初始化插件函数
        if (ArrayUtils.isNotEmpty(unitIds)) {
            for (String unitId : unitIds) {
                LargeModelFunctionEnum modelFunctionEnum = LargeModelFunctionEnum.getFunction(unitId);
                if (modelFunctionEnum == null) {
                    continue;
                }
                String llmConfig = modelFunctionEnum.getFunction().getLLMConfig().get(0);
                Tool tool = JsonUtils.deSerialize(llmConfig, Tool.class);
                tools.add(tool);
            }
        }
        return tools;
    }

    /**
     * 创建会话唯一标识符
     *
     * @param dialogueId 对话ID
     * @param agentId    应用ID
     * @return
     */
    public static String identifier(String dialogueId, String agentId) {
        return dialogueId + ":" + agentId;
    }

    /**
     * 检查对话文件内容是否为空
     *
     * @throws I18nMessageException 文件内容为空时抛出异常
     */
    public static void checkDialogueContentIsEmpty(List<String> fileUrls) {
        // 判断文件是否为空，如果不为空
        if (CollectionUtils.isNotEmpty(fileUrls)) {
            for (String fileUrl : fileUrls) {
                File file = DocumentLoad.downloadURLDocument(fileUrl);
                String documentContent = DocumentLoad.documentToText(file);
                if (StringUtils.isBlank(documentContent)) {
                    throw new I18nMessageException("exception/file.content.empty");
                }
            }
        }
    }

    /**
     * 获取Message对话的图片地址
     *
     * @param messages 对话
     * @return 返回图片地址列表，若无则返回null
     */
    public static List<String> getMessageImageUrl(List<Message> messages) {
        List<String> imageUrls = null;
        Message mess = messages.get(messages.size() - 1);
        if (!(mess.getContent() instanceof String) && ((LinkedHashMap) ((ArrayList) mess.getContent()).get(0)).containsKey("image_url")) {
            LinkedHashMap map = ((LinkedHashMap) ((ArrayList) mess.getContent()).get(0));
            MultiContent multiContent = JSONObject.parseObject(JsonUtils.serialize(map), MultiContent.class);
            if (ObjectUtil.isNotNull(multiContent.getImageUrl()) && StringUtils.isNotBlank(multiContent.getImageUrl().getUrl())) {
                imageUrls = new ArrayList<>();
                imageUrls.add(multiContent.getImageUrl().getUrl());
            }
        }
        return imageUrls;
    }

    /**
     * 构建ImageUrls
     */
    public static List<String> buildImageUrls(String imageUrl) {
        List<String> imageUrls = null;
        if (StringUtils.isNotBlank(imageUrl)) {
            imageUrls = new ArrayList<>();
            imageUrls.add(imageUrl);
        }
        return imageUrls;
    }

    /**
     * 判断将会调用的插件-用于扣减积分
     */
    public static CheckPluginUseEntity checkPluginUse(List<Message> messages, List<Tool> tools, List<String> fileUrls, List<String> imageUrls) {
        CheckPluginUseEntity checkPluginUseEntity = new CheckPluginUseEntity();
        if (CollectionUtils.isEmpty(messages) || CollectionUtils.isEmpty(tools)) {
            return checkPluginUseEntity;
        }
        LLMService llmService = SpringUtils.getBean(LLMService.class);
        Object content = messages.get(messages.size() - 1).getContent();
        String query;
        if (content instanceof List) {
            query = ((List<HashMap>) content).get(0).get("text").toString();
        } else {
            query = content.toString();
        }
        query = "用户输入:" + query + "\n";
        if (CollectionUtils.isNotEmpty(fileUrls)) {
            query = query + "用户上传文件地址:" + JsonUtils.serialize(fileUrls) + "\n";
        }
        if (CollectionUtils.isNotEmpty(imageUrls)) {
            query = query + "用户上传图片地址:" + JsonUtils.serialize(imageUrls);
        }

        List<Tool> deductionTools = new ArrayList<>();
        FunctionCallResult functionCallResult = llmService.functionCall(query, tools.toArray(new Tool[0]));
        if (functionCallResult != null && functionCallResult.isNeed()) {
            for (Tool tool : tools) {
                if (tool.getFunction().getName().equals(functionCallResult.getFunctionCall().getName())) {
                    deductionTools.add(tool);
                    break;
                }
            }
        }
        checkPluginUseEntity.setDeductionTools(deductionTools);
        checkPluginUseEntity.setFunctionCallResult(functionCallResult);
        return checkPluginUseEntity;
    }

}
