"use strict";
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.RefineComponentCommand = void 0;
const chalk_1 = __importDefault(require("chalk"));
const prompts_1 = __importDefault(require("prompts"));
const fs = __importStar(require("fs-extra"));
const fileSystem_1 = require("../utils/fileSystem");
const hybridAIClient_1 = require("../utils/hybridAIClient");
const review_context_1 = require("./review-context");
const MutationLogger_1 = require("../services/MutationLogger");
const RegressionRunner_1 = require("../services/RegressionRunner");
class RefineComponentCommand {
    constructor() {
        this.fs = new fileSystem_1.FileSystemManager();
        this.aiClient = new hybridAIClient_1.HybridAIClient();
        this.mutationLogger = new MutationLogger_1.MutationLogger(process.cwd());
        this.regressionRunner = new RegressionRunner_1.RegressionRunner(process.cwd(), "");
    }
    async execute(componentName, options) {
        console.log(chalk_1.default.blue(`🔧 Refining component: ${componentName}`));
        try {
            // Check if component exists
            const componentPath = await this.findComponent(componentName);
            if (!componentPath) {
                console.log(chalk_1.default.red(`❌ Component ${componentName} not found`));
                return;
            }
            // Update regression runner with component path
            this.regressionRunner = new RegressionRunner_1.RegressionRunner(process.cwd(), componentPath);
            // Load current component and mutation history
            const currentCode = await this.fs.readFile(componentPath);
            const mutationHistory = await this.mutationLogger.getMutationHistory(componentPath);
            const lastApprovedVersion = await this.mutationLogger.getLastApprovedVersion(componentPath);
            // Get refinement instructions from user
            const refinementInstructions = await this.getRefinementInstructions(componentName);
            // Generate refined component with AI
            const refinementResult = await this.generateRefinedComponent(componentName, currentCode, refinementInstructions, mutationHistory);
            // Create mutation record
            const mutationId = await this.mutationLogger.createMutationFromRefinement(componentPath, currentCode, refinementResult.new_file, refinementResult.chainOfThought, refinementResult.confidence, refinementResult.riskFlags);
            // Run regression tests
            console.log(chalk_1.default.blue("🧪 Running regression tests..."));
            const testResults = await this.runRegressionTests(refinementResult.new_file, componentPath);
            // Compare to baseline
            const baselineComparison = await this.compareToBaseline(testResults, lastApprovedVersion);
            // Show approval UI
            const approved = await this.showApprovalUI(componentName, currentCode, refinementResult, testResults, baselineComparison);
            if (approved) {
                // Apply the refinement
                await this.fs.writeFile(componentPath, refinementResult.new_file);
                // Update mutation status
                await this.mutationLogger.updateMutationStatus(mutationId, "applied");
                // Save baseline for future comparisons
                await this.regressionRunner.saveBaseline(testResults, componentPath);
                console.log(chalk_1.default.green(`✅ Component ${componentName} refined and applied successfully!`));
            }
            else {
                // Mark mutation as rejected
                await this.mutationLogger.updateMutationStatus(mutationId, "rejected", "User rejected");
                console.log(chalk_1.default.yellow(`⏭️  Refinement rejected`));
            }
        }
        catch (error) {
            console.error(chalk_1.default.red("❌ Component refinement failed:"), error);
            throw error;
        }
    }
    /**
     * Find component file path
     */
    async findComponent(componentName) {
        const possiblePaths = [
            `.mycontext/components/mobile/${componentName}.tsx`,
            `.mycontext/components/desktop/${componentName}.tsx`,
            `components/${componentName}.tsx`,
            `src/components/${componentName}.tsx`,
        ];
        for (const possiblePath of possiblePaths) {
            if (await this.fs.exists(possiblePath)) {
                return possiblePath;
            }
        }
        return null;
    }
    /**
     * Get refinement instructions from user
     */
    async getRefinementInstructions(componentName) {
        const response = await (0, prompts_1.default)({
            type: "text",
            name: "instructions",
            message: `What improvements would you like to make to ${componentName}?`,
            initial: "Improve accessibility, add loading states, and optimize performance",
        });
        return response.instructions || "General improvements";
    }
    /**
     * Generate refined component with AI
     */
    async generateRefinedComponent(componentName, currentCode, instructions, mutationHistory) {
        const historyContext = mutationHistory.length > 0
            ? `\nPrevious refinements:\n${mutationHistory
                .slice(-3)
                .map((m) => `- ${m.timestamp}: ${m.chainOfThought}`)
                .join("\n")}`
            : "";
        const prompt = `You are a code-refinement assistant for MyContext. 
Input:
- ORIGINAL_FILE: \`\`\`${currentCode}\`\`\`
- CONTEXT: "Project uses shadcn/ui, Next.js App Router, InstantDB. Keep 'use client' placement rules."
- REFINEMENT: "${instructions}"
- HISTORY: ${historyContext}

Produce strictly JSON with fields:
{
 "patch": "<git unified diff>",
 "new_file": "<full updated file text>",
 "tests": [ { "type":"unit","code":"...test code..." } ],
 "explanation": "...",
 "confidence": 0.x,
 "risk_flags": []
}

Notes:
- Keep TypeScript types strict.
- Do not add new npm dependencies.
- Provide one-line summary and short chain-of-thought under explanation.
- Keep code <= 200 lines change when possible.`;
        try {
            const response = await this.aiClient.generateText(prompt, {
                temperature: 0.3,
                maxTokens: 4000,
            });
            // Parse JSON response
            const jsonMatch = response.text.match(/\{[\s\S]*\}/);
            if (!jsonMatch) {
                throw new Error("No JSON found in response");
            }
            const result = JSON.parse(jsonMatch[0]);
            return {
                new_file: result.new_file || response.text,
                explanation: result.explanation || "Component refined",
                chainOfThought: result.explanation || "AI refinement applied",
                confidence: result.confidence || 0.7,
                riskFlags: result.risk_flags || [],
            };
        }
        catch (error) {
            console.log(chalk_1.default.yellow("⚠️  Could not parse AI response, using fallback"));
            return {
                new_file: currentCode,
                explanation: "Fallback refinement",
                chainOfThought: "AI parsing failed, using original code",
                confidence: 0.3,
                riskFlags: ["ai_parsing_failed"],
            };
        }
    }
    /**
     * Run regression tests on refined component
     */
    async runRegressionTests(refinedCode, componentPath) {
        // Write refined code to temporary file
        const tempPath = `${componentPath}.tmp`;
        await this.fs.writeFile(tempPath, refinedCode);
        try {
            // Update regression runner with temp path
            const tempRegressionRunner = new RegressionRunner_1.RegressionRunner(process.cwd(), tempPath);
            const results = await tempRegressionRunner.runRegressionSuite();
            // Clean up temp file using fs-extra
            await fs.remove(tempPath);
            return results;
        }
        catch (error) {
            // Clean up temp file using fs-extra
            await fs.remove(tempPath);
            throw error;
        }
    }
    /**
     * Compare test results to baseline
     */
    async compareToBaseline(currentResults, lastApprovedVersion) {
        if (!lastApprovedVersion) {
            return {
                hasBaseline: false,
                regressionDetected: false,
                summary: "No baseline available for comparison",
            };
        }
        // Simple comparison based on overall score
        const baselineScore = 0.8; // Default baseline score
        const currentScore = currentResults.overall.score;
        const regressionDetected = currentScore < baselineScore * 0.9; // 10% tolerance
        let summary = "";
        if (regressionDetected) {
            summary = `Regression detected: Score dropped from ${baselineScore.toFixed(2)} to ${currentScore.toFixed(2)}`;
        }
        else {
            summary = `No regression: Score ${currentScore.toFixed(2)} (baseline: ${baselineScore.toFixed(2)})`;
        }
        return {
            hasBaseline: true,
            regressionDetected,
            summary,
        };
    }
    /**
     * Show approval UI with test results
     */
    async showApprovalUI(componentName, originalCode, refinementResult, testResults, baselineComparison) {
        console.log(chalk_1.default.cyan(`\n📝 Component Refinement Proposal: ${componentName}`));
        console.log(chalk_1.default.yellow("\n🔍 Changes:"));
        console.log(chalk_1.default.gray(`  ${refinementResult.explanation}`));
        console.log(chalk_1.default.yellow("\n📊 Test Results:"));
        console.log(chalk_1.default.gray(`  TypeScript: ${testResults.typecheck.passed
            ? chalk_1.default.green("✅ Pass")
            : chalk_1.default.red("❌ Fail")}`));
        console.log(chalk_1.default.gray(`  ESLint: ${testResults.lint.passed
            ? chalk_1.default.green("✅ Pass")
            : chalk_1.default.red("❌ Fail")}`));
        console.log(chalk_1.default.gray(`  Unit Tests: ${testResults.unit.passed}/${testResults.unit.total} passing`));
        console.log(chalk_1.default.yellow("\n🤖 AI Confidence:"));
        console.log(chalk_1.default.gray(`  ${(refinementResult.confidence * 100).toFixed(0)}%`));
        if (refinementResult.riskFlags.length > 0) {
            console.log(chalk_1.default.yellow("\n⚠️  Risk Flags:"));
            refinementResult.riskFlags.forEach((flag) => {
                console.log(chalk_1.default.gray(`  - ${flag}`));
            });
        }
        console.log(chalk_1.default.yellow("\n📈 Regression Check:"));
        console.log(chalk_1.default.gray(`  ${baselineComparison.summary}`));
        const response = await (0, prompts_1.default)({
            type: "select",
            name: "action",
            message: "What would you like to do?",
            choices: [
                { title: "Accept refinement", value: "accept" },
                { title: "Reject refinement", value: "reject" },
                { title: "View diff", value: "diff" },
                { title: "Cancel", value: "cancel" },
            ],
            initial: 0,
        });
        if (response.action === "diff") {
            // Show diff (simplified)
            console.log(chalk_1.default.blue("\n📋 Diff Preview:"));
            console.log(chalk_1.default.gray("  [Diff would be shown here in a real implementation]"));
            // Ask again after showing diff
            const diffResponse = await (0, prompts_1.default)({
                type: "select",
                name: "action",
                message: "After viewing the diff:",
                choices: [
                    { title: "Accept refinement", value: "accept" },
                    { title: "Reject refinement", value: "reject" },
                ],
                initial: 0,
            });
            return diffResponse.action === "accept";
        }
        return response.action === "accept";
    }
    /**
     * Check if component needs refinement based on approvals
     */
    static async needsRefinement(componentName) {
        try {
            const approval = await review_context_1.ReviewContextCommand.getFeatureApproval(componentName.toLowerCase().replace(/\s+/g, "-"));
            return approval === false; // Component was rejected and needs refinement
        }
        catch (error) {
            return false;
        }
    }
}
exports.RefineComponentCommand = RefineComponentCommand;
//# sourceMappingURL=refine-component.js.map