// src/tools/chat/subagent.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 AgentService from "../../services/agent.js";
import { ChatSessionMode } from "@/models/chat-session.js";
import HostMonitorService from "../../services/host-monitor.js";

const VALID_AGENT_TYPES = ["explore", "general"] as const;
type AgentType = (typeof VALID_AGENT_TYPES)[number];

export class SubagentTool extends DtpTool {
  get name(): string {
    return "SubagentTool";
  }
  get slug(): string {
    return "subagent";
  }
  get metadata() {
    return {
      name: this.definition.function.name || "subagent",
      category: "chat",
      tags: ["subagent", "spawn", "delegate", "explore", "general"],
      modes: [
        ChatSessionMode.Plan,
        ChatSessionMode.Build,
        ChatSessionMode.Test,
        ChatSessionMode.Ship,
        ChatSessionMode.Develop,
      ],
    };
  }

  public definition: ToolDefinition = {
    type: "function",
    function: {
      name: "subagent",
      description:
        "Spawn a subagent to perform a specific task. The subagent will execute the task and return its result. Use 'explore' agent type for research and information gathering tasks. Use 'general' agent type for general-purpose task execution.",
      parameters: {
        type: "object",
        properties: {
          agent_type: {
            type: "string",
            enum: VALID_AGENT_TYPES,
            description:
              "The type of subagent to spawn. Use 'explore' for research and information gathering. Use 'general' for general-purpose task execution.",
          },
          prompt: {
            type: "string",
            description:
              "The task description and instructions for the subagent. Be specific about what information to find or what task to perform.",
          },
        },
        required: ["agent_type", "prompt"],
      },
    },
  };

  public async execute(
    context: ToolContext,
    args: ToolArguments,
  ): Promise<string> {
    const { agent_type, prompt } = args;

    if (!agent_type) {
      return JSON.stringify({
        success: false,
        error: "MISSING_AGENT_TYPE",
        message: "The 'agent_type' parameter is required.",
        hint: "Specify either 'explore' or 'general' for the agent_type parameter.",
      });
    }

    if (!VALID_AGENT_TYPES.includes(agent_type as AgentType)) {
      return JSON.stringify({
        success: false,
        error: "INVALID_AGENT_TYPE",
        message: `Invalid agent_type: '${agent_type}'. Must be one of: ${VALID_AGENT_TYPES.join(", ")}`,
        hint: "Use 'explore' for research tasks or 'general' for general tasks.",
      });
    }

    if (!prompt) {
      return JSON.stringify({
        success: false,
        error: "MISSING_PROMPT",
        message: "The 'prompt' parameter is required.",
        hint: "Provide specific instructions for the subagent to execute.",
      });
    }

    if (typeof prompt !== "string") {
      return JSON.stringify({
        success: false,
        error: "INVALID_PROMPT_TYPE",
        message: `The 'prompt' parameter must be a string, but received ${typeof prompt}.`,
        hint: "Ensure you pass a string value for the prompt parameter.",
      });
    }

    this.log.debug("Spawning subagent", {
      agentType: agent_type,
      promptLength: prompt.length,
    });

    try {
      const result = await AgentService.spawnSubagent(
        context.session,
        agent_type as AgentType,
        prompt,
      );

      const resultJson = JSON.stringify({
        success: true,
        data: {
          agentType: agent_type,
          result: result.response,
          historyCount: result.history.length,
          historyIds: result.historyIds,
          subagentType: agent_type,
          subagentPrompt: String(prompt),
          subagentStats: result.stats,
        },
      });
      const byteCount = Buffer.byteLength(resultJson, "utf-8");
      HostMonitorService.subagent(byteCount);
      HostMonitorService.toolCall(byteCount);
      return resultJson;
    } catch (error) {
      const errorMessage =
        error instanceof Error ? error.message : String(error);

      this.log.error("Subagent execution failed", {
        agentType: agent_type,
        error: errorMessage,
      });

      return JSON.stringify({
        success: false,
        error: "SUBAGENT_FAILED",
        message: errorMessage,
      });
    }
  }
}

export default new SubagentTool();
