"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RegressionRunner = void 0;
const child_process_1 = require("child_process");
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const chalk_1 = __importDefault(require("chalk"));
class RegressionRunner {
    constructor(projectRoot, componentPath) {
        this.projectRoot = projectRoot;
        this.componentPath = componentPath;
    }
    async runRegressionSuite() {
        console.log(chalk_1.default.blue("🧪 Running regression test suite..."));
        const typecheckResult = await this.runTypecheck();
        const lintResult = await this.runLint();
        const unitResult = await this.runUnitTests();
        // Calculate weighted score
        const weights = {
            typecheck: 0.3,
            lint: 0.2,
            unit: 0.5,
        };
        const overallScore = typecheckResult.score * weights.typecheck +
            lintResult.score * weights.lint +
            unitResult.score * weights.unit;
        const passed = typecheckResult.passed && lintResult.passed && unitResult.failed === 0;
        let summary = "";
        if (passed) {
            summary = `All tests passed (Score: ${overallScore.toFixed(2)})`;
        }
        else {
            const failures = [];
            if (!typecheckResult.passed)
                failures.push("TypeScript");
            if (!lintResult.passed)
                failures.push("ESLint");
            if (unitResult.failed > 0)
                failures.push(`${unitResult.failed} unit tests`);
            summary = `Failed: ${failures.join(", ")} (Score: ${overallScore.toFixed(2)})`;
        }
        return {
            typecheck: typecheckResult,
            lint: lintResult,
            unit: unitResult,
            overall: {
                score: overallScore,
                passed,
                summary,
            },
        };
    }
    async runTypecheck() {
        try {
            console.log(chalk_1.default.gray("  🔍 Running TypeScript check..."));
            const result = (0, child_process_1.execSync)(`npx tsc --noEmit --skipLibCheck`, {
                cwd: this.projectRoot,
                encoding: "utf8",
                stdio: "pipe",
            });
            return {
                passed: true,
                details: ["TypeScript compilation successful"],
                score: 1.0,
            };
        }
        catch (error) {
            const errorOutput = error.stdout || error.stderr || error.message;
            const details = errorOutput
                .split("\n")
                .filter((line) => line.trim());
            return {
                passed: false,
                details,
                score: 0.0,
            };
        }
    }
    async runLint() {
        try {
            console.log(chalk_1.default.gray("  🔍 Running ESLint..."));
            const result = (0, child_process_1.execSync)(`npx eslint "${this.componentPath}" --format=compact`, {
                cwd: this.projectRoot,
                encoding: "utf8",
                stdio: "pipe",
            });
            return {
                passed: true,
                details: ["ESLint check passed"],
                score: 1.0,
            };
        }
        catch (error) {
            const errorOutput = error.stdout || error.stderr || error.message;
            const details = errorOutput
                .split("\n")
                .filter((line) => line.trim());
            // Calculate partial score based on error severity
            const errorCount = details.filter((line) => line.includes("error")).length;
            const warningCount = details.filter((line) => line.includes("warning")).length;
            // Score decreases with errors, warnings have less impact
            const score = Math.max(0, 1.0 - errorCount * 0.3 - warningCount * 0.1);
            return {
                passed: errorCount === 0,
                details,
                score,
            };
        }
    }
    async runUnitTests() {
        try {
            console.log(chalk_1.default.gray("  🔍 Running unit tests..."));
            // Try to find test files for this component
            const testFiles = this.findTestFiles();
            if (testFiles.length === 0) {
                return {
                    passed: 0,
                    failed: 0,
                    total: 0,
                    details: ["No unit tests found for this component"],
                    score: 0.5, // Neutral score when no tests exist
                };
            }
            const result = (0, child_process_1.execSync)(`npx jest ${testFiles.join(" ")} --json`, {
                cwd: this.projectRoot,
                encoding: "utf8",
                stdio: "pipe",
            });
            // Parse test results from JSON output
            const output = result.toString();
            const jsonMatch = output.match(/\{[\s\S]*\}/);
            if (jsonMatch) {
                const testResult = JSON.parse(jsonMatch[0]);
                const passed = testResult.numPassedTests || 0;
                const failed = testResult.numFailedTests || 0;
                const total = testResult.numTotalTests || 0;
                const score = total > 0 ? passed / total : 0.5;
                return {
                    passed,
                    failed,
                    total,
                    details: [`${passed}/${total} tests passed`],
                    score,
                };
            }
            // Fallback to regex parsing if JSON parsing fails
            const passedMatch = output.match(/(\d+) passed/);
            const failedMatch = output.match(/(\d+) failed/);
            const passed = passedMatch ? parseInt(passedMatch[1], 10) : 0;
            const failed = failedMatch ? parseInt(failedMatch[1], 10) : 0;
            const total = passed + failed;
            const score = total > 0 ? passed / total : 0.5;
            return {
                passed,
                failed,
                total,
                details: [`${passed}/${total} tests passed`],
                score,
            };
        }
        catch (error) {
            const errorOutput = error.stdout || error.stderr || error.message;
            const details = errorOutput
                .split("\n")
                .filter((line) => line.trim());
            // Try to extract test results from error output
            const passedMatch = errorOutput.match(/(\d+) passed/);
            const failedMatch = errorOutput.match(/(\d+) failed/);
            const passed = passedMatch ? parseInt(passedMatch[1], 10) : 0;
            const failed = failedMatch ? parseInt(failedMatch[1], 10) : 0;
            const total = passed + failed;
            const score = total > 0 ? passed / total : 0.0;
            return {
                passed,
                failed,
                total,
                details,
                score,
            };
        }
    }
    findTestFiles() {
        const testFiles = [];
        const componentName = path_1.default.basename(this.componentPath, path_1.default.extname(this.componentPath));
        // Common test file patterns
        const patterns = [
            `${componentName}.test.ts`,
            `${componentName}.test.tsx`,
            `${componentName}.spec.ts`,
            `${componentName}.spec.tsx`,
            `__tests__/${componentName}.test.ts`,
            `__tests__/${componentName}.test.tsx`,
            `tests/${componentName}.test.ts`,
            `tests/${componentName}.test.tsx`,
        ];
        for (const pattern of patterns) {
            const testPath = path_1.default.join(this.projectRoot, pattern);
            if (fs_1.default.existsSync(testPath)) {
                testFiles.push(pattern);
            }
        }
        return testFiles;
    }
    async compareToBaseline(currentResult, baselineResult) {
        if (!baselineResult) {
            return {
                hasBaseline: false,
                regressionDetected: false,
                changes: {
                    typecheck: "unchanged",
                    lint: "unchanged",
                    unit: "unchanged",
                },
                summary: "No baseline available for comparison",
            };
        }
        const changes = {
            typecheck: this.compareScore(currentResult.typecheck.score, baselineResult.typecheck.score),
            lint: this.compareScore(currentResult.lint.score, baselineResult.lint.score),
            unit: this.compareScore(currentResult.unit.score, baselineResult.unit.score),
        };
        const regressions = Object.values(changes).filter((change) => change === "regressed").length;
        const improvements = Object.values(changes).filter((change) => change === "improved").length;
        let summary = "";
        if (regressions === 0 && improvements === 0) {
            summary = "No changes detected";
        }
        else if (regressions > 0) {
            summary = `${regressions} regression(s) detected`;
        }
        else {
            summary = `${improvements} improvement(s) detected`;
        }
        return {
            hasBaseline: true,
            regressionDetected: regressions > 0,
            changes,
            summary,
        };
    }
    compareScore(current, baseline) {
        const threshold = 0.05; // 5% threshold for change detection
        if (Math.abs(current - baseline) < threshold) {
            return "unchanged";
        }
        return current > baseline ? "improved" : "regressed";
    }
    async saveBaseline(result, componentPath) {
        const baselineDir = path_1.default.join(this.projectRoot, ".mycontext", "baselines");
        if (!fs_1.default.existsSync(baselineDir)) {
            fs_1.default.mkdirSync(baselineDir, { recursive: true });
        }
        const componentName = path_1.default.basename(componentPath, path_1.default.extname(componentPath));
        const baselineFile = path_1.default.join(baselineDir, `${componentName}-baseline.json`);
        const baseline = {
            timestamp: new Date().toISOString(),
            componentPath,
            result,
        };
        fs_1.default.writeFileSync(baselineFile, JSON.stringify(baseline, null, 2));
        console.log(chalk_1.default.green(`✅ Baseline saved for ${componentName}`));
    }
    async loadBaseline(componentPath) {
        const baselineDir = path_1.default.join(this.projectRoot, ".mycontext", "baselines");
        const componentName = path_1.default.basename(componentPath, path_1.default.extname(componentPath));
        const baselineFile = path_1.default.join(baselineDir, `${componentName}-baseline.json`);
        if (!fs_1.default.existsSync(baselineFile)) {
            return null;
        }
        try {
            const content = fs_1.default.readFileSync(baselineFile, "utf8");
            const baseline = JSON.parse(content);
            return baseline.result;
        }
        catch (error) {
            console.warn(chalk_1.default.yellow(`⚠️  Failed to load baseline for ${componentName}`));
            return null;
        }
    }
}
exports.RegressionRunner = RegressionRunner;
//# sourceMappingURL=RegressionRunner.js.map