"use strict";
/**
 * Validation Gates System
 *
 * Implements user approval checkpoints for PRD, context files, and other critical artifacts.
 * Follows "LLM as Compiler" philosophy - user approves 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.ValidationGates = void 0;
const prompts_1 = __importDefault(require("prompts"));
const chalk_1 = __importDefault(require("chalk"));
const fs = __importStar(require("fs-extra"));
const child_process_1 = require("child_process");
const util_1 = require("util");
const execAsync = (0, util_1.promisify)(child_process_1.exec);
class ValidationGates {
    /**
     * Validate PRD - CRITICAL GATE
     * User must read and approve the entire PRD before component generation.
     */
    static async validatePRD(prdPath, prdContent) {
        console.log(chalk_1.default.blue.bold('\n╔════════════════════════════════════════════════════════════════╗'));
        console.log(chalk_1.default.blue.bold('║           📋 PRD VALIDATION REQUIRED - CRITICAL GATE           ║'));
        console.log(chalk_1.default.blue.bold('╚════════════════════════════════════════════════════════════════╝\n'));
        console.log(chalk_1.default.yellow('🔍 The PRD is the "source code" for the AI compiler.'));
        console.log(chalk_1.default.yellow('⚠️  Component generation quality depends on PRD accuracy.'));
        console.log(chalk_1.default.yellow('📖 Please read EVERY section carefully before approving.\n'));
        // Display PRD in sections
        await this.displayPRDSections(prdContent);
        const response = await (0, prompts_1.default)([
            {
                type: 'select',
                name: 'action',
                message: 'What would you like to do?',
                choices: [
                    { title: '📖 Read PRD in full (opens in pager)', value: 'read' },
                    { title: '✏️  Edit PRD manually (opens in editor)', value: 'edit' },
                    { title: '✅ Approve PRD (I have read everything)', value: 'approve' },
                    { title: '🔄 Regenerate PRD with feedback', value: 'regenerate' },
                    { title: '❌ Cancel build-app workflow', value: 'cancel' },
                ],
                initial: 0,
            },
        ]);
        switch (response.action) {
            case 'read':
                await this.openInPager(prdContent);
                return this.validatePRD(prdPath, prdContent); // Re-prompt after reading
            case 'edit':
                await this.openInEditor(prdPath);
                const editedContent = await fs.readFile(prdPath, 'utf-8');
                console.log(chalk_1.default.green('\n✅ PRD edited successfully!'));
                return { approved: true, edited: true };
            case 'approve':
                const confirmation = await (0, prompts_1.default)({
                    type: 'confirm',
                    name: 'confirmed',
                    message: chalk_1.default.yellow('⚠️  Final confirmation: Have you read the ENTIRE PRD?'),
                    initial: false,
                });
                if (!confirmation.confirmed) {
                    console.log(chalk_1.default.yellow('\n📖 Please take time to read the PRD carefully.\n'));
                    return this.validatePRD(prdPath, prdContent);
                }
                console.log(chalk_1.default.green.bold('\n✅ PRD APPROVED - Proceeding to component generation\n'));
                return { approved: true };
            case 'regenerate':
                const { feedback } = await (0, prompts_1.default)({
                    type: 'text',
                    name: 'feedback',
                    message: 'What changes would you like in the PRD?',
                    validate: (value) => value.length >= 10 || 'Please provide detailed feedback (min 10 chars)',
                });
                return { approved: false, feedback };
            case 'cancel':
                throw new Error('User cancelled workflow');
            default:
                return { approved: false };
        }
    }
    /**
     * Validate Context File (Features, User Flows, Edge Cases, Tech Specs)
     */
    static async validateContextFile(fileName, content, filePath) {
        console.log(chalk_1.default.blue.bold(`\n╔════════════════════════════════════════════════════════════════╗`));
        console.log(chalk_1.default.blue.bold(`║           ✅ ${fileName.toUpperCase()} VALIDATION REQUIRED           ║`));
        console.log(chalk_1.default.blue.bold(`╚════════════════════════════════════════════════════════════════╝\n`));
        // Display content preview
        console.log(chalk_1.default.gray('Preview (first 20 lines):\n'));
        const lines = content.split('\n').slice(0, 20);
        lines.forEach((line, idx) => {
            console.log(chalk_1.default.gray(`${String(idx + 1).padStart(3, ' ')} │ ${line}`));
        });
        if (content.split('\n').length > 20) {
            console.log(chalk_1.default.gray(`... ${content.split('\n').length - 20} more lines\n`));
        }
        const response = await (0, prompts_1.default)([
            {
                type: 'select',
                name: 'action',
                message: `Review ${fileName}:`,
                choices: [
                    { title: '📖 Read full file (opens in pager)', value: 'read' },
                    { title: '✏️  Edit file', value: 'edit' },
                    { title: '✅ Approve', value: 'approve' },
                    { title: '🔄 Regenerate with feedback', value: 'regenerate' },
                ],
                initial: 0,
            },
        ]);
        switch (response.action) {
            case 'read':
                await this.openInPager(content);
                return this.validateContextFile(fileName, content, filePath);
            case 'edit':
                await this.openInEditor(filePath);
                console.log(chalk_1.default.green(`\n✅ ${fileName} edited successfully!`));
                return { approved: true, edited: true };
            case 'approve':
                console.log(chalk_1.default.green(`✅ ${fileName} approved\n`));
                return { approved: true };
            case 'regenerate':
                const { feedback } = await (0, prompts_1.default)({
                    type: 'text',
                    name: 'feedback',
                    message: `What changes would you like in ${fileName}?`,
                });
                return { approved: false, feedback };
            default:
                return { approved: false };
        }
    }
    /**
     * Validate Component List
     */
    static async validateComponentList(componentList, filePath) {
        console.log(chalk_1.default.blue.bold('\n╔════════════════════════════════════════════════════════════════╗'));
        console.log(chalk_1.default.blue.bold('║           📋 COMPONENT LIST VALIDATION REQUIRED                ║'));
        console.log(chalk_1.default.blue.bold('╚════════════════════════════════════════════════════════════════╝\n'));
        // Display component tree
        console.log(chalk_1.default.yellow(`Total Components: ${componentList.length}\n`));
        const groupedComponents = this.groupComponents(componentList);
        Object.entries(groupedComponents).forEach(([group, components]) => {
            console.log(chalk_1.default.blue(`📁 ${group} (${components.length})`));
            components.forEach((comp) => {
                console.log(chalk_1.default.gray(`   └─ ${comp.name || comp}`));
            });
            console.log();
        });
        const response = await (0, prompts_1.default)([
            {
                type: 'select',
                name: 'action',
                message: 'Review component list:',
                choices: [
                    { title: '✅ Approve component list', value: 'approve' },
                    { title: '✏️  Edit component list (opens JSON editor)', value: 'edit' },
                    { title: '🔄 Regenerate with different grouping', value: 'regenerate' },
                ],
            },
        ]);
        switch (response.action) {
            case 'approve':
                console.log(chalk_1.default.green('✅ Component list approved\n'));
                return { approved: true };
            case 'edit':
                await this.openInEditor(filePath);
                console.log(chalk_1.default.green('\n✅ Component list edited successfully!'));
                return { approved: true, edited: true };
            case 'regenerate':
                const { feedback } = await (0, prompts_1.default)({
                    type: 'text',
                    name: 'feedback',
                    message: 'How would you like components grouped?',
                });
                return { approved: false, feedback };
            default:
                return { approved: false };
        }
    }
    /**
     * Validate Types
     */
    static async validateTypes(typesPath, typesContent) {
        console.log(chalk_1.default.blue.bold('\n╔════════════════════════════════════════════════════════════════╗'));
        console.log(chalk_1.default.blue.bold('║           🔷 TYPESCRIPT TYPES VALIDATION REQUIRED              ║'));
        console.log(chalk_1.default.blue.bold('╚════════════════════════════════════════════════════════════════╝\n'));
        // Extract interface names
        const interfaceMatches = typesContent.matchAll(/(?:interface|type)\s+(\w+)/g);
        const interfaces = Array.from(interfaceMatches).map(match => match[1]);
        console.log(chalk_1.default.yellow(`Total Types: ${interfaces.length}\n`));
        interfaces.forEach((name, idx) => {
            console.log(chalk_1.default.gray(`${String(idx + 1).padStart(3, ' ')}. ${name}`));
        });
        console.log();
        const response = await (0, prompts_1.default)([
            {
                type: 'select',
                name: 'action',
                message: 'Review types:',
                choices: [
                    { title: '📖 Read full types file', value: 'read' },
                    { title: '✅ Approve types', value: 'approve' },
                    { title: '✏️  Edit types', value: 'edit' },
                ],
            },
        ]);
        switch (response.action) {
            case 'read':
                await this.openInPager(typesContent);
                return this.validateTypes(typesPath, typesContent);
            case 'approve':
                console.log(chalk_1.default.green('✅ Types approved\n'));
                return { approved: true };
            case 'edit':
                await this.openInEditor(typesPath);
                console.log(chalk_1.default.green('\n✅ Types edited successfully!'));
                return { approved: true, edited: true };
            default:
                return { approved: false };
        }
    }
    /**
     * Display PRD in sections
     */
    static displayPRDSections(prdContent) {
        const sections = prdContent.split(/^##\s+/m).filter(Boolean);
        console.log(chalk_1.default.blue('📑 PRD Sections:\n'));
        sections.forEach((section, idx) => {
            const title = section.split('\n')[0];
            const lineCount = section.split('\n').length;
            console.log(chalk_1.default.gray(`${String(idx + 1).padStart(2, ' ')}. ${title} (${lineCount} lines)`));
        });
        console.log();
    }
    /**
     * Open content in system pager (less/more)
     */
    static async openInPager(content) {
        const tempFile = `/tmp/mycontext-prd-${Date.now()}.md`;
        await fs.writeFile(tempFile, content);
        try {
            // Try to use `less` with syntax highlighting if available
            await execAsync(`less -R ${tempFile}`);
        }
        catch {
            // Fallback to basic `more`
            try {
                await execAsync(`more ${tempFile}`);
            }
            catch {
                console.log(chalk_1.default.yellow('\n⚠️  Could not open pager, displaying in terminal:\n'));
                console.log(content);
            }
        }
        finally {
            await fs.remove(tempFile).catch(() => { });
        }
    }
    /**
     * Open file in user's default editor
     */
    static async openInEditor(filePath) {
        const editor = process.env.EDITOR || process.env.VISUAL || 'vim';
        console.log(chalk_1.default.blue(`\n📝 Opening in ${editor}...`));
        console.log(chalk_1.default.gray('Press any key after saving and closing the editor.\n'));
        try {
            await execAsync(`${editor} ${filePath}`);
        }
        catch (error) {
            console.log(chalk_1.default.red(`\n❌ Could not open editor: ${error}`));
            console.log(chalk_1.default.yellow(`Please manually edit: ${filePath}`));
            await (0, prompts_1.default)({
                type: 'confirm',
                name: 'done',
                message: 'Press Enter after editing the file...',
            });
        }
    }
    /**
     * Group components by category
     */
    static groupComponents(componentList) {
        const grouped = {};
        componentList.forEach(comp => {
            const group = (typeof comp === 'object' ? comp.group : null) || 'uncategorized';
            if (!grouped[group]) {
                grouped[group] = [];
            }
            grouped[group].push(comp);
        });
        return grouped;
    }
    /**
     * Validate Build Strategy Selection
     */
    static async validateBuildStrategy(strategies, recommended) {
        console.log(chalk_1.default.blue.bold('\n╔════════════════════════════════════════════════════════════════╗'));
        console.log(chalk_1.default.blue.bold('║           🎯 BUILD STRATEGY SELECTION REQUIRED                 ║'));
        console.log(chalk_1.default.blue.bold('╚════════════════════════════════════════════════════════════════╝\n'));
        console.log(chalk_1.default.green(`💡 Recommended: ${recommended.name}\n`));
        console.log(chalk_1.default.gray(recommended.description));
        console.log();
        const { choice } = await (0, prompts_1.default)({
            type: 'select',
            name: 'choice',
            message: 'Select build strategy:',
            choices: strategies.map(s => ({
                title: `${s.icon} ${s.name} - ${s.timeToFirstDemo}`,
                value: s.id,
                description: s.description,
            })),
        });
        if (!choice) {
            return { approved: false };
        }
        console.log(chalk_1.default.green(`\n✅ Strategy selected: ${choice}\n`));
        return { approved: true, selectedStrategy: choice };
    }
    /**
     * Final build validation - user tests the app
     */
    static async validateFinalBuild() {
        console.log(chalk_1.default.blue.bold('\n╔════════════════════════════════════════════════════════════════╗'));
        console.log(chalk_1.default.blue.bold('║           🚀 FINAL BUILD VALIDATION - TEST YOUR APP            ║'));
        console.log(chalk_1.default.blue.bold('╚════════════════════════════════════════════════════════════════╝\n'));
        console.log(chalk_1.default.yellow('🧪 Please test your application:'));
        console.log(chalk_1.default.gray('   1. Run `pnpm dev` in another terminal'));
        console.log(chalk_1.default.gray('   2. Visit http://localhost:3000'));
        console.log(chalk_1.default.gray('   3. Test key user flows'));
        console.log(chalk_1.default.gray('   4. Check responsive design'));
        console.log(chalk_1.default.gray('   5. Verify all components render correctly\n'));
        const response = await (0, prompts_1.default)([
            {
                type: 'confirm',
                name: 'approved',
                message: 'Does the application work as expected?',
                initial: false,
            },
            {
                type: (prev) => (prev ? null : 'text'),
                name: 'issues',
                message: 'What issues did you find?',
            },
        ]);
        if (!response.approved) {
            return { approved: false, feedback: response.issues };
        }
        console.log(chalk_1.default.green.bold('\n🎉 Final build approved! Ready for deployment.\n'));
        return { approved: true };
    }
}
exports.ValidationGates = ValidationGates;
//# sourceMappingURL=validationGates.js.map