package com.gzzm.lobster.tool.builtin;

import com.gzzm.lobster.common.PendingRequestType;
import com.gzzm.lobster.common.ToolCategory;
import com.gzzm.lobster.common.ToolExecutionMode;
import com.gzzm.lobster.common.ToolRiskLevel;
import com.gzzm.lobster.pending.PendingRequest;
import com.gzzm.lobster.pending.PendingRequestService;
import com.gzzm.lobster.thread.ThreadRoom;
import com.gzzm.lobster.thread.ThreadService;
import com.gzzm.lobster.tool.*;
import net.cyan.nest.annotation.Inject;

import java.util.*;

/**
 * InteractionTools —— Layer 4 用户交互工具 / confirm_action + ask_user.
 *
 * <p>这两个工具一定返回 pending 状态，使当前 run 自然结束。
 */
public class InteractionTools {

    @Inject private PendingRequestService pendingService;
    @Inject private ThreadService threadService;

    public void registerTo(ToolRegistry registry) {
        registry.register(confirmDef(), this::confirm);
        registry.register(askDef(), this::ask);
    }

    private BuiltinToolDefinition confirmDef() {
        return BuiltinToolDefinition.builder()
                .name("confirm_action")
                .displayName("请求用户确认")
                .description("请求用户对一个即将执行的动作进行确认。调用后当前 run 结束，用户确认后触发新 run。")
                .category(ToolCategory.INTERACTION)
                .mode(ToolExecutionMode.ASYNC_PENDING)
                .risk(ToolRiskLevel.READ_ONLY)
                .sideEffect(SideEffectLevel.WRITE_LOCAL)
                .inputSchema(SchemaBuilder.obj()
                        .prop("title", "string", "标题")
                        .prop("description", "string", "向用户可见的描述文本")
                        .prop("payload", "object", "待确认上下文（任意键值对）")
                        .propArray("allowedActions", "可选动作列表",
                                java.util.Collections.singletonMap("type", "string"))
                        .required("title", "description")
                        .build())
                .build();
    }

    @SuppressWarnings("unchecked")
    private ToolResult confirm(ToolContext ctx, Map<String, Object> args) throws Exception {
        ThreadRoom thread = threadService.requireOwnedThread(ctx.getUserContext(), ctx.getThreadId());
        String title = asStr(args.get("title"));
        String description = asStr(args.get("description"));
        Object payloadObj = args.get("payload");
        Map<String, Object> payload = payloadObj instanceof Map ? (Map<String, Object>) payloadObj : null;
        List<String> allowed = null;
        Object act = args.get("allowedActions");
        if (act instanceof List) {
            allowed = new ArrayList<>();
            for (Object o : (List<Object>) act) allowed.add(String.valueOf(o));
        }
        if (allowed == null || allowed.isEmpty()) {
            allowed = new ArrayList<>(Arrays.asList("CONFIRM", "CANCEL"));
        }
        PendingRequest pr = pendingService.create(thread, ctx.getUserContext(),
                PendingRequestType.confirm_action, title, description, payload,
                allowed, null, ctx.getRunId(), ctx.getToolCallId());
        // Fix B6: 传真实 pending title（"覆盖原 OA 文件" 等），而不是工具 userMessage
        return ToolResult.pending(pr.getRequestId(), PendingRequestType.confirm_action,
                pr.getTitle(),
                "已发出确认请求，等待用户响应");
    }

    private BuiltinToolDefinition askDef() {
        return BuiltinToolDefinition.builder()
                .name("ask_user")
                .displayName("向用户提问/补料")
                .description("向用户提出一个问题或请求补充信息。调用后当前 run 结束。")
                .category(ToolCategory.INTERACTION)
                .mode(ToolExecutionMode.ASYNC_PENDING)
                .risk(ToolRiskLevel.READ_ONLY)
                .sideEffect(SideEffectLevel.WRITE_LOCAL)
                .inputSchema(SchemaBuilder.obj()
                        .prop("question", "string", "问题文本")
                        .prop("context", "string", "问题背景（可选）")
                        .propArray("suggestedOptions", "预设选项",
                                java.util.Collections.singletonMap("type", "string"))
                        .required("question")
                        .build())
                .build();
    }

    @SuppressWarnings("unchecked")
    private ToolResult ask(ToolContext ctx, Map<String, Object> args) throws Exception {
        ThreadRoom thread = threadService.requireOwnedThread(ctx.getUserContext(), ctx.getThreadId());
        String question = asStr(args.get("question"));
        String context = asStr(args.get("context"));
        Map<String, Object> payload = new LinkedHashMap<>();
        if (context != null) payload.put("context", context);
        Object sug = args.get("suggestedOptions");
        if (sug != null) payload.put("suggestedOptions", sug);
        PendingRequest pr = pendingService.create(thread, ctx.getUserContext(),
                PendingRequestType.ask_user, "补充说明", question, payload,
                java.util.Collections.<String>emptyList(), null,
                ctx.getRunId(), ctx.getToolCallId());
        // Fix B6
        return ToolResult.pending(pr.getRequestId(), PendingRequestType.ask_user,
                pr.getTitle(),
                "已发出补料请求，等待用户输入");
    }

    private String asStr(Object o) { return o == null ? null : String.valueOf(o); }
}
