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 gitCheckoutTool: ToolWithMetadata = {
  name: 'git_checkout',
  description: loadDescription('git_checkout'),
  metadata: {
    name: 'git_checkout',
    category: 'git',
    description: '切换分支或恢复文件',
    keywords: ['git', 'checkout', 'switch', '切换', '分支', 'restore', '恢复'],
    deferLoading: false,
  },
  parameters: {
    target: {
      type: 'string',
      description: '目标分支名或文件路径',
      required: true,
    },
    create: {
      type: 'boolean',
      description: '创建新分支并切换（-b）',
      required: false,
    },
    force: {
      type: 'boolean',
      description: '强制切换（丢弃本地修改）',
      required: false,
    },
    file: {
      type: 'boolean',
      description: '目标是文件路径（恢复文件到 HEAD 状态）',
      required: false,
    },
  },
  execute: async (params: Record<string, unknown>): Promise<ToolResult> => {
    const target = params.target as string;
    const create = params.create as boolean;
    const force = params.force as boolean;
    const isFile = params.file as boolean;

    if (!target) {
      return {
        success: false,
        output: '',
        error: '请指定目标分支名或文件路径（target 参数）',
      };
    }

    // 权限检查
    const permissionManager = getPermissionManager();
    const permResult = await permissionManager.checkGitPermission({
      operation: 'checkout',
      target,
      force,
    });

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

    try {
      const args: string[] = ['checkout'];

      if (create) {
        args.push('-b');
      }

      if (force) {
        args.push('-f');
      }

      if (isFile) {
        args.push('--', target);
      } else {
        args.push(target);
      }

      const { stdout, stderr } = await execAsync(`git ${args.join(' ')}`, {
        cwd: process.cwd(),
        timeout: 30000,
      });

      // 切换分支成功的提示通常在 stderr
      const output = stdout || stderr || `已切换到 ${target}`;

      return {
        success: true,
        output,
      };
    } catch (error) {
      const execError = error as { stdout?: string; stderr?: string; message: string };
      const errorMsg = execError.stderr || execError.message;

      // 检查常见错误
      if (errorMsg.includes('local changes') || errorMsg.includes('would be overwritten')) {
        return {
          success: false,
          output: execError.stdout || '',
          error: `本地有未提交的变更会被覆盖。请先提交或暂存（git_stash）变更，或使用 force: true 强制切换（会丢失本地修改）。\n${errorMsg}`,
        };
      }

      if (errorMsg.includes('did not match') || errorMsg.includes('pathspec')) {
        return {
          success: false,
          output: execError.stdout || '',
          error: `找不到分支或文件: ${target}\n${errorMsg}`,
        };
      }

      return {
        success: false,
        output: execError.stdout || '',
        error: errorMsg,
      };
    }
  },
};
