import { exec } from 'node:child_process';
import { promises } from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';
import { promisify } from 'node:util';

const execAsync = promisify(exec);
class BaseCodeTool {
  config;
  configPath;
  constructor(initialConfig) {
    this.config = {
      name: this.getMetadata().name,
      ...initialConfig
    };
    this.configPath = this.getDefaultConfigPath();
  }
  /**
   * Get the default configuration path for this tool
   */
  getDefaultConfigPath() {
    const homeDir = os.homedir();
    const configDir = path.join(homeDir, ".ccjk", "tools");
    return path.join(configDir, `${this.getMetadata().name}.json`);
  }
  /**
   * Check if the tool is installed
   */
  async isInstalled() {
    try {
      const command = this.getInstallCheckCommand();
      const { stdout, stderr } = await execAsync(command);
      const version = this.parseVersion(stdout || stderr);
      return {
        installed: true,
        version,
        path: await this.findToolPath()
      };
    } catch (error) {
      return {
        installed: false,
        error: error instanceof Error ? error.message : "Unknown error"
      };
    }
  }
  /**
   * Install the tool
   */
  async install() {
    try {
      const command = this.getInstallCommand();
      const { stdout, stderr } = await execAsync(command);
      return {
        success: true,
        output: stdout || stderr,
        exitCode: 0
      };
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : "Installation failed",
        exitCode: 1
      };
    }
  }
  /**
   * Uninstall the tool
   */
  async uninstall() {
    try {
      const command = this.getUninstallCommand();
      const { stdout, stderr } = await execAsync(command);
      await this.removeConfigFile();
      return {
        success: true,
        output: stdout || stderr,
        exitCode: 0
      };
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : "Uninstallation failed",
        exitCode: 1
      };
    }
  }
  /**
   * Get current configuration
   */
  async getConfig() {
    try {
      await this.loadConfig();
      return { ...this.config };
    } catch (_error) {
      return { ...this.config };
    }
  }
  /**
   * Update configuration
   */
  async updateConfig(updates) {
    this.config = {
      ...this.config,
      ...updates
    };
    await this.saveConfig();
  }
  /**
   * Configure the tool with full config
   */
  async configure(config) {
    const isValid = await this.validateConfig(config);
    if (!isValid) {
      throw new Error("Invalid configuration");
    }
    this.config = { ...config };
    await this.saveConfig();
  }
  /**
   * Validate configuration
   */
  async validateConfig(config) {
    if (!config.name) {
      return false;
    }
    return true;
  }
  /**
   * Execute a command with the tool
   */
  async execute(command, args = []) {
    try {
      const fullCommand = this.buildCommand(command, args);
      const { stdout, stderr } = await execAsync(fullCommand, {
        env: { ...process.env, ...this.config.env }
      });
      return {
        success: true,
        output: stdout || stderr,
        exitCode: 0
      };
    } catch (error) {
      return {
        success: false,
        error: error.message || "Execution failed",
        exitCode: error.code || 1
      };
    }
  }
  /**
   * Get tool version
   */
  async getVersion() {
    const status = await this.isInstalled();
    return status.version;
  }
  /**
   * Reset tool to default configuration
   */
  async reset() {
    this.config = {
      name: this.getMetadata().name
    };
    await this.removeConfigFile();
  }
  /**
   * Load configuration from file
   */
  async loadConfig() {
    try {
      const data = await promises.readFile(this.configPath, "utf-8");
      const loadedConfig = JSON.parse(data);
      this.config = { ...this.config, ...loadedConfig };
    } catch (_error) {
    }
  }
  /**
   * Save configuration to file
   */
  async saveConfig() {
    try {
      const configDir = path.dirname(this.configPath);
      await promises.mkdir(configDir, { recursive: true });
      await promises.writeFile(this.configPath, JSON.stringify(this.config, null, 2));
    } catch (error) {
      throw new Error(`Failed to save configuration: ${error}`);
    }
  }
  /**
   * Remove configuration file
   */
  async removeConfigFile() {
    try {
      await promises.unlink(this.configPath);
    } catch (_error) {
    }
  }
  /**
   * Build command string from command and arguments
   */
  buildCommand(command, args) {
    const escapedArgs = args.map((arg) => {
      return arg.includes(" ") ? `"${arg}"` : arg;
    });
    return [command, ...escapedArgs].join(" ");
  }
  /**
   * Parse version from command output
   */
  parseVersion(output) {
    const patterns = [
      /version\s+(\d+\.\d+\.\d+)/i,
      /v?(\d+\.\d+\.\d+)/,
      /(\d+\.\d+\.\d+)/
    ];
    for (const pattern of patterns) {
      const match = output.match(pattern);
      if (match) {
        return match[1];
      }
    }
    return void 0;
  }
  /**
   * Find the tool's installation path
   */
  async findToolPath() {
    try {
      const { stdout } = await execAsync(`which ${this.getMetadata().name}`);
      return stdout.trim();
    } catch (_error) {
      return void 0;
    }
  }
  /**
   * Create default capabilities object
   */
  createDefaultCapabilities() {
    return {
      supportsChat: false,
      supportsFileEdit: false,
      supportsCodeGen: false,
      supportsReview: false,
      supportsTesting: false,
      supportsDebugging: false
    };
  }
}

class AiderTool extends BaseCodeTool {
  getMetadata() {
    return {
      name: "aider",
      displayName: "Aider",
      description: "AI pair programming in your terminal",
      version: "1.0.0",
      homepage: "https://aider.chat",
      documentation: "https://aider.chat/docs",
      capabilities: {
        supportsChat: true,
        supportsFileEdit: true,
        supportsCodeGen: true,
        supportsReview: true,
        supportsTesting: false,
        supportsDebugging: true
      }
    };
  }
  getInstallCheckCommand() {
    return "aider --version";
  }
  getInstallCommand() {
    return "pip install aider-chat";
  }
  getUninstallCommand() {
    return "pip uninstall -y aider-chat";
  }
  /**
   * Start a chat session
   */
  async chat(prompt) {
    return this.execute("aider", ["--message", prompt]);
  }
  /**
   * Continue a chat session
   */
  async continueChat(message) {
    return this.execute("aider", ["--message", message]);
  }
  /**
   * End chat session
   */
  async endChat() {
    await this.execute("aider", ["--exit"]);
  }
  /**
   * Edit a file
   */
  async editFile(filePath, instructions) {
    return this.execute("aider", [filePath, "--message", instructions]);
  }
  /**
   * Edit multiple files
   */
  async editFiles(files, instructions) {
    return this.execute("aider", [...files, "--message", instructions]);
  }
}

class ClaudeCodeTool extends BaseCodeTool {
  getMetadata() {
    return {
      name: "claude-code",
      displayName: "Claude Code",
      description: "Anthropic's official CLI tool for Claude AI",
      version: "1.0.0",
      homepage: "https://claude.ai",
      documentation: "https://docs.anthropic.com/claude/docs",
      capabilities: {
        supportsChat: true,
        supportsFileEdit: true,
        supportsCodeGen: true,
        supportsReview: true,
        supportsTesting: true,
        supportsDebugging: true
      },
      runtime: {
        runtime: "claude-code",
        ownership: "host-native",
        configBackend: "claude-family",
        native: {
          agentLoop: true,
          planTask: true,
          subagents: true,
          slashCommands: true,
          mcp: true,
          permissions: true,
          memory: true,
          ideIntegration: true,
          worktree: true,
          statusline: true
        },
        managedByCcjk: {
          providerProfiles: false,
          modelRouting: true,
          configSync: true,
          permissionRepair: true,
          mcpBundles: true,
          doctor: true
        }
      }
    };
  }
  getInstallCheckCommand() {
    return "claude --version";
  }
  getInstallCommand() {
    return "npm install -g @anthropic-ai/claude-code";
  }
  getUninstallCommand() {
    return "npm uninstall -g @anthropic-ai/claude-code";
  }
  /**
   * Start a chat session
   */
  async chat(prompt) {
    return this.execute("claude", ["chat", prompt]);
  }
  /**
   * Continue a chat session
   */
  async continueChat(message) {
    return this.execute("claude", ["continue", message]);
  }
  /**
   * End chat session
   */
  async endChat() {
    await this.execute("claude", ["exit"]);
  }
  /**
   * Edit a file
   */
  async editFile(filePath, instructions) {
    return this.execute("claude", ["edit", filePath, "--instructions", instructions]);
  }
  /**
   * Edit multiple files
   */
  async editFiles(files, instructions) {
    const fileArgs = files.flatMap((f) => ["--file", f]);
    return this.execute("claude", ["edit", ...fileArgs, "--instructions", instructions]);
  }
  /**
   * Generate code
   */
  async generateCode(prompt, outputPath) {
    const args = ["generate", prompt];
    if (outputPath) {
      args.push("--output", outputPath);
    }
    return this.execute("claude", args);
  }
}

class ClavueTool extends BaseCodeTool {
  getMetadata() {
    return {
      name: "clavue",
      displayName: "Clavue",
      description: "Execution-first Claude-family CLI with native provider profiles",
      version: "1.0.0",
      homepage: "https://www.clavue.com",
      capabilities: {
        supportsChat: true,
        supportsFileEdit: true,
        supportsCodeGen: true,
        supportsReview: true,
        supportsTesting: true,
        supportsDebugging: true
      },
      runtime: {
        runtime: "clavue",
        ownership: "hybrid",
        configBackend: "claude-family",
        native: {
          agentLoop: true,
          planTask: true,
          subagents: true,
          slashCommands: true,
          mcp: true,
          permissions: true,
          memory: true,
          ideIntegration: true,
          worktree: true,
          statusline: true
        },
        managedByCcjk: {
          providerProfiles: true,
          modelRouting: true,
          configSync: true,
          permissionRepair: true,
          mcpBundles: true,
          doctor: true
        }
      }
    };
  }
  getInstallCheckCommand() {
    return "clavue --version";
  }
  getInstallCommand() {
    return "npm install -g clavue";
  }
  getUninstallCommand() {
    return "npm uninstall -g clavue";
  }
  async chat(prompt) {
    return this.execute("clavue", ["chat", prompt]);
  }
  async continueChat(message) {
    return this.execute("clavue", ["continue", message]);
  }
  async endChat() {
    await this.execute("clavue", ["exit"]);
  }
  async editFile(filePath, instructions) {
    return this.execute("clavue", ["edit", filePath, "--instructions", instructions]);
  }
  async editFiles(files, instructions) {
    const fileArgs = files.flatMap((f) => ["--file", f]);
    return this.execute("clavue", ["edit", ...fileArgs, "--instructions", instructions]);
  }
  async generateCode(prompt, outputPath) {
    const args = ["generate", prompt];
    if (outputPath) {
      args.push("--output", outputPath);
    }
    return this.execute("clavue", args);
  }
}

class ClineTool extends BaseCodeTool {
  getMetadata() {
    return {
      name: "cline",
      displayName: "Cline",
      description: "Autonomous coding agent for VS Code",
      version: "1.0.0",
      homepage: "https://github.com/cline/cline",
      documentation: "https://github.com/cline/cline/wiki",
      capabilities: {
        supportsChat: true,
        supportsFileEdit: true,
        supportsCodeGen: true,
        supportsReview: true,
        supportsTesting: true,
        supportsDebugging: true
      }
    };
  }
  getInstallCheckCommand() {
    return "cline --version";
  }
  getInstallCommand() {
    return "npm install -g cline";
  }
  getUninstallCommand() {
    return "npm uninstall -g cline";
  }
  /**
   * Start a chat session
   */
  async chat(prompt) {
    return this.execute("cline", ["chat", prompt]);
  }
  /**
   * Continue a chat session
   */
  async continueChat(message) {
    return this.execute("cline", ["continue", message]);
  }
  /**
   * End chat session
   */
  async endChat() {
    await this.execute("cline", ["exit"]);
  }
  /**
   * Edit a file
   */
  async editFile(filePath, instructions) {
    return this.execute("cline", ["edit", filePath, "--instructions", instructions]);
  }
  /**
   * Edit multiple files
   */
  async editFiles(files, instructions) {
    const fileArgs = files.flatMap((f) => ["--file", f]);
    return this.execute("cline", ["edit", ...fileArgs, "--instructions", instructions]);
  }
  /**
   * Generate code
   */
  async generateCode(prompt, outputPath) {
    const args = ["generate", prompt];
    if (outputPath) {
      args.push("--output", outputPath);
    }
    return this.execute("cline", args);
  }
}

class CodexTool extends BaseCodeTool {
  getMetadata() {
    return {
      name: "codex",
      displayName: "OpenAI Codex",
      description: "OpenAI's code generation model",
      version: "1.0.0",
      homepage: "https://openai.com/codex",
      documentation: "https://platform.openai.com/docs",
      capabilities: {
        supportsChat: true,
        supportsFileEdit: false,
        supportsCodeGen: true,
        supportsReview: false,
        supportsTesting: false,
        supportsDebugging: false
      },
      runtime: {
        runtime: "codex",
        ownership: "host-native",
        configBackend: "tool-specific",
        native: {
          agentLoop: true,
          planTask: true,
          subagents: true,
          slashCommands: true,
          mcp: true,
          permissions: true,
          memory: true,
          ideIntegration: true,
          worktree: true,
          statusline: false
        },
        managedByCcjk: {
          providerProfiles: false,
          modelRouting: true,
          configSync: true,
          permissionRepair: true,
          mcpBundles: true,
          doctor: true
        }
      }
    };
  }
  getInstallCheckCommand() {
    return "codex --version";
  }
  getInstallCommand() {
    return "pip install openai-codex";
  }
  getUninstallCommand() {
    return "pip uninstall -y openai-codex";
  }
  /**
   * Generate code
   */
  async generateCode(prompt, outputPath) {
    const args = ["generate", prompt];
    if (outputPath) {
      args.push("--output", outputPath);
    }
    return this.execute("codex", args);
  }
}

class ContinueTool extends BaseCodeTool {
  getMetadata() {
    return {
      name: "continue",
      displayName: "Continue",
      description: "Open-source autopilot for software development",
      version: "1.0.0",
      homepage: "https://continue.dev",
      documentation: "https://continue.dev/docs",
      capabilities: {
        supportsChat: true,
        supportsFileEdit: true,
        supportsCodeGen: true,
        supportsReview: true,
        supportsTesting: true,
        supportsDebugging: true
      }
    };
  }
  getInstallCheckCommand() {
    return "continue --version";
  }
  getInstallCommand() {
    return "npm install -g continue";
  }
  getUninstallCommand() {
    return "npm uninstall -g continue";
  }
  /**
   * Start a chat session
   */
  async chat(prompt) {
    return this.execute("continue", ["chat", prompt]);
  }
  /**
   * Continue a chat session
   */
  async continueChat(message) {
    return this.execute("continue", ["chat", message]);
  }
  /**
   * End chat session
   */
  async endChat() {
    await this.execute("continue", ["exit"]);
  }
  /**
   * Generate code
   */
  async generateCode(prompt, outputPath) {
    const args = ["generate", prompt];
    if (outputPath) {
      args.push("--output", outputPath);
    }
    return this.execute("continue", args);
  }
}

class CursorTool extends BaseCodeTool {
  getMetadata() {
    return {
      name: "cursor",
      displayName: "Cursor",
      description: "AI-first code editor",
      version: "1.0.0",
      homepage: "https://cursor.sh",
      documentation: "https://cursor.sh/docs",
      capabilities: {
        supportsChat: true,
        supportsFileEdit: true,
        supportsCodeGen: true,
        supportsReview: true,
        supportsTesting: true,
        supportsDebugging: true
      }
    };
  }
  getInstallCheckCommand() {
    return "cursor --version";
  }
  getInstallCommand() {
    return 'echo "Please download Cursor from https://cursor.sh"';
  }
  getUninstallCommand() {
    return 'echo "Please uninstall Cursor manually"';
  }
  /**
   * Start a chat session
   */
  async chat(prompt) {
    return this.execute("cursor", ["chat", prompt]);
  }
  /**
   * Continue a chat session
   */
  async continueChat(message) {
    return this.execute("cursor", ["chat", message]);
  }
  /**
   * End chat session
   */
  async endChat() {
    await this.execute("cursor", ["exit"]);
  }
  /**
   * Edit a file
   */
  async editFile(filePath, instructions) {
    return this.execute("cursor", ["edit", filePath, "--instructions", instructions]);
  }
  /**
   * Edit multiple files
   */
  async editFiles(files, instructions) {
    const fileArgs = files.flatMap((f) => ["--file", f]);
    return this.execute("cursor", ["edit", ...fileArgs, "--instructions", instructions]);
  }
  /**
   * Generate code
   */
  async generateCode(prompt, outputPath) {
    const args = ["generate", prompt];
    if (outputPath) {
      args.push("--output", outputPath);
    }
    return this.execute("cursor", args);
  }
}

class ToolRegistry {
  static instance;
  tools;
  toolClasses;
  constructor() {
    this.tools = /* @__PURE__ */ new Map();
    this.toolClasses = /* @__PURE__ */ new Map();
  }
  /**
   * Get singleton instance
   */
  static getInstance() {
    if (!ToolRegistry.instance) {
      ToolRegistry.instance = new ToolRegistry();
    }
    return ToolRegistry.instance;
  }
  /**
   * Register a tool class
   */
  registerToolClass(name, toolClass) {
    this.toolClasses.set(name.toLowerCase(), toolClass);
  }
  /**
   * Register a tool instance
   */
  registerTool(tool) {
    const metadata = tool.getMetadata();
    this.tools.set(metadata.name.toLowerCase(), tool);
  }
  /**
   * Get a tool instance by name
   */
  getTool(name) {
    const normalizedName = name.toLowerCase();
    if (this.tools.has(normalizedName)) {
      return this.tools.get(normalizedName);
    }
    const ToolClass = this.toolClasses.get(normalizedName);
    if (ToolClass) {
      const tool = new ToolClass();
      this.tools.set(normalizedName, tool);
      return tool;
    }
    return void 0;
  }
  /**
   * Get all registered tool names
   */
  getToolNames() {
    return Array.from(this.toolClasses.keys());
  }
  /**
   * Get all tool instances
   */
  getAllTools() {
    return Array.from(this.tools.values());
  }
  /**
   * Check if a tool is registered
   */
  hasTool(name) {
    return this.toolClasses.has(name.toLowerCase());
  }
  /**
   * Unregister a tool
   */
  unregisterTool(name) {
    const normalizedName = name.toLowerCase();
    this.tools.delete(normalizedName);
    this.toolClasses.delete(normalizedName);
  }
  /**
   * Clear all registered tools
   */
  clear() {
    this.tools.clear();
    this.toolClasses.clear();
  }
  /**
   * Get metadata for all registered tools
   */
  async getAllMetadata() {
    const metadata = [];
    for (const name of this.toolClasses.keys()) {
      const tool = this.getTool(name);
      if (tool) {
        metadata.push(tool.getMetadata());
      }
    }
    return metadata;
  }
}
function getRegistry() {
  return ToolRegistry.getInstance();
}

const RUNTIME_CAPABILITY_FALLBACKS = {
  clavue: {
    runtime: "clavue",
    ownership: "hybrid",
    configBackend: "claude-family",
    native: {
      agentLoop: true,
      planTask: true,
      subagents: true,
      slashCommands: true,
      mcp: true,
      permissions: true,
      memory: true,
      ideIntegration: true,
      worktree: true,
      statusline: true
    },
    managedByCcjk: {
      providerProfiles: true,
      modelRouting: true,
      configSync: true,
      permissionRepair: true,
      mcpBundles: true,
      doctor: true
    }
  }
};
const registry = ToolRegistry.getInstance();
registry.registerToolClass("claude-code", ClaudeCodeTool);
registry.registerToolClass("clavue", ClavueTool);
registry.registerToolClass("codex", CodexTool);
registry.registerToolClass("aider", AiderTool);
registry.registerToolClass("continue", ContinueTool);
registry.registerToolClass("cline", ClineTool);
registry.registerToolClass("cursor", CursorTool);
function getRuntimeCapabilityDescriptor(name) {
  const normalizedName = name.toLowerCase();
  return registry.getTool(normalizedName)?.getMetadata().runtime || RUNTIME_CAPABILITY_FALLBACKS[normalizedName];
}

export { AiderTool as A, BaseCodeTool as B, ClaudeCodeTool as C, ToolRegistry as T, getRegistry as a, ClavueTool as b, ClineTool as c, CodexTool as d, ContinueTool as e, CursorTool as f, getRuntimeCapabilityDescriptor as g };
