import * as fs from 'fs/promises';
import * as path from 'path';
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';

interface GrepMatch {
  file: string;
  line: number;
  content: string;
}

export const grepContentTool: ToolWithMetadata = {
  name: 'grep_content',
  description: loadDescription('grep_content'),
  metadata: {
    name: 'grep_content',
    category: 'filesystem',
    description: '在文件内容中搜索文本',
    keywords: ['grep', 'search', 'content', 'text', 'find', 'regex', '搜索', '内容', '文本', '查找', '正则'],
    deferLoading: true,
  },
  parameters: {
    directory: {
      type: 'string',
      description: '搜索的起始目录',
      required: true,
    },
    pattern: {
      type: 'string',
      description: '搜索的文本或正则表达式模式',
      required: true,
    },
    file_pattern: {
      type: 'string',
      description: '文件名匹配模式（可选，如 *.ts）',
      required: false,
    },
    max_results: {
      type: 'number',
      description: '最大结果数量（可选，默认 100）',
      required: false,
    },
  },
  execute: async (params: Record<string, unknown>): Promise<ToolResult> => {
    const directory = params.directory as string;
    const pattern = params.pattern as string;
    const filePattern = params.file_pattern as string | undefined;
    const maxResults = (params.max_results as number) || 100;
    const cwd = process.cwd();
    const absolutePath = path.isAbsolute(directory)
      ? directory
      : path.join(cwd, directory);

    // 权限检查
    const permissionManager = getPermissionManager();
    const permResult = await permissionManager.checkFilePermission({
      operation: 'grep',
      path: absolutePath,
      workdir: cwd,
    });

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

    const matches: GrepMatch[] = [];
    const searchRegex = new RegExp(pattern, 'gi');
    const fileRegex = filePattern
      ? new RegExp(filePattern.replace(/\*/g, '.*').replace(/\?/g, '.'), 'i')
      : null;

    async function searchFile(filePath: string): Promise<void> {
      if (matches.length >= maxResults) return;

      try {
        const content = await fs.readFile(filePath, 'utf-8');
        const lines = content.split('\n');

        for (let i = 0; i < lines.length; i++) {
          if (matches.length >= maxResults) break;

          if (searchRegex.test(lines[i])) {
            matches.push({
              file: filePath,
              line: i + 1,
              content: lines[i].trim().substring(0, 200), // 截断过长的行
            });
          }
          // 重置正则表达式的 lastIndex
          searchRegex.lastIndex = 0;
        }
      } catch {
        // 忽略无法读取的文件（如二进制文件）
      }
    }

    async function searchDirectory(dir: string, depth = 0): Promise<void> {
      if (depth > 10 || matches.length >= maxResults) return;

      try {
        const entries = await fs.readdir(dir, { withFileTypes: true });

        for (const entry of entries) {
          if (matches.length >= maxResults) break;

          const fullPath = path.join(dir, entry.name);

          // 跳过隐藏文件和 node_modules
          if (entry.name.startsWith('.') || entry.name === 'node_modules') {
            continue;
          }

          if (entry.isDirectory()) {
            await searchDirectory(fullPath, depth + 1);
          } else if (entry.isFile()) {
            // 检查文件名是否匹配
            if (fileRegex && !fileRegex.test(entry.name)) {
              continue;
            }
            await searchFile(fullPath);
          }
        }
      } catch {
        // 忽略权限错误
      }
    }

    try {
      await searchDirectory(absolutePath);

      if (matches.length === 0) {
        return {
          success: true,
          output: '没有找到匹配的内容',
        };
      }

      const output = matches
        .map((m) => `${m.file}:${m.line}: ${m.content}`)
        .join('\n');

      return {
        success: true,
        output: `找到 ${matches.length} 处匹配${matches.length >= maxResults ? '（已达上限）' : ''}:\n\n${output}`,
      };
    } catch (error) {
      return {
        success: false,
        output: '',
        error: error instanceof Error ? error.message : String(error),
      };
    }
  },
};
