import { appendSchemaFingerprint } from '../shared/schema-fingerprint.js';
import { findSchema } from './schema.js';
import { executeFilesQuery } from './files.js';
import { executeContentQuery } from './content.js';
import { executeReferencesQuery } from './references.js';
import { executeStructuralQuery } from './structural.js';
import { executeSymbolsQuery } from './symbols.js';
import { FindRuntimeService } from './shared.js';
import { summarizeError } from '../../utils/error-display.js';
import { mapWithConcurrency } from '../../utils/concurrency.js';
const MAX_FIND_QUERIES = 20;
const MAX_PARALLEL_FIND_QUERIES = 5;
export function createFindTool(projectRoot, featureFlags, runtime = new FindRuntimeService()) {
    if (typeof projectRoot !== 'string' || projectRoot.trim().length === 0) {
        throw new Error('createFindTool requires projectRoot');
    }
    return {
        definition: findSchema,
        async execute(args) {
            try {
                if (!Array.isArray(args.queries) || args.queries.length === 0) {
                    return { success: false, error: 'Missing or empty "queries" array' };
                }
                if (args.queries.length > MAX_FIND_QUERIES) {
                    return { success: false, error: `Too many queries: maximum ${MAX_FIND_QUERIES} per find call` };
                }
                const input = args;
                const output = input.output ?? {};
                const parallel = input.parallel !== false;
                const runQuery = async (query) => {
                    let result;
                    switch (query.mode) {
                        case 'files':
                            result = await executeFilesQuery(query, output, projectRoot);
                            break;
                        case 'content':
                            result = await executeContentQuery(query, output, runtime, projectRoot);
                            break;
                        case 'symbols':
                            result = await executeSymbolsQuery(query, output, projectRoot);
                            break;
                        case 'references':
                            result = await executeReferencesQuery(query, output, projectRoot);
                            break;
                        case 'structural':
                            result = await executeStructuralQuery(query, output, projectRoot);
                            break;
                        default: {
                            const exhaustive = query;
                            result = { error: `Unknown mode: ${exhaustive.mode}` };
                        }
                    }
                    return [query.id, appendSchemaFingerprint(result, 'find', query.mode, { featureFlags })];
                };
                let pairs;
                if (parallel) {
                    pairs = await mapWithConcurrency(input.queries, MAX_PARALLEL_FIND_QUERIES, runQuery);
                }
                else {
                    pairs = [];
                    for (const query of input.queries) {
                        pairs.push(await runQuery(query));
                    }
                }
                const results = {};
                for (const [id, result] of pairs) {
                    results[id] = result;
                }
                const finalResults = input.queries.length > 1
                    ? appendSchemaFingerprint(results, 'find', 'multi', { featureFlags })
                    : results;
                return { success: true, output: JSON.stringify(finalResults) };
            }
            catch (err) {
                return {
                    success: false,
                    error: summarizeError(err),
                };
            }
        },
    };
}
