import path from 'node:path';
import { readFile } from 'node:fs/promises';
function isSourceNode(node) {
    return node.type !== 'file' && node.type !== 'module' && node.external !== true;
}
function candidateFromNode(node) {
    return {
        nodeId: node.id,
        name: node.name,
        type: node.type,
        path: node.path,
        relativePath: node.relativePath,
        line: node.line,
        endLine: node.endLine,
        containerName: node.containerName,
    };
}
function resolveWithinRepo(repoRoot, targetPath) {
    const root = path.resolve(repoRoot);
    const resolved = path.isAbsolute(targetPath) ? path.resolve(targetPath) : path.resolve(root, targetPath);
    const relativePath = path.relative(root, resolved);
    if (relativePath === '' || relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
        return `Resolved path "${targetPath}" is outside repo root "${root}".`;
    }
    return {
        path: resolved,
        relativePath: relativePath.split(path.sep).join('/'),
    };
}
function findParsedFile(index, node) {
    const resolvedNodePath = path.resolve(node.path);
    return index.files.find(file => path.resolve(file.path) === resolvedNodePath);
}
async function readFileLines(file, filePath) {
    if (file?.lines)
        return file.lines;
    if (file?.content != null)
        return file.content.split(/\r?\n/);
    return (await readFile(filePath, 'utf8')).split(/\r?\n/);
}
function selectByQuery(index, query) {
    if ('nodeId' in query) {
        return index.nodes.filter(node => node.id === query.nodeId && isSourceNode(node));
    }
    let resolvedFile;
    if (query.file) {
        const resolved = resolveWithinRepo(index.repoRoot, query.file);
        if (typeof resolved === 'string')
            return resolved;
        resolvedFile = resolved.path;
    }
    return index.nodes.filter(node => {
        if (!isSourceNode(node))
            return false;
        if (node.name !== query.name)
            return false;
        if (query.type && node.type !== query.type)
            return false;
        return !resolvedFile || path.resolve(node.path) === resolvedFile;
    });
}
export async function readCodeSource(index, query, _options = {}) {
    const selected = selectByQuery(index, query);
    if (typeof selected === 'string') {
        return { status: 'error', message: selected };
    }
    if (selected.length === 0) {
        return { status: 'not_found', candidates: [], message: 'No matching source node was found.' };
    }
    if (selected.length > 1) {
        return {
            status: 'ambiguous',
            candidates: selected.map(candidateFromNode),
            message: `Found ${selected.length} matching source nodes.`,
        };
    }
    const node = selected[0];
    if (node.line == null) {
        return { status: 'error', message: `Node "${node.id}" does not have a source line.` };
    }
    const resolved = resolveWithinRepo(index.repoRoot, node.path);
    if (typeof resolved === 'string') {
        return { status: 'error', message: resolved };
    }
    const endLine = node.endLine ?? node.line;
    const file = findParsedFile(index, node);
    const lines = await readFileLines(file, resolved.path);
    const source = lines.slice(node.line - 1, endLine).join('\n');
    return {
        status: 'resolved',
        nodeId: node.id,
        name: node.name,
        type: node.type,
        path: resolved.path,
        relativePath: node.relativePath ?? resolved.relativePath,
        line: node.line,
        endLine,
        containerName: node.containerName,
        source,
    };
}
//# sourceMappingURL=source.js.map