// src/tools/skills/create-skill.ts
// Copyright (C) 2025 DTP Technologies, LLC
// All Rights Reserved

import type { ToolDefinition } from "../../lib/ai-client.js";

import {
  DtpTool,
  type ToolArguments,
  type ToolContext,
} from "../../lib/tool.js";
import { AiSkill } from "../../models/ai-skill.js";
import { ChatSessionMode } from "../../models/chat-session.js";
import type { IUser } from "../../models/user.js";

export class CreateSkillTool extends DtpTool {
  get name(): string {
    return "CreateSkillTool";
  }
  get slug(): string {
    return "create-skill";
  }
  get metadata() {
    return {
      name: this.definition.function.name || "create_skill",
      category: "skills",
      tags: ["skill", "create", "new", "add"],
      modes: [
        ChatSessionMode.Plan,
        ChatSessionMode.Build,
        ChatSessionMode.Test,
        ChatSessionMode.Ship,
        ChatSessionMode.Develop,
      ],
    };
  }

  public definition: ToolDefinition = {
    type: "function",
    function: {
      name: "create_skill",
      description:
        "Create a new skill. Skills are recipes or instruction manuals the agent can follow. Provide a clear name, description, tags for searchability, and the content with detailed instructions.",
      parameters: {
        type: "object",
        properties: {
          name: {
            type: "string",
            description:
              "The name of the skill (e.g., 'Write React Component').",
          },
          description: {
            type: "string",
            description:
              "A brief description of what this skill does and when to use it.",
          },
          tags: {
            type: "string",
            description:
              "Comma-separated list of tags for searchability (e.g., 'react, frontend, component').",
          },
          modes: {
            type: "array",
            items: {
              type: "string",
              enum: ["build", "plan", "test", "ship", "dev"],
            },
            description:
              "Array of modes where this skill can be used. Defaults to ['build'] if not specified.",
          },
          content: {
            type: "string",
            description:
              "The full content/instructions of the skill. This is what the agent will read when using this skill.",
          },
        },
        required: ["name", "description", "content"],
      },
    },
  };

  public async execute(
    context: ToolContext,
    args: ToolArguments,
  ): Promise<string> {
    const name = args.name as string | undefined;
    const description = args.description as string | undefined;
    const tagsStr = args.tags as string | undefined;
    const modesArg = args.modes as string[] | undefined;
    const content = args.content as string | undefined;

    if (!name || !description || !content) {
      return this.error(
        "INVALID_PARAMETER",
        "name, description, and content are required.",
        { parameter: "name, description, content" },
      );
    }

    const tags = tagsStr
      ? tagsStr
          .split(",")
          .map((t) => t.trim())
          .filter((t) => t.length > 0)
      : [];

    let modes: ChatSessionMode[] = [ChatSessionMode.Build];
    if (modesArg && Array.isArray(modesArg)) {
      modes = modesArg
        .map((m) => m.toLowerCase())
        .filter((m) => ["build", "plan", "test", "ship", "dev"].includes(m))
        .map((m) => {
          switch (m) {
            case "build":
              return ChatSessionMode.Build;
            case "plan":
              return ChatSessionMode.Plan;
            case "test":
              return ChatSessionMode.Test;
            case "ship":
              return ChatSessionMode.Ship;
            case "dev":
              return ChatSessionMode.Develop;
            default:
              return ChatSessionMode.Build;
          }
        });
      if (modes.length === 0) modes = [ChatSessionMode.Build];
    }

    try {
      const user = context.session.user as IUser;
      const skill = new AiSkill({
        user: user._id,
        name,
        description,
        tags,
        modes,
        content,
      });

      await skill.save();
      return this.success(
        { skillId: skill._id?.toString(), name },
        `Skill created: ${name}`,
      );
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);
      return this.error(
        "OPERATION_FAILED",
        `Failed to create skill: ${errorMessage}`,
      );
    }
  }
}

export default new CreateSkillTool();
