// SPEC-597-EXEMPT: canonical mapping (npm-package↔framework, keyword catalogue)
// — must enumerate framework names by design; no detection logic to migrate.
// Planu — Extended manifest readers: rubygems, nuget, pub, swiftpm (SPEC-054)
// All file I/O via node:fs/promises — no live API calls.
import { readFile } from 'node:fs/promises';
import { glob } from 'glob';
import { extractMajor } from './manifest-readers.js';
/** Read Gemfile and return gem→installedMajor for gems with a version constraint. */
export async function readRubygemsManifest(projectPath) {
    const result = new Map();
    try {
        const raw = await readFile(`${projectPath}/Gemfile`, 'utf-8');
        for (const line of raw.split('\n')) {
            const trimmed = line.trim();
            if (trimmed.startsWith('#')) {
                continue;
            }
            // Match: gem 'rails', '~> 7.1'  or  gem "devise", ">= 4.9"  (with version constraint)
            const match = /^\s*gem\s+['"]([^'"]+)['"]\s*(?:,\s*['"]([^'"]+)['"])?/.exec(trimmed);
            if (!match) {
                continue;
            }
            /* v8 ignore start */
            const name = match[1] ?? '';
            const versionConstraint = match[2] ?? '';
            /* v8 ignore stop */
            if (!name || !versionConstraint) {
                // Skip gems without version constraint
                continue;
            }
            const major = extractMajor(versionConstraint);
            if (major !== null && !result.has(name)) {
                result.set(name, major);
            }
        }
    }
    catch {
        // File missing or invalid
    }
    return result;
}
/** Read *.csproj and packages.config files and return package→installedMajor. */
export async function readNugetManifest(projectPath) {
    const result = new Map();
    try {
        const csprojFiles = await glob('**/*.csproj', { cwd: projectPath, nodir: true });
        for (const relPath of csprojFiles) {
            const raw = await readFile(`${projectPath}/${relPath}`, 'utf-8');
            const matches = raw.matchAll(/<PackageReference\s+Include="([^"]+)"\s+Version="([^"]+)"/gi);
            for (const match of matches) {
                /* v8 ignore start */
                const name = match[1] ?? '';
                const ver = match[2] ?? '';
                /* v8 ignore stop */
                const major = extractMajor(ver);
                if (name && major !== null && !result.has(name)) {
                    result.set(name, major);
                }
            }
        }
    }
    catch {
        // Glob or file read error
    }
    // Also try packages.config for older .NET projects
    try {
        const raw = await readFile(`${projectPath}/packages.config`, 'utf-8');
        const matches = raw.matchAll(/<package\s+id="([^"]+)"\s+version="([^"]+)"/gi);
        for (const match of matches) {
            /* v8 ignore start */
            const name = match[1] ?? '';
            const ver = match[2] ?? '';
            /* v8 ignore stop */
            const major = extractMajor(ver);
            if (name && major !== null && !result.has(name)) {
                result.set(name, major);
            }
        }
    }
    catch {
        // File missing or invalid
    }
    return result;
}
/** Read pubspec.yaml and return package→installedMajor (Dart/Flutter). */
export async function readPubManifest(projectPath) {
    const result = new Map();
    try {
        const raw = await readFile(`${projectPath}/pubspec.yaml`, 'utf-8');
        let inDeps = false;
        for (const line of raw.split('\n')) {
            const trimmed = line.trim();
            // Detect dependency sections (must be a top-level key — no leading spaces)
            if (/^dependencies\s*:/.test(line) || /^dev_dependencies\s*:/.test(line)) {
                inDeps = true;
                continue;
            }
            // Any top-level key (no leading whitespace) ends the dependency section
            if (/^\S/.test(line) && trimmed !== '') {
                inDeps = false;
                continue;
            }
            if (!inDeps) {
                continue;
            }
            // Skip SDK constraints (e.g. "    sdk: flutter" or "  flutter_sdk: flutter")
            if (/sdk\s*:/.test(trimmed)) {
                continue;
            }
            // Match "  http: ^1.1.0" or "  provider: '>=6.0.0'"
            // Requires at least 2 spaces of indentation (dep entries under the section header)
            const match = /^(\s{2,})(\w[\w_-]*)\s*:\s*['"]?([^\s'"#]+)['"]?/.exec(line);
            if (!match) {
                continue;
            }
            /* v8 ignore start */
            const name = match[2] ?? '';
            const versionStr = match[3] ?? '';
            /* v8 ignore stop */
            if (!name || !versionStr || versionStr === 'null') {
                continue;
            }
            const major = extractMajor(versionStr);
            if (major !== null && !result.has(name)) {
                result.set(name, major);
            }
        }
    }
    catch {
        // File missing or invalid
    }
    return result;
}
/** Read Package.swift and return package→installedMajor (Swift Package Manager). */
export async function readSwiftPMManifest(projectPath) {
    const result = new Map();
    try {
        const raw = await readFile(`${projectPath}/Package.swift`, 'utf-8');
        for (const line of raw.split('\n')) {
            // Extract version from various SPM dependency syntaxes
            const fromMatch = /\.package\s*\([^)]*from:\s*"([^"]+)"/.exec(line);
            const exactMatch = /\.package\s*\([^)]*\.exact\s*\("([^"]+)"\)/.exec(line);
            const upToNextMajorMatch = /\.package\s*\([^)]*\.upToNextMajor\s*\(from:\s*"([^"]+)"\)/.exec(line);
            const versionStr = fromMatch?.[1] ?? exactMatch?.[1] ?? upToNextMajorMatch?.[1];
            if (!versionStr) {
                continue;
            }
            // Extract package name from URL (last segment without .git, lowercased)
            const urlNameMatch = /\/([^/]+?)(?:\.git)?"/.exec(line);
            /* v8 ignore start */
            const name = urlNameMatch?.[1]?.toLowerCase() ?? '';
            /* v8 ignore stop */
            if (!name) {
                continue;
            }
            const major = extractMajor(versionStr);
            if (major !== null && !result.has(name)) {
                result.set(name, major);
            }
        }
    }
    catch {
        // File missing or invalid
    }
    return result;
}
//# sourceMappingURL=manifest-readers-extended.js.map