import { tool } from "@opencode-ai/plugin";

import { SkillStore } from "../../src/skills/store.js";
import {
  getRuntimeSessionContext,
  type RuntimeSessionContext,
} from "../../src/runtime/sessionContext.js";

type ToolContextReader = {
  read(sessionId: string): RuntimeSessionContext | null;
};

const runtimeContextReader: ToolContextReader = {
  read: getRuntimeSessionContext,
};

export const createSkillManagerTool = (
  skillStore = new SkillStore(),
  toolContextStore: ToolContextReader = runtimeContextReader,
  initializePromise: Promise<unknown> = Promise.resolve(),
) =>
  tool({
    description:
      "维护已验证、可复用、非敏感的 workflow 或方法模式。支持 list、write_skill、remove_skill、append_pattern、remove_pattern、write_reference、remove_reference、write_script、remove_script。",
    args: {
      action: tool.schema
        .enum([
          "list",
          "write_skill",
          "remove_skill",
          "append_pattern",
          "remove_pattern",
          "write_reference",
          "remove_reference",
          "write_script",
          "remove_script",
        ])
        .describe("Skill maintenance operation."),
      reason: tool.schema
        .string()
        .describe(
          "Why this skill maintenance action is justified for future reuse.",
        ),
      skill_path: tool.schema
        .string()
        .describe(
          "Target skill directory path relative to .opencode/skills. Use 'workflow' for the workflow index, or '__root__' for the root skills index.",
        ),
      pattern: tool.schema
        .string()
        .optional()
        .describe("Pattern text used by append_pattern."),
      target_id: tool.schema
        .string()
        .optional()
        .describe("Stable learned pattern id used by remove_pattern."),
      file_path: tool.schema
        .string()
        .optional()
        .describe(
          "Asset file path. For references use references/*.md; for scripts use scripts/*.py.",
        ),
      content: tool.schema
        .string()
        .optional()
        .describe(
          "Content used by write_skill, write_reference, or write_script.",
        ),
    },
    async execute(args, context) {
      await initializePromise;
      const sessionContext = toolContextStore.read(context.sessionID);
      if (!sessionContext) {
        throw new Error(`session context not found for ${context.sessionID}`);
      }
      if (
        sessionContext.allowLearningWrite === false &&
        args.action !== "list"
      ) {
        return JSON.stringify({
          ok: true,
          kind: "skill",
          decision: "rejected",
          detail: "skill writes are disabled for this session",
        });
      }
      if (args.action === "list") {
        const result = await skillStore.list(args.skill_path);
        if (!result) {
          return JSON.stringify({
            ok: true,
            kind: "skill",
            decision: "rejected",
            detail:
              "invalid skill_path; expected a relative path under .opencode/skills",
          });
        }
        return JSON.stringify({
          ok: true,
          kind: "skill",
          decision: "accepted",
          detail: "skill listed",
          references: result.references,
          scripts: result.scripts,
          skill_path: result.skillPath,
          target: result.target,
          patterns: result.patterns,
        });
      }

      const result =
        args.action === "write_skill"
          ? await skillStore.writeSkill(args.skill_path, args.content ?? "")
          : args.action === "remove_skill"
            ? await skillStore.removeSkill(args.skill_path)
            : args.action === "append_pattern"
              ? await skillStore.appendPattern(
                  args.skill_path,
                  args.pattern ?? "",
                )
              : args.action === "remove_pattern"
                ? await skillStore.removePattern(
                    args.skill_path,
                    args.target_id ?? "",
                  )
                : args.action === "write_reference"
                  ? await skillStore.writeReference(
                      args.skill_path,
                      args.file_path ?? "",
                      args.content ?? "",
                    )
                  : args.action === "remove_reference"
                    ? await skillStore.removeReference(
                        args.skill_path,
                        args.file_path ?? "",
                      )
                    : args.action === "write_script"
                      ? await skillStore.writeScript(
                          args.skill_path,
                          args.file_path ?? "",
                          args.content ?? "",
                        )
                      : await skillStore.removeScript(
                          args.skill_path,
                          args.file_path ?? "",
                        );

      return JSON.stringify({
        ok: true,
        kind: "skill",
        decision: result.changed ? "accepted" : "rejected",
        detail: result.detail,
        target: result.target,
      });
    },
  });

export default createSkillManagerTool();
