import { exec } from 'child_process';
import { promisify } from 'util';
import type { ToolResult } from '../../types/index.js';
import type { ToolWithMetadata } from '../types.js';
import { loadDescription } from '../load_description.js';
import { getPermissionManager } from '../../permission/index.js';

const execAsync = promisify(exec);

export const bashTool: ToolWithMetadata = {
  name: 'bash',
  description: loadDescription('bash'),
  metadata: {
    name: 'bash',
    category: 'shell',
    description: '执行 shell 命令',
    keywords: ['bash', 'shell', 'command', 'execute', 'run', 'terminal', '命令', '执行', '终端', 'sh', 'cmd'],
    deferLoading: false, // 核心工具，始终加载
  },
  parameters: {
    command: {
      type: 'string',
      description: '要执行的 bash 命令',
      required: true,
    },
    cwd: {
      type: 'string',
      description: '工作目录（可选，默认为当前目录）',
      required: false,
    },
  },
  execute: async (params: Record<string, unknown>): Promise<ToolResult> => {
    const command = params.command as string;
    const cwd = (params.cwd as string) || process.cwd();

    // 权限检查
    const permissionManager = getPermissionManager();
    const permResult = await permissionManager.checkBashPermission({
      command,
      workdir: cwd,
    });

    if (!permResult.allowed) {
      // 如果需要用户确认但没有设置回调，返回等待确认的状态
      if (permResult.needsConfirmation) {
        return {
          success: false,
          output: '',
          error: `需要用户确认: ${command}\n原因: ${permResult.reason || '需要权限确认'}\n模式: ${permResult.patterns?.join(', ') || ''}`,
        };
      }

      return {
        success: false,
        output: '',
        error: `权限被拒绝: ${permResult.reason || '命令不被允许执行'}`,
      };
    }

    try {
      const { stdout, stderr } = await execAsync(command, {
        cwd,
        timeout: 60000, // 60 秒超时
        maxBuffer: 1024 * 1024 * 10, // 10MB 输出限制
      });

      return {
        success: true,
        output: stdout + (stderr ? `\nSTDERR: ${stderr}` : ''),
      };
    } catch (error) {
      const execError = error as { stdout?: string; stderr?: string; message: string };
      return {
        success: false,
        output: execError.stdout || '',
        error: execError.stderr || execError.message,
      };
    }
  },
};
