"use strict";
/**
 * Build Validation System
 *
 * Ensures every component passes TypeScript, ESLint, and build checks.
 * Follows "LLM as Compiler" philosophy - validates the "compiled output".
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BuildValidator = void 0;
const child_process_1 = require("child_process");
const util_1 = require("util");
const chalk_1 = __importDefault(require("chalk"));
const fs = __importStar(require("fs-extra"));
const path_1 = __importDefault(require("path"));
const execAsync = (0, util_1.promisify)(child_process_1.exec);
class BuildValidator {
    constructor(projectPath, verbose = false) {
        this.projectPath = projectPath;
        this.verbose = verbose;
    }
    /**
     * Run TypeScript type checking
     */
    async validateTypeScript(filePath) {
        console.log(chalk_1.default.blue('🔷 Running TypeScript check...'));
        try {
            const command = filePath
                ? `npx tsc --noEmit ${filePath}`
                : `npx tsc --noEmit`;
            const { stdout, stderr } = await execAsync(command, {
                cwd: this.projectPath,
                timeout: 30000, // 30 second timeout
            });
            if (this.verbose) {
                console.log(chalk_1.default.gray(stdout));
            }
            console.log(chalk_1.default.green('✅ TypeScript check passed'));
            return { passed: true, errors: [], warnings: [] };
        }
        catch (error) {
            const errors = this.parseTypeScriptErrors(error.stdout || error.stderr);
            console.log(chalk_1.default.red(`❌ TypeScript check failed (${errors.length} errors)`));
            if (this.verbose) {
                errors.forEach(err => console.log(chalk_1.default.red(`   ${err}`)));
            }
            return {
                passed: false,
                errors,
                warnings: [],
                output: error.stdout || error.stderr,
            };
        }
    }
    /**
     * Run ESLint
     */
    async validateESLint(filePath) {
        console.log(chalk_1.default.blue('📋 Running ESLint check...'));
        try {
            const command = filePath
                ? `npx eslint ${filePath}`
                : `npx eslint . --ext .ts,.tsx`;
            const { stdout, stderr } = await execAsync(command, {
                cwd: this.projectPath,
                timeout: 30000,
            });
            if (this.verbose) {
                console.log(chalk_1.default.gray(stdout));
            }
            console.log(chalk_1.default.green('✅ ESLint check passed'));
            return { passed: true, errors: [], warnings: [] };
        }
        catch (error) {
            const { errors, warnings } = this.parseESLintErrors(error.stdout || error.stderr);
            if (errors.length > 0) {
                console.log(chalk_1.default.red(`❌ ESLint check failed (${errors.length} errors, ${warnings.length} warnings)`));
            }
            else if (warnings.length > 0) {
                console.log(chalk_1.default.yellow(`⚠️  ESLint check passed with warnings (${warnings.length})`));
            }
            if (this.verbose) {
                errors.forEach(err => console.log(chalk_1.default.red(`   ${err}`)));
                warnings.forEach(warn => console.log(chalk_1.default.yellow(`   ${warn}`)));
            }
            return {
                passed: errors.length === 0,
                errors,
                warnings,
                output: error.stdout || error.stderr,
            };
        }
    }
    /**
     * Run full build
     */
    async validateBuild() {
        console.log(chalk_1.default.blue('🔨 Running build check...'));
        try {
            const { stdout, stderr } = await execAsync('npm run build', {
                cwd: this.projectPath,
                timeout: 120000, // 2 minute timeout for build
            });
            if (this.verbose) {
                console.log(chalk_1.default.gray(stdout));
            }
            console.log(chalk_1.default.green('✅ Build check passed'));
            return { passed: true, errors: [], warnings: [] };
        }
        catch (error) {
            const errors = this.parseBuildErrors(error.stdout || error.stderr);
            console.log(chalk_1.default.red(`❌ Build check failed (${errors.length} errors)`));
            if (this.verbose) {
                errors.forEach(err => console.log(chalk_1.default.red(`   ${err}`)));
            }
            return {
                passed: false,
                errors,
                warnings: [],
                output: error.stdout || error.stderr,
            };
        }
    }
    /**
     * Run tests for a component
     */
    async validateTests(testPath) {
        console.log(chalk_1.default.blue('🧪 Running tests...'));
        try {
            const command = testPath
                ? `npm test -- ${testPath}`
                : `npm test`;
            const { stdout, stderr } = await execAsync(command, {
                cwd: this.projectPath,
                timeout: 60000, // 1 minute timeout
            });
            if (this.verbose) {
                console.log(chalk_1.default.gray(stdout));
            }
            console.log(chalk_1.default.green('✅ Tests passed'));
            return { passed: true, errors: [], warnings: [] };
        }
        catch (error) {
            const errors = this.parseTestErrors(error.stdout || error.stderr);
            console.log(chalk_1.default.red(`❌ Tests failed (${errors.length} failures)`));
            if (this.verbose) {
                errors.forEach(err => console.log(chalk_1.default.red(`   ${err}`)));
            }
            return {
                passed: false,
                errors,
                warnings: [],
                output: error.stdout || error.stderr,
            };
        }
    }
    /**
     * Run all validations for a component
     */
    async validateComponent(componentPath, withTests = false) {
        console.log(chalk_1.default.blue.bold(`\n🔍 Validating: ${path_1.default.basename(componentPath)}\n`));
        const results = {
            typescript: await this.validateTypeScript(componentPath),
            eslint: await this.validateESLint(componentPath),
            build: await this.validateBuild(),
        };
        if (withTests) {
            const testPath = componentPath.replace(/\.tsx?$/, '.test.tsx');
            if (await fs.pathExists(testPath)) {
                results.tests = await this.validateTests(testPath);
            }
        }
        const allPassed = results.typescript.passed &&
            results.eslint.passed &&
            results.build.passed &&
            (!results.tests || results.tests.passed);
        if (allPassed) {
            console.log(chalk_1.default.green.bold('\n✅ All validations passed!\n'));
        }
        else {
            console.log(chalk_1.default.red.bold('\n❌ Some validations failed\n'));
        }
        return results;
    }
    /**
     * Run complete project validation
     */
    async validateProject() {
        console.log(chalk_1.default.blue.bold('\n🔍 Running Complete Project Validation\n'));
        const results = {
            typescript: await this.validateTypeScript(),
            eslint: await this.validateESLint(),
            build: await this.validateBuild(),
        };
        // Check for test script in package.json
        const packageJsonPath = path_1.default.join(this.projectPath, 'package.json');
        if (await fs.pathExists(packageJsonPath)) {
            const packageJson = await fs.readJson(packageJsonPath);
            if (packageJson.scripts?.test) {
                results.tests = await this.validateTests();
            }
        }
        return results;
    }
    /**
     * Parse TypeScript errors
     */
    parseTypeScriptErrors(output) {
        const errors = [];
        const errorRegex = /(.+\.tsx?)\((\d+),(\d+)\): error TS(\d+): (.+)/g;
        let match;
        while ((match = errorRegex.exec(output)) !== null) {
            const [, file, line, col, code, message] = match;
            errors.push(`${file}:${line}:${col} - TS${code}: ${message}`);
        }
        return errors;
    }
    /**
     * Parse ESLint errors
     */
    parseESLintErrors(output) {
        const errors = [];
        const warnings = [];
        const lines = output.split('\n');
        for (const line of lines) {
            if (line.includes('error')) {
                errors.push(line.trim());
            }
            else if (line.includes('warning')) {
                warnings.push(line.trim());
            }
        }
        return { errors, warnings };
    }
    /**
     * Parse build errors
     */
    parseBuildErrors(output) {
        const errors = [];
        const lines = output.split('\n');
        for (const line of lines) {
            if (line.includes('ERROR') ||
                line.includes('Failed to compile') ||
                line.includes('Module not found') ||
                line.includes('Cannot find')) {
                errors.push(line.trim());
            }
        }
        return errors;
    }
    /**
     * Parse test errors
     */
    parseTestErrors(output) {
        const errors = [];
        const lines = output.split('\n');
        for (const line of lines) {
            if (line.includes('FAIL') || line.includes('✕')) {
                errors.push(line.trim());
            }
        }
        return errors;
    }
    /**
     * Get error context for AI retry
     */
    static extractErrorContext(validationResults) {
        const context = [];
        if (!validationResults.typescript.passed) {
            context.push('TypeScript Errors:');
            validationResults.typescript.errors.forEach(err => context.push(`  - ${err}`));
        }
        if (!validationResults.eslint.passed) {
            context.push('ESLint Errors:');
            validationResults.eslint.errors.forEach(err => context.push(`  - ${err}`));
        }
        if (!validationResults.build.passed) {
            context.push('Build Errors:');
            validationResults.build.errors.forEach(err => context.push(`  - ${err}`));
        }
        if (validationResults.tests && !validationResults.tests.passed) {
            context.push('Test Failures:');
            validationResults.tests.errors.forEach(err => context.push(`  - ${err}`));
        }
        return context.join('\n');
    }
    /**
     * Format validation summary
     */
    static formatValidationSummary(results) {
        const summary = [];
        summary.push('Validation Results:');
        summary.push(`  TypeScript: ${results.typescript.passed ? '✅ Passed' : '❌ Failed'}`);
        summary.push(`  ESLint: ${results.eslint.passed ? '✅ Passed' : '❌ Failed'}`);
        summary.push(`  Build: ${results.build.passed ? '✅ Passed' : '❌ Failed'}`);
        if (results.tests) {
            summary.push(`  Tests: ${results.tests.passed ? '✅ Passed' : '❌ Failed'}`);
        }
        return summary.join('\n');
    }
}
exports.BuildValidator = BuildValidator;
//# sourceMappingURL=buildValidator.js.map