import type { ToolsetDefinition, BodySchema } from "../types.js";
import { passthrough } from "../extractors.js";

/**
 * Generate a UID from an agent name by converting to lowercase and replacing
 * spaces/special chars with underscores. E.g., "DevOps Assistant" -> "devops_assistant"
 */
function generateAgentUid(name: string): string {
  return name
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "_")
    .replace(/^_+|_+$/g, ""); // trim leading/trailing underscores
}

const agentCreateSchema: BodySchema = {
  description: "Agent creation request. The 'spec' field contains the YAML specification defining the agent's behavior, stages, steps, rules, skills, MCP servers, and inputs. The API validates the spec format server-side. The 'uid' field is required and must be unique within the scope.",
  fields: [
    { name: "uid", type: "string", required: true, description: "Unique identifier for the custom agent. This will be the agent's ID and must be unique within the scope (account/org/project). Use lowercase with underscores, no spaces or colons (e.g., 'code_reviewer', 'my_custom_agent'). Cannot conflict with system agent UIDs." },
    { name: "name", type: "string", required: true, description: "Display name of the custom agent (e.g., 'Code Reviewer', 'My Custom Agent')" },
    { name: "description", type: "string", required: false, description: "Brief description of the agent's purpose and capabilities" },
    { name: "spec", type: "string", required: true, description: "Agent YAML specification. Defines step, container image, task, rules, MCP servers, and inputs. The API validates and converts this to step template and publishes it. The agent name in the spec cannot conflict with existing system agent UUIDs." },
    { name: "wiki", type: "string", required: false, description: "URL to the agent's documentation or wiki" },
    { name: "logo", type: "string", required: false, description: "URL to the agent's logo image" },
  ],
};

const agentUpdateSchema: BodySchema = {
  description: "Agent update request. All fields are optional. Only provided fields will be updated. The 'spec' field replaces the entire agent specification and will be validated and converted to pipeline YAML format.",
  fields: [
    { name: "name", type: "string", required: false, description: "Updated display name of the custom agent" },
    { name: "description", type: "string", required: false, description: "Updated description of the agent's purpose" },
    { name: "spec", type: "string", required: false, description: "Updated agent YAML specification (full replacement). This will be validated and converted to step template and published" },
    { name: "wiki", type: "string", required: false, description: "Updated URL to the agent's documentation" },
    { name: "logo", type: "string", required: false, description: "Updated URL to the agent's logo" },
  ],
};

export const agentsToolset: ToolsetDefinition = {
  name: "agents",
  displayName: "Agents",
  description: "Custom AI agent definitions and configurations. Build agents that clone repos, run tasks, integrate with MCP servers, and follow rules/skills.",
  resources: [
    {
      resourceType: "agent",
      displayName: "AI Agent",
      description: "Custom or system AI agent definition. Agents execute tasks using LLMs, can clone repos, run in containers, use MCP servers, and follow rules/skills. Supports CRUD operations.",
      toolset: "agents",
      scope: "project",
      scopeOptional: false,
      identifierFields: ["agent_id"],
      deepLinkTemplate: "/ng/account/{accountId}/all/orgs/{orgIdentifier}/projects/{projectIdentifier}/agents/{agentIdentifier}/details",
      operations: {
        list: {
          method: "GET",
          path: "/gateway/agents/api/v1/agents",
          operationPolicy: { risk: "read", retryPolicy: "safe" },
          responseExtractor: passthrough,
          description: "List all agents (system and custom) scoped to the account/org/project context",
        },
        get: {
          method: "GET",
          path: "/gateway/agents/api/v1/agents/{agentIdentifier}",
          operationPolicy: { risk: "read", retryPolicy: "safe" },
          pathParams: { agent_id: "agentIdentifier" },
          responseExtractor: passthrough,
          description: "Get agent details including YAML spec, role, status, timestamps, wiki, and logo",
        },
        create: {
          method: "POST",
          path: "/gateway/agents/api/v1/agents",
          operationPolicy: { risk: "low_write", retryPolicy: "do_not_retry" },
          bodyBuilder: (input) => {
            const body = input.body as Record<string, unknown> | undefined;
            if (!body) throw new Error("body is required for agent creation");

            // Ensure uid is present - generate from name if not provided
            if (!body.uid && body.name) {
              body.uid = generateAgentUid(body.name as string);
            }

            if (!body.uid) {
              throw new Error("uid is required (or name must be provided to generate uid)");
            }

            return body;
          },
          responseExtractor: passthrough,
          description: "Create a new custom agent with YAML specification. System agents cannot be created via API. The uid field is required and must be unique within the scope.",
          bodySchema: agentCreateSchema,
        },
        update: {
          method: "PUT",
          path: "/gateway/agents/api/v1/agents/{agentIdentifier}",
          operationPolicy: { risk: "low_write", retryPolicy: "safe" },
          pathParams: { agent_id: "agentIdentifier" },
          bodyBuilder: (input) => {
            const body = input.body as Record<string, unknown> | undefined;
            if (!body) throw new Error("body is required for agent update");
            return body;
          },
          responseExtractor: passthrough,
          description: "Update a custom agent. All fields are optional. Only custom agents can be updated (role='custom').",
          bodySchema: agentUpdateSchema,
        },
        delete: {
          method: "DELETE",
          path: "/gateway/agents/api/v1/agents/{agentIdentifier}",
          operationPolicy: { risk: "destructive", retryPolicy: "do_not_retry" },
          pathParams: { agent_id: "agentIdentifier" },
          responseExtractor: passthrough,
          description: "Delete a custom agent (soft delete - sets status to 'deleted'). Only custom agents can be deleted.",
        },
      },
    },
  ],
};
