import type { Tool, ToolResult } from '../tools/types.js';
import type { DockerSandbox } from './docker.js';

interface ShellExecArgs {
  command: string;
  cwd?: string;
  timeout?: number;
}

interface ProcessStartArgs {
  command: string;
  cwd?: string;
}

/**
 * Create a sandboxed version of shell.exec that delegates to docker exec.
 * Same Tool interface — drop-in replacement for the host shell.exec.
 */
export function createSandboxedShellTool(sandbox: DockerSandbox): Tool {
  return {
    name: 'shell.exec',
    description: 'Execute a shell command inside a sandboxed container and return stdout/stderr.',
    inputSchema: {
      type: 'object',
      properties: {
        command: { type: 'string', description: 'The shell command to execute' },
        cwd: { type: 'string', description: 'Working directory inside the container (optional)' },
        timeout: { type: 'number', description: 'Timeout in milliseconds (default 30000)' },
      },
      required: ['command'],
    },
    execute: async (rawArgs: unknown): Promise<ToolResult> => {
      const args = rawArgs as ShellExecArgs;
      const timeout = args.timeout ?? 30_000;

      try {
        const result = await sandbox.exec(args.command, {
          cwd: args.cwd,
          timeout,
        });

        const output = result.stdout + (result.stderr ? `\nstderr: ${result.stderr}` : '');
        return { success: true, output };
      } catch (error) {
        return {
          success: false,
          output: '',
          error: error instanceof Error ? error.message : String(error),
        };
      }
    },
  };
}

/**
 * Create a sandboxed version of process.start that runs in the container.
 * Uses `nohup ... &` via docker exec since we can't spawn detached inside containers.
 */
export function createSandboxedProcessStartTool(sandbox: DockerSandbox): Tool {
  return {
    name: 'process.start',
    description: 'Start a command in the background inside a sandboxed container.',
    inputSchema: {
      type: 'object',
      properties: {
        command: { type: 'string', description: 'The shell command to run in the background' },
        cwd: { type: 'string', description: 'Working directory inside the container (optional)' },
      },
      required: ['command'],
    },
    execute: async (rawArgs: unknown): Promise<ToolResult> => {
      const args = rawArgs as ProcessStartArgs;

      try {
        const wrappedCmd = `nohup bash -c '${args.command.replace(/'/g, "'\\''")}' > /tmp/proc.log 2>&1 & echo $!`;
        const result = await sandbox.exec(wrappedCmd, { cwd: args.cwd });

        const pid = result.stdout.trim();
        return {
          success: true,
          output: `Started sandboxed background process (PID ${pid})\nCommand: ${args.command}`,
        };
      } catch (error) {
        return {
          success: false,
          output: '',
          error: error instanceof Error ? error.message : 'Failed to start sandboxed process',
        };
      }
    },
  };
}
