import { tool } from 'ai';
import type { ToolDefinition, ToolContext, ToolCategory } from './types.js';

/**
 * Central registry for tool management
 *
 * Handles tool registration, lookup, and conversion to AI SDK format
 */
export class ToolRegistry {
  private tools = new Map<string, ToolDefinition>();

  /**
   * Register a tool definition
   */
  register(definition: ToolDefinition): void {
    if (this.tools.has(definition.name)) {
      throw new Error(`Tool "${definition.name}" is already registered`);
    }
    this.tools.set(definition.name, definition);
  }

  /**
   * Get a tool by name
   */
  get(name: string): ToolDefinition | undefined {
    return this.tools.get(name);
  }

  /**
   * Check if a tool is registered
   */
  has(name: string): boolean {
    return this.tools.has(name);
  }

  /**
   * Get all registered tools
   */
  getAll(): ToolDefinition[] {
    return Array.from(this.tools.values());
  }

  /**
   * Get tools filtered by category
   */
  getByCategory(category: ToolCategory): ToolDefinition[] {
    return this.getAll().filter((t) => t.category === category);
  }

  /**
   * Get tool names
   */
  getNames(): string[] {
    return Array.from(this.tools.keys());
  }

  /**
   * Remove a tool by name
   */
  remove(name: string): boolean {
    return this.tools.delete(name);
  }

  /**
   * Clear all registered tools
   */
  clear(): void {
    this.tools.clear();
  }

  /**
   * Create a new registry with only the specified tools
   */
  subset(names: string[]): ToolRegistry {
    const registry = new ToolRegistry();
    for (const name of names) {
      const tool = this.get(name);
      if (tool) {
        registry.tools.set(name, tool);
      }
    }
    return registry;
  }

  /**
   * Convert to AI SDK tools format
   *
   * Creates tool wrappers that execute with the provided context
   */
  toAITools(context: ToolContext): Record<string, ReturnType<typeof tool>> {
    const result: Record<string, ReturnType<typeof tool>> = {};

    for (const def of this.tools.values()) {
      result[def.name] = tool({
        description: def.description,
        parameters: def.schema,
        execute: async (input) => {
          const result = await def.execute(input, context);
          return result;
        },
      });
    }

    return result;
  }
}

// Import tools for default registry
import { readFileTool, writeFileTool, editFileTool, listFilesTool } from './coding.js';
import { grepTool, globTool } from './search.js';
import { semanticSearchTool, indexRepositoryTool } from './semantic.js';
import { executeCommandTool, gitCommandTool } from './shell.js';
import { taskTool } from './task.js';

/**
 * Create a registry with all default tools
 */
export function createDefaultRegistry(): ToolRegistry {
  const registry = new ToolRegistry();

  // Coding tools
  registry.register(readFileTool);
  registry.register(writeFileTool);
  registry.register(editFileTool);
  registry.register(listFilesTool);

  // Search tools
  registry.register(grepTool);
  registry.register(globTool);
  registry.register(semanticSearchTool);
  registry.register(indexRepositoryTool);

  // Shell tools
  registry.register(executeCommandTool);
  registry.register(gitCommandTool);

  // Task tool
  registry.register(taskTool);

  return registry;
}

/**
 * Create a registry with only read-only tools (for explore mode)
 */
export function createReadOnlyRegistry(): ToolRegistry {
  const registry = new ToolRegistry();

  registry.register(readFileTool);
  registry.register(listFilesTool);
  registry.register(grepTool);
  registry.register(globTool);

  return registry;
}
