// Planu — Web Fetcher: Stack Detection from text and file paths (SPEC-382)
// SPEC-597-EXEMPT: regex patterns + canonical labels for free-form text scanning.
// Different surface than detection-signals.json (which targets project files,
// not free-text web content). Migration pending a unified detection registry.
// ~50 well-known technologies with their normalized names
const KNOWN_TECHS = [
    { pattern: /\bnext\.?js\b/i, normalized: 'next.js' },
    { pattern: /\breact\b/i, normalized: 'react' },
    { pattern: /\bvue\.?js\b|\bvuejs\b/i, normalized: 'vue' },
    { pattern: /\bangular\b/i, normalized: 'angular' },
    { pattern: /\bsvelte\b/i, normalized: 'svelte' },
    { pattern: /\bastro\b/i, normalized: 'astro' },
    { pattern: /\bremix\b/i, normalized: 'remix' },
    { pattern: /\bsolid\.?js\b|\bsolidjs\b/i, normalized: 'solid.js' },
    { pattern: /\bqwik\b/i, normalized: 'qwik' },
    { pattern: /\bnuxt\b/i, normalized: 'nuxt' },
    { pattern: /\bgatsbyjs\b|\bgatsby\b/i, normalized: 'gatsby' },
    { pattern: /\bexpress\.?js\b|\bexpressjs\b/i, normalized: 'express' },
    { pattern: /\bhono\b/i, normalized: 'hono' },
    { pattern: /\bfastify\b/i, normalized: 'fastify' },
    { pattern: /\bkoa\b/i, normalized: 'koa' },
    { pattern: /\bnestjs\b|\bnest\.js\b/i, normalized: 'nestjs' },
    { pattern: /\bdjango\b/i, normalized: 'django' },
    { pattern: /\bflask\b/i, normalized: 'flask' },
    { pattern: /\bfastapi\b/i, normalized: 'fastapi' },
    { pattern: /\brails\b|\bruby on rails\b/i, normalized: 'rails' },
    { pattern: /\blaravel\b/i, normalized: 'laravel' },
    { pattern: /\bspring boot\b|\bspringboot\b/i, normalized: 'spring' },
    { pattern: /\bgin\b.{0,10}\bgo\b|\bgo\b.{0,10}\bgin\b/i, normalized: 'gin' },
    { pattern: /\bfiber\b.{0,10}\bgo\b|\bgo\b.{0,10}\bfiber\b/i, normalized: 'fiber' },
    { pattern: /\btypescript\b/i, normalized: 'typescript' },
    { pattern: /\bjavascript\b/i, normalized: 'javascript' },
    { pattern: /\bpython\b/i, normalized: 'python' },
    { pattern: /\bgolang\b|\bgo lang\b|\b(?:^|\s)go(?:\s|$)\b/i, normalized: 'go' },
    { pattern: /\brust\b/i, normalized: 'rust' },
    { pattern: /\bjava\b/i, normalized: 'java' },
    { pattern: /\bkotlin\b/i, normalized: 'kotlin' },
    { pattern: /\bswift\b/i, normalized: 'swift' },
    { pattern: /\bflutter\b/i, normalized: 'flutter' },
    { pattern: /\bexpo\b/i, normalized: 'expo' },
    { pattern: /\breact native\b|\breact-native\b/i, normalized: 'react-native' },
    { pattern: /\bpostgresql\b|\bpostgres\b/i, normalized: 'postgresql' },
    { pattern: /\bmysql\b/i, normalized: 'mysql' },
    { pattern: /\bmongodb\b|\bmongo\b/i, normalized: 'mongodb' },
    { pattern: /\bsqlite\b/i, normalized: 'sqlite' },
    { pattern: /\bsupabase\b/i, normalized: 'supabase' },
    { pattern: /\bfirebase\b/i, normalized: 'firebase' },
    { pattern: /\bprisma\b/i, normalized: 'prisma' },
    { pattern: /\bdrizzle\b/i, normalized: 'drizzle' },
    { pattern: /\btailwind\b/i, normalized: 'tailwind' },
    { pattern: /\bvite\b/i, normalized: 'vite' },
    { pattern: /\bvitest\b/i, normalized: 'vitest' },
    { pattern: /\bjest\b/i, normalized: 'jest' },
    { pattern: /\bdocker\b/i, normalized: 'docker' },
    { pattern: /\bkubernetes\b|\bk8s\b/i, normalized: 'kubernetes' },
    { pattern: /\bstripe\b/i, normalized: 'stripe' },
    { pattern: /\bgraphql\b/i, normalized: 'graphql' },
    { pattern: /\btrpc\b/i, normalized: 'trpc' },
    { pattern: /\bzod\b/i, normalized: 'zod' },
    { pattern: /\bprisma\b/i, normalized: 'prisma' },
];
// npm package pattern: word with hyphen or scoped (@scope/pkg)
const NPM_PACKAGE_RE = /(?:^|\s)((?:@[\w-]+\/[\w-]+|[\w][\w-]{1,}))(?=\s|$)/g;
function extractContext(text, match) {
    const idx = match.index ?? 0;
    const matchLen = match[0].length;
    const start = Math.max(0, idx - 20);
    const end = Math.min(text.length, idx + matchLen + 20);
    return text.slice(start, end).trim();
}
function normalizeText(text) {
    return text.replace(/\s+/g, ' ').trim();
}
export function detectTechsFromText(text) {
    const normalized = normalizeText(text);
    const found = new Map();
    for (const { pattern, normalized: techName } of KNOWN_TECHS) {
        if (found.has(techName)) {
            continue;
        }
        const match = normalized.match(pattern);
        if (match) {
            found.set(techName, {
                name: techName,
                confidence: 'high',
                context: extractContext(normalized, match),
            });
        }
    }
    // Also detect npm package patterns with medium confidence (not already detected)
    const npmMatches = [...normalized.matchAll(NPM_PACKAGE_RE)];
    for (const match of npmMatches) {
        const pkg = match[1];
        if (!pkg) {
            continue;
        }
        const pkgNorm = pkg.toLowerCase();
        // Skip if already captured by known techs or too short
        if (found.has(pkgNorm) || pkgNorm.length < 3) {
            continue;
        }
        // Only include if it looks like a package (has hyphen or slash → scoped)
        if (pkg.includes('-') || pkg.includes('/')) {
            found.set(pkgNorm, {
                name: pkgNorm,
                confidence: 'low',
                context: extractContext(normalized, match),
            });
        }
    }
    return [...found.values()];
}
const FILE_TECH_MAP = [
    { pattern: /package\.json$/, name: 'node', confidence: 'high' },
    { pattern: /next\.config\.[cm]?[jt]s$/, name: 'next.js', confidence: 'high' },
    { pattern: /vite\.config\.[cm]?[jt]s$/, name: 'vite', confidence: 'high' },
    { pattern: /vitest\.config\.[cm]?[jt]s$/, name: 'vitest', confidence: 'high' },
    { pattern: /astro\.config\.[cm]?[jt]s$/, name: 'astro', confidence: 'high' },
    { pattern: /remix\.config\.[cm]?[jt]s$/, name: 'remix', confidence: 'high' },
    { pattern: /svelte\.config\.[cm]?[jt]s$/, name: 'svelte', confidence: 'high' },
    { pattern: /nuxt\.config\.[cm]?[jt]s$/, name: 'nuxt', confidence: 'high' },
    { pattern: /tailwind\.config\.[cm]?[jt]s$/, name: 'tailwind', confidence: 'high' },
    { pattern: /prisma\/schema\.prisma$|\.prisma$/, name: 'prisma', confidence: 'high' },
    { pattern: /drizzle\.config\.[cm]?[jt]s$/, name: 'drizzle', confidence: 'high' },
    { pattern: /Dockerfile$|docker-compose\.ya?ml$/, name: 'docker', confidence: 'high' },
    { pattern: /requirements\.txt$|setup\.py$|pyproject\.toml$/, name: 'python', confidence: 'high' },
    { pattern: /go\.mod$|go\.sum$/, name: 'go', confidence: 'high' },
    { pattern: /Cargo\.toml$|Cargo\.lock$/, name: 'rust', confidence: 'high' },
    { pattern: /pom\.xml$|build\.gradle$/, name: 'java', confidence: 'high' },
    { pattern: /tsconfig\.json$/, name: 'typescript', confidence: 'high' },
    { pattern: /\.tsx?$/, name: 'typescript', confidence: 'medium' },
    { pattern: /\.vue$/, name: 'vue', confidence: 'high' },
    { pattern: /\.svelte$/, name: 'svelte', confidence: 'high' },
    { pattern: /\.tsx$/, name: 'react', confidence: 'medium' },
    { pattern: /\.jsx$/, name: 'react', confidence: 'medium' },
    { pattern: /\.py$/, name: 'python', confidence: 'medium' },
    { pattern: /\.go$/, name: 'go', confidence: 'medium' },
    { pattern: /\.rs$/, name: 'rust', confidence: 'medium' },
    { pattern: /\.kt$/, name: 'kotlin', confidence: 'medium' },
    { pattern: /\.swift$/, name: 'swift', confidence: 'medium' },
    { pattern: /\.dart$/, name: 'flutter', confidence: 'medium' },
];
export function detectTechsFromFiles(fileList) {
    const found = new Map();
    for (const filePath of fileList) {
        for (const { pattern, name, confidence } of FILE_TECH_MAP) {
            if (!found.has(name) && pattern.test(filePath)) {
                found.set(name, {
                    name,
                    confidence,
                    context: filePath,
                });
            }
        }
    }
    return [...found.values()];
}
//# sourceMappingURL=stack-detector.js.map