import { glob } from "glob";
import { stat } from "fs/promises";
import { resolvePath, getDisplayPath } from "../utils/path.js";
import { GLOB_TOOL_NAME } from "../constants/tools.js";
/**
 * Maximum number of files returned by glob tool
 */
const MAX_GLOB_RESULTS = 100;
/**
 * Glob Tool Plugin - Fast file pattern matching
 */
export const globTool = {
    name: GLOB_TOOL_NAME,
    config: {
        type: "function",
        function: {
            name: GLOB_TOOL_NAME,
            description: "Fast file pattern matching tool that works with any codebase size",
            parameters: {
                type: "object",
                properties: {
                    pattern: {
                        type: "string",
                        description: "The glob pattern to match files against",
                    },
                    path: {
                        type: "string",
                        description: 'The directory to search in. If not specified, the current working directory will be used. IMPORTANT: Omit this field to use the default directory. DO NOT enter "undefined" or "null" - simply omit it for the default behavior. Must be a valid directory path if provided.',
                    },
                    limit: {
                        type: "number",
                        description: "Maximum number of files to return. Defaults to 100.",
                    },
                },
                required: ["pattern"],
            },
        },
    },
    prompt: () => `- Fast file pattern matching tool that works with any codebase size
- Supports glob patterns like "**/*.js" or "src/**/*.ts"
- Returns matching file paths sorted by modification time
- Use this tool when you need to find files by name patterns
- When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead
- You can call multiple tools in a single response. It is always better to speculatively perform multiple searches in parallel if they are potentially useful.`,
    execute: async (args, context) => {
        const pattern = args.pattern;
        const searchPath = args.path;
        const limit = args.limit || MAX_GLOB_RESULTS;
        const startTime = Date.now();
        if (!pattern || typeof pattern !== "string") {
            return {
                success: false,
                content: "",
                error: "pattern parameter is required and must be a string",
            };
        }
        try {
            // Determine search directory
            const workdir = searchPath
                ? resolvePath(searchPath, context.workdir)
                : context.workdir;
            // Execute glob search using glob package
            const matches = await glob(pattern, {
                cwd: workdir,
                nodir: true,
                dot: true,
                ignore: ["**/.git/**"],
            });
            if (matches.length === 0) {
                return {
                    success: true,
                    content: "No files match the pattern",
                    shortResult: "No matches found",
                };
            }
            // Get file modification time and sort
            const filesWithStats = await Promise.allSettled(matches.map(async (file) => {
                try {
                    const fullPath = resolvePath(file, workdir);
                    const stats = await stat(fullPath);
                    return {
                        path: file,
                        mtime: stats.mtime,
                    };
                }
                catch {
                    // If unable to get file stats, use current time
                    return {
                        path: file,
                        mtime: new Date(),
                    };
                }
            }));
            // Filter successful results and sort by modification time
            const sortedFiles = filesWithStats
                .filter((result) => result.status === "fulfilled")
                .map((result) => result
                .value)
                .sort((a, b) => b.mtime.getTime() - a.mtime.getTime()) // Most recently modified files first
                .map((item) => item.path);
            const totalCount = sortedFiles.length;
            const finalFiles = sortedFiles.slice(0, limit);
            // Format output
            const output = finalFiles
                .map((file, index) => `${index + 1}. ${file}`)
                .join("\n");
            const isTruncated = totalCount > limit;
            const shortResult = isTruncated
                ? `Found ${totalCount} files (showing first ${limit})`
                : `Found ${totalCount} file${totalCount === 1 ? "" : "s"}`;
            const durationMs = Date.now() - startTime;
            return {
                success: true,
                content: output,
                shortResult,
                metadata: {
                    durationMs,
                    numFiles: totalCount,
                    truncated: isTruncated,
                },
            };
        }
        catch (error) {
            return {
                success: false,
                content: "",
                error: `Glob search failed: ${error instanceof Error ? error.message : String(error)}`,
            };
        }
    },
    formatCompactParams: (params, context) => {
        const pattern = params.pattern;
        const path = params.path;
        if (path) {
            const displayPath = getDisplayPath(path, context.workdir);
            return `${pattern} in ${displayPath}`;
        }
        return pattern || "";
    },
};
