// engine/detectors/library-detector-python.ts — Python library detection
// SPEC-004 tech-debt: Reads requirements.txt, pyproject.toml, and setup.py
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
// === Python library catalog ===
const PYTHON_HTTP_LIBS = ['httpx', 'aiohttp', 'requests'];
const PYTHON_DATA_LIBS = ['pandas', 'polars', 'numpy', 'scipy'];
const PYTHON_QUEUE_LIBS = ['celery', 'rq', 'arq', 'dramatiq'];
const PYTHON_AUTH_LIBS = ['python-jose', 'authlib', 'fastapi-users'];
// === Detection helpers ===
function filterPresent(catalog, deps) {
    return catalog.filter((lib) => deps.has(lib));
}
// === Python dependency collection ===
export function parsePythonRequirements(content) {
    const deps = new Set();
    for (const line of content.split('\n')) {
        const trimmed = line.trim();
        if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('-')) {
            continue;
        }
        // Normalize: strip version specifiers and extras, lowercase
        const pkgName = trimmed.split(/[>=<!~\s[]/)[0];
        if (pkgName) {
            deps.add(pkgName.toLowerCase());
        }
    }
    return deps;
}
export function parsePyprojectToml(content) {
    const deps = new Set();
    // Match quoted package names in [project.dependencies] or [tool.poetry.dependencies]
    const matches = content.matchAll(/"([a-zA-Z0-9_-]+)(?:[>=<!~[].*)?"(?:\s*,)?/g);
    for (const match of matches) {
        /* v8 ignore next 2 -- group 1 always present when regex matches */
        if (match[1]) {
            deps.add(match[1].toLowerCase());
        }
    }
    // Also match bare names in array format: "httpx>=0.23"
    const arrayMatches = content.matchAll(/^\s*"([a-zA-Z0-9_-]+)/gm);
    for (const match of arrayMatches) {
        /* v8 ignore next 2 -- group 1 always present when regex matches */
        if (match[1]) {
            deps.add(match[1].toLowerCase());
        }
    }
    return deps;
}
export function parseSetupPy(content) {
    const deps = new Set();
    // Match install_requires list items — use line-bounded [^\n'"] to avoid cross-line greedy matches
    const matches = content.matchAll(/['"]([a-zA-Z0-9_-]+)(?:[>=<!~[][^\n'"]*)?['"]/g);
    for (const match of matches) {
        /* v8 ignore next 2 -- group 1 always present when regex matches */
        if (match[1]) {
            deps.add(match[1].toLowerCase());
        }
    }
    return deps;
}
async function collectRequirementsTxt(projectPath) {
    try {
        const content = await readFile(join(projectPath, 'requirements.txt'), 'utf-8');
        return parsePythonRequirements(content);
    }
    catch {
        return new Set();
    }
}
async function collectPyprojectToml(projectPath) {
    try {
        const content = await readFile(join(projectPath, 'pyproject.toml'), 'utf-8');
        return parsePyprojectToml(content);
    }
    catch {
        return new Set();
    }
}
async function collectSetupPy(projectPath) {
    try {
        const content = await readFile(join(projectPath, 'setup.py'), 'utf-8');
        return parseSetupPy(content);
    }
    catch {
        return new Set();
    }
}
export async function collectAllPythonDeps(projectPath) {
    const [reqDeps, pyprojectDeps, setupDeps] = await Promise.all([
        collectRequirementsTxt(projectPath),
        collectPyprojectToml(projectPath),
        collectSetupPy(projectPath),
    ]);
    return new Set([...reqDeps, ...pyprojectDeps, ...setupDeps]);
}
// === Public API ===
/**
 * Detect popular Python libraries in a project.
 * Reads requirements.txt, pyproject.toml, and setup.py.
 */
export async function detectPythonLibraries(projectPath) {
    const deps = await collectAllPythonDeps(projectPath);
    return {
        http: filterPresent(PYTHON_HTTP_LIBS, deps),
        data: filterPresent(PYTHON_DATA_LIBS, deps),
        queue: filterPresent(PYTHON_QUEUE_LIBS, deps),
        auth: filterPresent(PYTHON_AUTH_LIBS, deps),
    };
}
//# sourceMappingURL=library-detector-python.js.map