// Copyright (C) 2026 Rob Colbert <rob.colbert@openplatform.us>
// Licensed under the Apache License, Version 2.0

import type { IAiLogger, IToolArguments, IToolDefinition } from "@gadget/ai";
import { formatError } from "@gadget/ai";
import { DroneTool } from "../tool.ts";

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

export class SubagentTool extends DroneTool {
  private _spawnSubagent: ((agentType: string, prompt: string) => Promise<string>) | null = null;

  setSpawner(fn: typeof this._spawnSubagent): void {
    this._spawnSubagent = fn;
  }

  get name(): string {
    return "subagent";
  }

  get category(): string {
    return "chat";
  }

  get definition(): IToolDefinition {
    return {
      type: "function",
      function: {
        name: this.name,
        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"],
        },
      },
    };
  }

  async execute(args: IToolArguments, logger: IAiLogger): Promise<string> {
    const { agent_type, prompt } = args;

    if (!agent_type) {
      return formatError({
        code: "MISSING_PARAMETER",
        message: "The 'agent_type' parameter is required.",
        parameter: "agent_type",
        expected: "Either 'explore' or 'general'",
        recoveryHint: "Specify either 'explore' or 'general' for the agent_type parameter.",
      });
    }

    if (!VALID_AGENT_TYPES.includes(agent_type as AgentType)) {
      return formatError({
        code: "INVALID_PARAMETER",
        message: `Invalid agent_type: '${agent_type}'. Must be one of: ${VALID_AGENT_TYPES.join(", ")}`,
        parameter: "agent_type",
        expected: `One of: ${VALID_AGENT_TYPES.join(", ")}`,
        recoveryHint: "Use 'explore' for research tasks or 'general' for general tasks.",
      });
    }

    if (!prompt || typeof prompt !== "string") {
      return formatError({
        code: "MISSING_PARAMETER",
        message: "The 'prompt' parameter is required and must be a string.",
        parameter: "prompt",
        expected: "A non-empty string describing the task for the subagent.",
        recoveryHint: "Provide specific instructions for the subagent to execute.",
      });
    }

    if (!this._spawnSubagent) {
      return formatError({
        code: "OPERATION_FAILED",
        message: "SubagentTool has not been initialized with a spawner function.",
      });
    }

    logger.debug("spawning subagent", { agentType: agent_type, promptLength: (prompt as string).length });

    try {
      return await this._spawnSubagent(agent_type as string, prompt as string);
    } catch (error) {
      const message = error instanceof Error ? error.message : String(error);
      logger.error("subagent execution failed", { agentType: agent_type, error: message });
      return JSON.stringify({
        success: false,
        error: "SUBAGENT_FAILED",
        message,
      });
    }
  }
}
