package com.infoepoch.pms.agent.platform.agent.adapter.out.ai;

import com.alibaba.cloud.ai.graph.agent.Builder;
import com.alibaba.cloud.ai.graph.agent.ReactAgent;
import com.alibaba.cloud.ai.graph.agent.flow.agent.LlmRoutingAgent;
import com.alibaba.cloud.ai.graph.agent.hook.hip.HumanInTheLoopHook;
import com.alibaba.cloud.ai.graph.agent.hook.hip.ToolConfig;
import com.alibaba.cloud.ai.graph.agent.interceptor.Interceptor;
import com.alibaba.cloud.ai.graph.checkpoint.BaseCheckpointSaver;
import com.infoepoch.pms.agent.platform.agent.adapter.out.tool.ChatbotBuiltInToolRegistry;
import com.infoepoch.pms.agent.platform.agent.adapter.out.tool.SubmitTool;
import com.infoepoch.pms.agent.platform.agent.domain.Agent;
import com.infoepoch.pms.agent.platform.agent.domain.service.SystemPromptGenerator;
import com.infoepoch.pms.agent.platform.chatbot.domain.Chatbot;
import com.infoepoch.pms.agent.platform.model.application.ModelProvisionService;
import com.infoepoch.pms.agent.platform.shared.observation.ToolExecutionTraceBuffer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

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

/**
 * 动态聊天智能体构建器。
 * <p>
 * 每次请求时从数据库加载所有 enabled 智能体。
 * 存在业务子智能体时，使用 LlmRoutingAgent 以嵌套子图方式路由到对应子智能体；
 * 不存在业务子智能体时，直接返回通用 ReactAgent。
 * </p>
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicAgentBuilder {

    /**
     * 通用兜底助手名称。
     */
    private static final String GENERAL_ASSISTANT_NAME = "general_assistant";
    /**
     * 通用兜底助手描述。
     */
    private static final String GENERAL_ASSISTANT_DESCRIPTION = "处理闲聊、通用问答、非表单申请类咨询，以及没有匹配业务智能体的请求。";
    /**
     * 主助手默认系统提示词。
     */
    private static final String DEFAULT_CHATBOT_SYSTEM_PROMPT = "你是一个智能助手，负责基于当前聊天机器人的能力与配置为用户提供帮助。"
            + "当存在匹配的子智能体时，请优先调用对应工具处理。"
            + "如果没有合适工具，就直接给出清晰、准确的回复。";
    /**
     * 路由代理默认系统提示词。
     */
    private static final String DEFAULT_ROUTING_SYSTEM_PROMPT = """
            你负责在多个智能体之间做任务路由。
            如果用户是在办理某个表单申请、补充申请字段、修改申请内容、确认提交申请，请选择最匹配的业务智能体。
            如果用户只是闲聊、普通问答、或内容不属于任何业务申请，请选择 general_assistant。
            除非用户明确提出多个独立任务，否则只选择一个最合适的智能体。
            """;

    private final ModelProvisionService modelProvisionService;
    private final SystemPromptGenerator promptGenerator;
    private final SubmitTool submitTool;
    private final ToolExecutionTraceBuffer toolExecutionTraceBuffer;
    private final ChatbotBuiltInToolRegistry chatbotBuiltInToolRegistry;

    /**
     * 根据聊天机器人配置构建主智能体。
     *
     * @param chatbot 聊天机器人配置
     * @param saver   会话持久化 saver，由调用方管理生命周期
     * @return 已配置好的主智能体，可直接调用
     */
    public com.alibaba.cloud.ai.graph.agent.Agent buildChatbotAgent(Chatbot chatbot, BaseCheckpointSaver saver, String requestKey) {
        List<Agent> enabledSubAgents = chatbot.getSubAgents().stream()
                .filter(Agent::isEnabled)
                .toList();
        log.debug("chatbot={}, 加载到 {} 个 enabled 子智能体", chatbot.getId(), enabledSubAgents.size());

        if (enabledSubAgents.isEmpty()) {
            return buildStandaloneFallbackAgent(chatbot, saver, requestKey);
        }

        ReactAgent fallbackAgent = buildRoutingFallbackAgent(chatbot, saver, requestKey);
        List<com.alibaba.cloud.ai.graph.agent.Agent> routedAgents = new ArrayList<>();
        routedAgents.add(fallbackAgent);
        for (Agent agent : enabledSubAgents) {
            routedAgents.add(buildBusinessSubAgent(agent, chatbot, saver, requestKey));
        }

        return LlmRoutingAgent.builder()
                .name("main_agent")
                .description("负责把用户请求路由给最合适的通用助手或业务申请智能体。")
                .model(modelProvisionService.create(chatbot.getModelConfig()))
                .systemPrompt(resolveRoutingSystemPrompt(chatbot))
                .instruction("请基于当前对话上下文，选择下一步最应该处理该请求的单个智能体。")
                .subAgents(routedAgents)
                .saver(saver)
                .build();
    }

    /**
     * 构建无子智能体的通用Agent。
     *
     * @param chatbot    聊天机器人配置
     * @param saver      checkpoint 持久化器
     * @param requestKey 请求标识
     * @return 兜底 ReactAgent
     */
    private ReactAgent buildStandaloneFallbackAgent(Chatbot chatbot, BaseCheckpointSaver saver, String requestKey) {
        Builder builder = ReactAgent.builder()
                .name(GENERAL_ASSISTANT_NAME)
                .description(GENERAL_ASSISTANT_DESCRIPTION)
                .model(modelProvisionService.create(chatbot.getModelConfig()))
                .systemPrompt(resolveMainSystemPrompt(chatbot))
                .outputKey(GENERAL_ASSISTANT_NAME + "_result")
                .saver(saver);
        mountConfiguredBuiltInTools(builder, chatbot);
        applyInterceptors(builder, chatbot.getContextWindowSize(), requestKey);
        return builder.build();
    }

    /**
     * 构建路由场景下的通用子 Agent。
     *
     * @param chatbot    聊天机器人配置
     * @param saver      checkpoint 持久化器
     * @param requestKey 请求标识
     * @return 通用兜底 ReactAgent
     */
    private ReactAgent buildRoutingFallbackAgent(Chatbot chatbot, BaseCheckpointSaver saver, String requestKey) {
        Builder builder = ReactAgent.builder()
                .name(GENERAL_ASSISTANT_NAME)
                .description(GENERAL_ASSISTANT_DESCRIPTION)
                .model(modelProvisionService.create(chatbot.getModelConfig()))
                .systemPrompt(resolveMainSystemPrompt(chatbot))
                .outputKey(GENERAL_ASSISTANT_NAME + "_result")
                .saver(saver);
        mountConfiguredBuiltInTools(builder, chatbot);
        applyInterceptors(builder, chatbot.getContextWindowSize(), requestKey);
        return builder.build();
    }

    /**
     * 为业务智能体构建可路由子 Agent。
     *
     * @param agent      业务智能体
     * @param chatbot    聊天机器人配置
     * @param saver      checkpoint 持久化器
     * @param requestKey 请求标识
     * @return 业务子 ReactAgent
     */
    private ReactAgent buildBusinessSubAgent(Agent agent,
                                             Chatbot chatbot,
                                             BaseCheckpointSaver saver,
                                             String requestKey) {
        String agentName = agent.getName();
        String subSystemPrompt = promptGenerator.generate(agent);
        log.info("为子智能体 [{}] 生成 system prompt: {}", agent.getName(), subSystemPrompt);
        List<ToolCallback> toolCallbacks = new ArrayList<>();
        toolCallbacks.addAll(List.of(org.springframework.ai.support.ToolCallbacks.from(submitTool)));
        toolCallbacks.addAll(resolveConfiguredBuiltInToolCallbacks(chatbot));
        Builder builder = ReactAgent.builder()
                .name(agentName)
                .description(agent.getDescription())
                .model(modelProvisionService.create(agent.getModelConfig()))
                .systemPrompt(subSystemPrompt)
                .outputKey(agentName + "_result")
                .tools(toolCallbacks)
                .toolContext(java.util.Map.of(SubmitTool.AGENT_CONTEXT_KEY, agent))
                .hooks(HumanInTheLoopHook.builder()
                        .approvalOn("submit", ToolConfig.builder()
                                .description("提交当前子智能体已收集完成的表单字段")
                                .build())
                        .build())
                .saver(saver);
        applyInterceptors(builder, agent.getContextWindowSize(), requestKey);
        return builder.build();
    }

    /**
     * 按聊天机器人配置挂载内置工具。
     *
     * @param builder Agent 构建器
     * @param chatbot 聊天机器人配置
     */
    private void mountConfiguredBuiltInTools(Builder builder, Chatbot chatbot) {
        List<ToolCallback> toolCallbacks = resolveConfiguredBuiltInToolCallbacks(chatbot);
        if (!toolCallbacks.isEmpty()) {
            builder.tools(toolCallbacks);
        }
    }

    private List<ToolCallback> resolveConfiguredBuiltInToolCallbacks(Chatbot chatbot) {
        List<ToolCallback> toolCallbacks = new ArrayList<>();
        for (String toolKey : chatbot.getEnabledTools()) {
            chatbotBuiltInToolRegistry.findToolCallbackProvider(toolKey)
                    .ifPresent(provider -> toolCallbacks.addAll(List.of(provider.getToolCallbacks())));
        }
        return toolCallbacks;
    }

    /**
     * 为 Agent 统一装配拦截器（消息窗口 + 工具轨迹）。
     *
     * @param builder           Agent 构建器
     * @param contextWindowSize 上下文窗口大小
     * @param requestKey        请求标识
     */
    private void applyInterceptors(Builder builder, int contextWindowSize, String requestKey) {
        List<Interceptor> interceptors = new ArrayList<>();
        if (contextWindowSize > 0) {
            interceptors.add(new MessageFilterInterceptor(contextWindowSize));
        }
        interceptors.add(new ToolExecutionTraceInterceptor(toolExecutionTraceBuffer, requestKey));
        builder.interceptors(interceptors);
    }

    /**
     * 解析主 Agent 的系统提示词。
     *
     * @param chatbot 聊天机器人配置
     * @return 最终系统提示词
     */
    private String resolveMainSystemPrompt(Chatbot chatbot) {
        if (StringUtils.hasText(chatbot.getSystemPrompt())) {
            return chatbot.getSystemPrompt();
        }
        return DEFAULT_CHATBOT_SYSTEM_PROMPT;
    }

    /**
     * 解析路由 Agent 的系统提示词。
     *
     * @param chatbot 聊天机器人配置
     * @return 最终路由系统提示词
     */
    private String resolveRoutingSystemPrompt(Chatbot chatbot) {
        if (StringUtils.hasText(chatbot.getSystemPrompt())) {
            return chatbot.getSystemPrompt();
        }
        return DEFAULT_ROUTING_SYSTEM_PROMPT;
    }

}
