// engine/config-health/build-tool-checker.ts — SPEC-050 S3
// Config health checks for build tools (Vite-specific).
// C7: vite.config.ts not in tsconfig include → error
// C8: rolldown bundler + this.emitFile in config → warning
// C9: Vite 7+ with explicit es5/es6 target → info
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { detectBuildTool } from '../build-tool-detector.js';
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
async function readFileSafe(filePath) {
    try {
        return await readFile(filePath, 'utf-8');
    }
    catch {
        return '';
    }
}
function parseVersionMajor(version) {
    if (!version) {
        return null;
    }
    const cleaned = version.replace(/^[^0-9]*/, '');
    const match = /^(\d+)/.exec(cleaned);
    return match !== null ? parseInt(match[1] ?? '0', 10) : null;
}
// ---------------------------------------------------------------------------
// C7: vite.config.ts not covered by tsconfig include patterns
// ---------------------------------------------------------------------------
/**
 * Check that vite.config.ts is covered by tsconfig.json include patterns.
 * If tsconfig has no include array, TypeScript covers all files by default → no finding.
 */
async function checkViteConfigInTsconfig(projectPath) {
    const tsconfigContent = await readFileSafe(join(projectPath, 'tsconfig.json'));
    if (!tsconfigContent) {
        return [];
    }
    let tsconfig;
    try {
        tsconfig = JSON.parse(tsconfigContent);
    }
    catch {
        return [];
    }
    // No include array → TypeScript covers everything by default
    if (!tsconfig.include) {
        return [];
    }
    // Check if vite.config.ts is covered by any include pattern
    const patterns = tsconfig.include;
    const covered = patterns.some((p) => p === 'vite.config.ts' ||
        p === '*.config.ts' ||
        p === '*.ts' ||
        p.endsWith('/**') ||
        p === '**' ||
        p === '**/*.ts');
    if (covered) {
        return [];
    }
    return [
        {
            severity: 'error',
            checker: 'build-tool',
            file: 'tsconfig.json',
            message: 'vite.config.ts not covered by tsconfig — TypeScript will not check build config',
            fix: "Add 'vite.config.ts' or '*.config.ts' to tsconfig.json 'include' array",
        },
    ];
}
// ---------------------------------------------------------------------------
// C8: Rolldown-incompatible plugin (this.emitFile) in vite.config
// ---------------------------------------------------------------------------
/**
 * Scan vite.config content for this.emitFile usage (Rollup hook not supported in Rolldown).
 * Only triggered when bundler is rolldown.
 */
async function checkRolldownPluginCompat(projectPath, configFile) {
    const configContent = await readFileSafe(join(projectPath, configFile));
    if (!configContent) {
        return [];
    }
    if (!configContent.includes('this.emitFile')) {
        return [];
    }
    return [
        {
            severity: 'warning',
            checker: 'build-tool',
            file: configFile,
            message: 'Rollup plugin hook this.emitFile detected — may not be Rolldown-compatible (Rolldown does not implement all Rollup hooks)',
            fix: 'Check the Rolldown plugin compatibility matrix at https://rolldown.rs/contrib-guide/. Pin to Vite 7 if a critical plugin is incompatible.',
        },
    ];
}
// ---------------------------------------------------------------------------
// C9: Vite 7+ with explicit legacy target
// ---------------------------------------------------------------------------
const LEGACY_TARGETS = new Set(['es5', 'es6', 'es2015']);
/**
 * Detect if Vite 7+ config has an explicit legacy build.target that overrides
 * the new baseline-widely-available default.
 */
async function checkVite7LegacyTarget(projectPath, configFile) {
    const configContent = await readFileSafe(join(projectPath, configFile));
    if (!configContent) {
        return [];
    }
    const targetMatch = /build\s*[:{][^}]*target\s*[:=]\s*['"`]([^'"`]+)['"`]/.exec(configContent);
    if (!targetMatch) {
        return [];
    }
    const target = (targetMatch[1] ?? '').toLowerCase();
    if (!LEGACY_TARGETS.has(target)) {
        return [];
    }
    return [
        {
            severity: 'info',
            checker: 'build-tool',
            file: configFile,
            message: `Explicit build target '${target}' overrides Vite 7 baseline-widely-available default`,
            fix: 'Consider removing the explicit target and using @vitejs/plugin-legacy only if you need IE11 support',
        },
    ];
}
// ---------------------------------------------------------------------------
// Main export
// ---------------------------------------------------------------------------
/**
 * Run build-tool health checks by auto-detecting the build tool from the project.
 * Only runs Vite-specific checks when Vite is detected.
 * Per SPEC-050 S3: no build tool detected → no checks.
 */
export async function checkBuildToolHealth(projectPath) {
    const buildTool = await detectBuildTool(projectPath);
    if (buildTool.buildTool !== 'vite') {
        return [];
    }
    const configFile = buildTool.configFile ?? 'vite.config.ts';
    const major = parseVersionMajor(buildTool.version);
    const promises = [
        // C7: vite.config.ts coverage
        checkViteConfigInTsconfig(projectPath),
    ];
    // C8: Rolldown plugin compat check
    if (buildTool.bundler === 'rolldown') {
        promises.push(checkRolldownPluginCompat(projectPath, configFile));
    }
    // C9: Vite 7+ legacy target check
    if (major !== null && major >= 7) {
        promises.push(checkVite7LegacyTarget(projectPath, configFile));
    }
    const results = await Promise.all(promises);
    return results.flat();
}
//# sourceMappingURL=build-tool-checker.js.map