// SPEC-597-EXEMPT: canonical mapping (npm-package↔framework, keyword catalogue)
// — must enumerate framework names by design; no detection logic to migrate.
// engine/detectors/template-engine-detector.ts — SPEC-043
// Detects server-side template engines by ecosystem.
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { glob } from 'glob';
// === Detector registry ===
const TEMPLATE_ENGINE_SIGNALS = [
    // Python
    {
        name: 'jinja2',
        extensions: ['jinja2', 'j2'],
        depFiles: [{ file: 'requirements.txt', contains: 'Jinja2' }],
    },
    {
        name: 'django-templates',
        extensions: ['html'],
        depFiles: [{ file: 'requirements.txt', contains: 'Django' }],
    },
    // Ruby
    {
        name: 'erb',
        extensions: ['erb'],
        depFiles: [{ file: 'Gemfile', contains: 'rails' }],
    },
    // PHP
    {
        name: 'blade',
        extensions: ['blade.php'],
        depFiles: [{ file: 'composer.json', contains: 'laravel/framework' }],
    },
    {
        name: 'twig',
        extensions: ['twig'],
        depFiles: [{ file: 'composer.json', contains: 'twig/twig' }],
    },
    // Go
    {
        name: 'go-templates',
        extensions: ['templ'],
    },
    // Java/Spring — detected via pom.xml only (html extension is too generic)
    {
        name: 'thymeleaf',
        depFiles: [{ file: 'pom.xml', contains: 'thymeleaf' }],
        xmlTags: ['th:text', 'th:each', 'th:if'],
    },
    // JavaScript/Node
    {
        name: 'handlebars',
        extensions: ['hbs', 'handlebars'],
        depPackages: ['handlebars', 'express-handlebars'],
    },
    {
        name: 'nunjucks',
        extensions: ['njk', 'nunjucks'],
        depPackages: ['nunjucks'],
    },
    {
        name: 'pug',
        extensions: ['pug', 'jade'],
        depPackages: ['pug'],
    },
    {
        name: 'ejs',
        extensions: ['ejs'],
        depPackages: ['ejs'],
    },
];
// === File helpers ===
async function readText(filePath) {
    try {
        return await readFile(filePath, 'utf-8');
    }
    catch {
        return null;
    }
}
async function hasFilesWithExtension(projectPath, ext) {
    try {
        const matches = await glob(`**/*.${ext}`, {
            cwd: projectPath,
            nodir: true,
            maxDepth: 4,
            ignore: ['node_modules/**', 'dist/**', 'build/**', '.git/**', 'vendor/**'],
        });
        return matches.length > 0;
    }
    catch {
        return false;
    }
}
async function readPackageJsonDeps(projectPath) {
    const deps = new Set();
    const content = await readText(join(projectPath, 'package.json'));
    if (!content) {
        return deps;
    }
    try {
        const pkg = JSON.parse(content);
        for (const dep of Object.keys(pkg.dependencies ?? {})) {
            deps.add(dep);
        }
        for (const dep of Object.keys(pkg.devDependencies ?? {})) {
            deps.add(dep);
        }
    }
    catch {
        // Unparseable — skip
    }
    return deps;
}
/**
 * Detect Go templates specifically via {{ }} syntax in HTML files.
 */
async function detectGoTemplates(projectPath) {
    try {
        const matches = await glob('**/*.html', {
            cwd: projectPath,
            nodir: true,
            maxDepth: 4,
            ignore: ['node_modules/**', 'dist/**', 'build/**', 'vendor/**'],
        });
        for (const file of matches) {
            const content = await readText(join(projectPath, file));
            if (content && /\{\{[\s-]*\.?\w+/.test(content)) {
                // Go template syntax: {{ .Field }} or {{- .Field -}}
                return true;
            }
        }
    }
    catch {
        // Skip
    }
    return false;
}
/**
 * Detect the primary template engine used in a project.
 * Returns the engine name (e.g. 'jinja2', 'erb', 'blade') or null if none found.
 */
export async function detectTemplateEngine(projectPath) {
    const nodeDeps = await readPackageJsonDeps(projectPath);
    for (const signal of TEMPLATE_ENGINE_SIGNALS) {
        // Check npm deps (Node.js engines)
        if (signal.depPackages?.some((pkg) => nodeDeps.has(pkg))) {
            return signal.name;
        }
        // Check dep files (requirements.txt, Gemfile, composer.json, pom.xml)
        if (signal.depFiles) {
            for (const { file, contains } of signal.depFiles) {
                const content = await readText(join(projectPath, file));
                if (content?.includes(contains)) {
                    return signal.name;
                }
            }
        }
        // Check file extensions (skip Go — handled separately below)
        if (signal.extensions && signal.name !== 'go-templates' && signal.name !== 'django-templates') {
            for (const ext of signal.extensions) {
                if (await hasFilesWithExtension(projectPath, ext)) {
                    return signal.name;
                }
            }
        }
    }
    // Go templates: check for .templ files (typed Go templates) or {{ }} syntax in HTML
    if ((await hasFilesWithExtension(projectPath, 'templ')) ||
        (await detectGoTemplates(projectPath))) {
        return 'go-templates';
    }
    return null;
}
//# sourceMappingURL=template-engine-detector.js.map