/**
 * Generate Command - Generate code from description
 *
 * Now with Senior Developer Mode (--pro) for impressive, production-ready output
 */
import chalk from 'chalk';
import inquirer from 'inquirer';
import { createSpinner, CH } from '../utils/logger.js';
import { APIClient, CLIError, classifyError, formatCLIError } from '../utils/api.js';
import { FileUtils } from '../utils/files.js';
export class GenerateCommand {
    config;
    logger;
    api;
    fileUtils;
    constructor(config, logger) {
        this.config = config;
        this.logger = logger;
        this.api = new APIClient(config, logger);
        this.fileUtils = new FileUtils(process.cwd(), config.get('project').ignorePatterns);
    }
    async run(description, options) {
        // Check auth
        if (!this.config.isAuthenticated()) {
            this.logger.error('Not authenticated. Run: vigthoria login');
            return;
        }
        // Server-side token validation — fail fast instead of waiting for 401
        const tokenCheck = await this.api.validateToken();
        if (!tokenCheck.valid) {
            this.logger.error(tokenCheck.error || 'Auth token is invalid. Run: vigthoria login');
            return;
        }
        // Determine mode
        const proMode = options.pro === true;
        // Auto-detect language from description if not explicitly specified
        if (!options.language) {
            options.language = this.detectLanguageFromDescription(description);
        }
        this.logger.section(proMode ? `${CH.rocket} Senior Developer Mode` : 'Code Generation');
        console.log(chalk.gray(`Language: ${options.language}`));
        console.log(chalk.gray(`Description: ${description}`));
        if (proMode) {
            console.log(chalk.cyan('Pro Mode: Planning → Generating → Quality Check'));
        }
        console.log();
        const spinner = createSpinner({
            text: proMode ? 'Phase 1: Planning project structure...' : 'Generating code...',
            spinner: 'dots',
        }).start();
        try {
            let code;
            let quality = null;
            if (proMode) {
                // Senior Developer Mode - uses planning and quality checks
                spinner.text = 'Phase 1: Planning project structure...';
                const result = await this.api.generateProject(description, options.language, options.model);
                spinner.text = 'Phase 2: Generating impressive code...';
                code = result.code;
                quality = result.quality;
                spinner.stop();
                // Show quality report
                if (quality) {
                    console.log();
                    this.logger.section('Quality Report');
                    console.log(chalk.gray(`Lines of code: ${quality.lineCount}`));
                    console.log(chalk.gray(`Quality score: ${quality.score}/5`));
                    console.log();
                    console.log(chalk.gray('Visual Checks:'));
                    console.log(`  ${quality.checks?.hasAnimations ? chalk.green('✓') : chalk.red('✗')} CSS Animations (@keyframes)`);
                    console.log(`  ${quality.checks?.hasNeonEffects ? chalk.green('✓') : chalk.red('✗')} Neon/Glow Effects`);
                    console.log(`  ${quality.checks?.hasResponsive ? chalk.green('✓') : chalk.red('✗')} Responsive Design (@media)`);
                    console.log(`  ${quality.checks?.hasFontAwesome ? chalk.green('✓') : chalk.red('✗')} Font Awesome Icons`);
                    console.log(`  ${quality.checks?.hasGoogleFonts ? chalk.green('✓') : chalk.red('✗')} Google Fonts`);
                    console.log();
                    console.log(chalk.gray('Structure Checks:'));
                    console.log(`  ${quality.checks?.hasEmbeddedCSS ? chalk.green('✓') : chalk.red('✗')} Embedded CSS (<style> tag)`);
                    console.log(`  ${quality.checks?.hasEmbeddedJS ? chalk.green('✓') : chalk.red('✗')} Embedded JavaScript (<script> tag)`);
                    console.log(`  ${quality.checks?.singleFile ? chalk.green('✓') : chalk.red('✗')} Single-file (no external CSS/JS)`);
                    console.log();
                }
            }
            else {
                // Standard mode
                code = await this.api.generateCode(description, options.language, options.model);
                spinner.stop();
            }
            // Strip any markdown fences the model may have wrapped around the code
            code = this.stripMarkdownFences(code, options.language);
            // Display generated code (skip display when --output is set to avoid noise)
            if (!options.output) {
                this.logger.section('Generated Code');
                console.log(chalk.gray('─'.repeat(60)));
                console.log(this.highlightCode(code, options.language));
                console.log(chalk.gray('─'.repeat(60)));
                console.log();
            }
            // Save options — when --output is specified, save directly (non-interactive)
            if (options.output) {
                await this.saveToFile(options.output, code);
            }
            else if (process.stdout.isTTY) {
                await this.promptForAction(code, options.language);
            }
            // Non-TTY: code was already printed above — skip interactive menu
        }
        catch (error) {
            spinner.stop();
            const cliErr = error instanceof CLIError ? error : classifyError(error);
            this.logger.error(formatCLIError(cliErr));
        }
    }
    /**
     * Strip markdown code fences the model may wrap around the output.
     * The CLI asks for raw code but some models still wrap in ```lang ... ```.
     */
    stripMarkdownFences(code, language) {
        const trimmed = code.trim();
        // Try language-specific fence first
        const langFenceRe = new RegExp(`^\`\`\`(?:${language})?\\s*\\n([\\s\\S]*?)\\n?\`\`\`\\s*$`, 'i');
        const langMatch = trimmed.match(langFenceRe);
        if (langMatch) {
            return langMatch[1].trim();
        }
        // Try generic fence
        const genericMatch = trimmed.match(/^```\w*\s*\n([\s\S]*?)\n?```\s*$/);
        if (genericMatch) {
            return genericMatch[1].trim();
        }
        return code;
    }
    highlightCode(code, language) {
        // Basic syntax highlighting
        // In production, use a proper library like highlight.js
        const lines = code.split('\n');
        return lines.map((line, i) => {
            const lineNum = chalk.gray(String(i + 1).padStart(4, ' ') + ' │ ');
            return lineNum + this.highlightLine(line, language);
        }).join('\n');
    }
    highlightLine(line, language) {
        // Simple keyword highlighting
        const keywords = {
            typescript: ['const', 'let', 'var', 'function', 'class', 'interface', 'type', 'export', 'import', 'from', 'async', 'await', 'return', 'if', 'else', 'for', 'while', 'try', 'catch', 'throw', 'new'],
            javascript: ['const', 'let', 'var', 'function', 'class', 'export', 'import', 'from', 'async', 'await', 'return', 'if', 'else', 'for', 'while', 'try', 'catch', 'throw', 'new'],
            python: ['def', 'class', 'import', 'from', 'return', 'if', 'elif', 'else', 'for', 'while', 'try', 'except', 'raise', 'with', 'as', 'async', 'await', 'yield', 'lambda'],
            rust: ['fn', 'let', 'mut', 'const', 'struct', 'enum', 'impl', 'trait', 'pub', 'use', 'mod', 'return', 'if', 'else', 'match', 'for', 'while', 'loop', 'async', 'await'],
            go: ['func', 'var', 'const', 'type', 'struct', 'interface', 'package', 'import', 'return', 'if', 'else', 'for', 'range', 'switch', 'case', 'go', 'defer', 'chan'],
        };
        const langKeywords = keywords[language] || keywords['typescript'];
        let highlighted = line;
        // Highlight keywords
        langKeywords.forEach(kw => {
            const regex = new RegExp(`\\b${kw}\\b`, 'g');
            highlighted = highlighted.replace(regex, chalk.magenta(kw));
        });
        // Highlight strings
        highlighted = highlighted.replace(/(["'`])(?:(?!\1)[^\\]|\\.)*\1/g, (match) => chalk.green(match));
        // Highlight comments
        highlighted = highlighted.replace(/(\/\/.*$|#.*$)/g, (match) => chalk.gray(match));
        // Highlight numbers
        highlighted = highlighted.replace(/\b(\d+)\b/g, (match) => chalk.yellow(match));
        return highlighted;
    }
    async saveToFile(filePath, code) {
        if (this.fileUtils.writeFile(filePath, code)) {
            this.logger.success(`Code saved to ${filePath}`);
        }
        else {
            this.logger.error('Failed to save file');
        }
    }
    async promptForAction(code, language) {
        const { action } = await inquirer.prompt([
            {
                type: 'list',
                name: 'action',
                message: 'What would you like to do with this code?',
                choices: [
                    { name: 'Copy to clipboard', value: 'copy' },
                    { name: 'Save to file', value: 'save' },
                    { name: 'Regenerate', value: 'regenerate' },
                    { name: 'Done', value: 'done' },
                ],
            },
        ]);
        switch (action) {
            case 'copy':
                // Note: Clipboard access requires additional setup
                this.logger.info('Code copied to clipboard');
                console.log(chalk.gray('(Note: Clipboard access may require additional permissions)'));
                break;
            case 'save':
                const { filename } = await inquirer.prompt([
                    {
                        type: 'input',
                        name: 'filename',
                        message: 'Enter filename:',
                        default: this.suggestFilename(language),
                    },
                ]);
                await this.saveToFile(filename, code);
                break;
            case 'regenerate':
                this.logger.info('Use the generate command again with different parameters');
                break;
            case 'done':
                break;
        }
    }
    suggestFilename(language) {
        const extensions = {
            typescript: 'generated.ts',
            javascript: 'generated.js',
            python: 'generated.py',
            rust: 'generated.rs',
            go: 'generated.go',
            java: 'Generated.java',
            csharp: 'Generated.cs',
        };
        return extensions[language] || 'generated.txt';
    }
    /**
     * Auto-detect the target language from the user's description.
     * Falls back to 'javascript' if no language is recognized.
     */
    detectLanguageFromDescription(description) {
        const lower = description.toLowerCase();
        const patterns = [
            [/\b(typescript|\.ts\b)/i, 'typescript'],
            [/\b(javascript|\.js\b|node\.?js|es6|ecmascript)\b/i, 'javascript'],
            [/\b(python|\.py\b|django|flask|fastapi)\b/i, 'python'],
            [/\b(rust|\.rs\b|cargo)\b/i, 'rust'],
            [/\b(go|golang|\.go\b)\b/i, 'go'],
            [/\b(java\b|\.java\b|spring\b)/i, 'java'],
            [/\b(c#|csharp|\.cs\b|dotnet|\.net)\b/i, 'csharp'],
            [/\b(c\+\+|cpp|\.cpp\b|\.hpp\b)\b/i, 'cpp'],
            [/\b(ruby|\.rb\b|rails)\b/i, 'ruby'],
            [/\b(php|\.php\b|laravel)\b/i, 'php'],
            [/\b(swift|\.swift\b|swiftui)\b/i, 'swift'],
            [/\b(kotlin|\.kt\b)\b/i, 'kotlin'],
            [/\b(html|\.html\b|webpage|web page|website|landing page)\b/i, 'html'],
            [/\b(css|\.css\b|stylesheet)\b/i, 'css'],
            [/\b(sql|\.sql\b|database query|select\s+\*)\b/i, 'sql'],
            [/\b(bash|shell|\.sh\b|script)\b/i, 'bash'],
        ];
        for (const [regex, lang] of patterns) {
            if (regex.test(lower)) {
                return lang;
            }
        }
        // If the description mentions "function" without any language hint, default to javascript
        if (/\bfunction\b/i.test(lower)) {
            return 'javascript';
        }
        return 'javascript';
    }
}
