package com.gzzm.lobster.tool.builtin;

import com.gzzm.lobster.common.ToolCategory;
import com.gzzm.lobster.common.ToolRiskLevel;
import com.gzzm.lobster.plan.PlanService;
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.*;

/**
 * PlanTools —— 计划工具 / update_plan tool.
 *
 * <p>由 LLM 自主管理计划；runtime 仅持久化并通过 stream 推送。
 */
public class PlanTools {

    @Inject private PlanService planService;
    @Inject private ThreadService threadService;

    public void registerTo(ToolRegistry registry) {
        registry.register(updateDef(), this::update);
    }

    private BuiltinToolDefinition updateDef() {
        Map<String, Object> itemSchema = SchemaBuilder.obj()
                .prop("itemId", "string", "item id（可选，新建时可不填）")
                .propInt("seq", "顺序号")
                .prop("title", "string", "步骤标题")
                .prop("description", "string", "步骤详细描述")
                .propEnum("status", "步骤状态", "PENDING", "IN_PROGRESS", "COMPLETED", "SKIPPED", "FAILED")
                .prop("resultSummary", "string", "执行结果摘要（可选）")
                .prop("artifactId", "string", "关联工件（可选）")
                .build();
        return BuiltinToolDefinition.builder()
                .name("update_plan")
                .displayName("更新任务计划")
                .description("创建或更新当前 thread 的任务计划。用于长任务或多步骤任务。"
                        + "每次调用会覆盖当前计划的全部步骤，便于 LLM 自然迭代计划。")
                .category(ToolCategory.PLAN)
                .risk(ToolRiskLevel.WRITE)
                .inputSchema(SchemaBuilder.obj()
                        .prop("planId", "string", "计划 ID（可选，不填则自动选择当前激活计划或新建）")
                        .prop("title", "string", "计划标题（可选）")
                        .prop("skillId", "string", "关联 Skill（可选）")
                        .propArray("items", "步骤列表", itemSchema)
                        .required("items")
                        .build())
                .build();
    }

    @SuppressWarnings("unchecked")
    private ToolResult update(ToolContext ctx, Map<String, Object> args) throws Exception {
        String planId = asStr(args.get("planId"));
        String title = asStr(args.get("title"));
        String skillId = asStr(args.get("skillId"));
        Object itemsObj = args.get("items");
        List<Map<String, Object>> items = new ArrayList<>();
        if (itemsObj instanceof List) {
            for (Object o : (List<Object>) itemsObj) {
                if (o instanceof Map) items.add((Map<String, Object>) o);
            }
        }
        ThreadRoom thread = threadService.requireOwnedThread(ctx.getUserContext(), ctx.getThreadId());
        PlanService.PlanSnapshot snap = planService.upsert(thread, ctx.getUserContext(),
                planId, title, items, skillId);
        Map<String, Object> data = snap.toMap();
        return ToolResult.ok("计划已更新", data);
    }

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