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';

/**
 * 简单的 glob 模式匹配
 * 支持 ** (任意目录) 和 * (任意字符)
 */
function globToRegex(pattern: string): RegExp {
  // 转义正则特殊字符，但保留 * 和 **
  let regexStr = pattern
    .replace(/[.+^${}()|[\]\\]/g, '\\$&') // 转义特殊字符
    .replace(/\*\*/g, '{{GLOBSTAR}}') // 临时替换 **
    .replace(/\*/g, '[^/]*') // * 匹配非 / 字符
    .replace(/\?/g, '[^/]') // ? 匹配单个非 / 字符
    .replace(/\{\{GLOBSTAR\}\}/g, '.*'); // ** 匹配任意字符包括 /

  return new RegExp(`^${regexStr}$`, 'i');
}

/**
 * 检查是否应该忽略的目录/文件
 */
function shouldIgnore(name: string): boolean {
  const ignorePatterns = [
    'node_modules',
    '.git',
    '.svn',
    '.hg',
    'dist',
    'build',
    'coverage',
    '.cache',
    '.vscode',
    '.idea',
    '__pycache__',
    '.pytest_cache',
    '.mypy_cache',
    'venv',
    '.venv',
    'target', // Rust
    'vendor', // Go
  ];
  return name.startsWith('.') || ignorePatterns.includes(name);
}

interface FileInfo {
  path: string;
  mtime: number;
}

export const globTool: ToolWithMetadata = {
  name: 'glob',
  description: loadDescription('glob'),
  metadata: {
    name: 'glob',
    category: 'filesystem',
    description: '使用 glob 模式匹配文件',
    keywords: ['glob', 'pattern', 'match', 'file', 'search', '模式', '匹配', '文件'],
    deferLoading: false, // 常用工具，不延迟加载
  },
  parameters: {
    pattern: {
      type: 'string',
      description: '要匹配的 glob 模式（如 "**/*.ts" 或 "src/**/*.js"）',
      required: true,
    },
    path: {
      type: 'string',
      description:
        '搜索的目录。如果不指定，使用当前工作目录。重要：省略此字段使用默认目录，不要输入 "undefined" 或 "null"。',
      required: false,
    },
  },
  execute: async (params: Record<string, unknown>): Promise<ToolResult> => {
    const pattern = params.pattern as string;
    const searchPath = params.path as string | undefined;
    const cwd = process.cwd();

    // 解析搜索目录
    let searchDir: string;
    if (searchPath) {
      searchDir = path.isAbsolute(searchPath) ? searchPath : path.resolve(cwd, searchPath);
    } else {
      searchDir = cwd;
    }

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

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

    const limit = 100;
    const files: FileInfo[] = [];
    let truncated = false;

    // 编译 glob 模式
    const regex = globToRegex(pattern);

    async function searchRecursive(dir: string, relativePath: string = ''): Promise<void> {
      if (files.length >= limit) {
        truncated = true;
        return;
      }

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

        for (const entry of entries) {
          if (files.length >= limit) {
            truncated = true;
            return;
          }

          const entryRelPath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
          const fullPath = path.join(dir, entry.name);

          if (entry.isDirectory()) {
            // 忽略特定目录
            if (!shouldIgnore(entry.name)) {
              await searchRecursive(fullPath, entryRelPath);
            }
          } else {
            // 检查文件是否匹配模式
            if (regex.test(entryRelPath)) {
              try {
                const stat = await fs.stat(fullPath);
                files.push({
                  path: fullPath,
                  mtime: stat.mtimeMs,
                });
              } catch {
                // 忽略无法访问的文件
                files.push({
                  path: fullPath,
                  mtime: 0,
                });
              }
            }
          }
        }
      } catch {
        // 忽略权限错误等
      }
    }

    try {
      // 检查搜索目录是否存在
      const dirStat = await fs.stat(searchDir);
      if (!dirStat.isDirectory()) {
        return {
          success: false,
          output: '',
          error: `路径不是目录: ${searchDir}`,
        };
      }

      await searchRecursive(searchDir);

      // 按修改时间排序（最新的在前）
      files.sort((a, b) => b.mtime - a.mtime);

      const output: string[] = [];

      if (files.length === 0) {
        output.push('No files found');
      } else {
        output.push(...files.map((f) => f.path));
        if (truncated) {
          output.push('');
          output.push('(Results are truncated. Consider using a more specific path or pattern.)');
        }
      }

      return {
        success: true,
        output: output.join('\n'),
      };
    } catch (error) {
      return {
        success: false,
        output: '',
        error: error instanceof Error ? error.message : String(error),
      };
    }
  },
};
