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 gitAddTool: ToolWithMetadata = {
  name: 'git_add',
  description: loadDescription('git_add'),
  metadata: {
    name: 'git_add',
    category: 'git',
    description: '暂存文件到 Git',
    keywords: ['git', 'add', 'stage', '暂存', '添加', 'staging'],
    deferLoading: false,
  },
  parameters: {
    files: {
      type: 'array',
      description: '要暂存的文件列表',
      required: false,
    },
    all: {
      type: 'boolean',
      description: '暂存所有变更（-A）',
      required: false,
    },
    update: {
      type: 'boolean',
      description: '仅暂存已跟踪文件的变更（-u）',
      required: false,
    },
  },
  execute: async (params: Record<string, unknown>): Promise<ToolResult> => {
    let files = params.files as string[] | string | undefined;
    const all = params.all as boolean;
    const update = params.update as boolean;

    // 转换单个文件为数组
    if (typeof files === 'string') {
      files = [files];
    }

    // 权限检查
    const permissionManager = getPermissionManager();
    const permResult = await permissionManager.checkGitPermission({
      operation: 'add',
      target: all ? '所有文件' : files?.join(', '),
    });

    if (!permResult.allowed) {
      if (permResult.needsConfirmation) {
        return {
          success: false,
          output: '',
          error: `需要用户确认: git add\n原因: ${permResult.reason || '需要权限确认'}`,
        };
      }
      return {
        success: false,
        output: '',
        error: `权限被拒绝: ${permResult.reason || '操作不被允许'}`,
      };
    }

    try {
      let command: string;

      if (all) {
        command = 'git add -A';
      } else if (update) {
        command = 'git add -u';
      } else if (files && files.length > 0) {
        // 转义文件名中的特殊字符
        const escapedFiles = files.map(f => `"${f}"`).join(' ');
        command = `git add ${escapedFiles}`;
      } else {
        return {
          success: false,
          output: '',
          error: '请指定要暂存的文件（files 参数）或使用 all: true 暂存所有变更',
        };
      }

      const { stdout, stderr } = await execAsync(command, {
        cwd: process.cwd(),
        timeout: 30000,
      });

      // git add 成功时通常没有输出，显示暂存的文件
      let output = stdout || '文件已暂存';

      // 获取暂存状态
      const { stdout: statusOut } = await execAsync('git status -s', {
        cwd: process.cwd(),
        timeout: 10000,
      });

      if (statusOut) {
        output += '\n\n当前暂存状态:\n' + statusOut;
      }

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