/**
 * cv explain command
 * Explain code or concepts using Claude
 */
import { Command } from 'commander';
import chalk from 'chalk';
import ora from 'ora';
import { configManager, createAIManager, createVectorManager, createGraphManager, createGitManager, createRLMRouter } from '@cv-git/core';
import { findRepoRoot } from '@cv-git/shared';
import { addGlobalOptions } from '../utils/output.js';
import { getAnthropicApiKey, getEmbeddingCredentials } from '../utils/credentials.js';
export function explainCommand() {
    const cmd = new Command('explain');
    cmd
        .description('Explain code, files, or concepts using AI')
        .argument('<target>', 'What to explain (symbol name, file path, or concept)')
        .option('--no-stream', 'Disable streaming output')
        .option('--deep', 'Use RLM-powered deep reasoning for complex queries')
        .option('--trace', 'Show reasoning trace (only with --deep)')
        .option('--max-depth <n>', 'Maximum recursion depth for deep reasoning (default: 5)', '5');
    addGlobalOptions(cmd);
    cmd.action(async (target, options) => {
        let spinner = ora('Initializing...').start();
        try {
            // Find repository root
            const repoRoot = await findRepoRoot();
            if (!repoRoot) {
                spinner.fail(chalk.red('Not in a CV-Git repository'));
                console.error(chalk.gray('Run `cv init` first'));
                process.exit(1);
            }
            // Load configuration
            const config = await configManager.load(repoRoot);
            // Check for API keys (CredentialManager -> config -> env var)
            const anthropicApiKey = await getAnthropicApiKey(config.ai.apiKey);
            if (!anthropicApiKey) {
                spinner.fail(chalk.red('Anthropic API key not found'));
                console.error();
                console.error(chalk.yellow('Set your Anthropic API key:'));
                console.error(chalk.gray('  cv auth setup anthropic'));
                console.error(chalk.gray('  export ANTHROPIC_API_KEY=sk-ant-...'));
                process.exit(1);
            }
            // Get embedding credentials (OpenRouter preferred, fallback to OpenAI)
            const embeddingCreds = await getEmbeddingCredentials();
            // Initialize components
            spinner.text = 'Connecting to services...';
            // Vector manager (optional but recommended)
            let vector = undefined;
            if ((embeddingCreds.openrouterApiKey || embeddingCreds.openaiApiKey) && config.vector) {
                try {
                    vector = createVectorManager({
                        url: config.vector.url,
                        openrouterApiKey: embeddingCreds.openrouterApiKey,
                        openaiApiKey: embeddingCreds.openaiApiKey,
                        collections: config.vector.collections,
                        embeddingModel: config.embedding?.model
                    });
                    await vector.connect();
                }
                catch (error) {
                    console.log(chalk.gray('  ⚠ Could not connect to vector DB - continuing without semantic search'));
                }
            }
            // Graph manager
            const graph = createGraphManager(config.graph.url, config.graph.database);
            await graph.connect();
            // Git manager
            const git = createGitManager(repoRoot);
            // AI manager
            const ai = createAIManager({
                provider: 'anthropic',
                model: config.ai.model,
                apiKey: anthropicApiKey
            }, vector, graph, git);
            // Use RLM Router for deep reasoning if --deep flag is set
            if (options.deep) {
                spinner.text = 'Starting deep reasoning...';
                const rlm = createRLMRouter({
                    apiKey: anthropicApiKey,
                    model: config.ai.model || 'claude-sonnet-4-5-20250514',
                    maxDepth: parseInt(options.maxDepth, 10) || 5,
                    maxTokens: config.ai.maxTokens
                }, vector, graph, git);
                try {
                    const result = await rlm.reason(target);
                    spinner.succeed(chalk.green(`Deep reasoning complete (depth: ${result.depth})`));
                    // Show sources if any
                    if (result.sources.length > 0) {
                        console.log();
                        console.log(chalk.bold.cyan('Sources:'));
                        result.sources.slice(0, 10).forEach(source => {
                            console.log(chalk.gray(`  • ${source}`));
                        });
                    }
                    // Show trace if --trace flag
                    if (options.trace && result.trace.length > 0) {
                        console.log();
                        console.log(chalk.bold.cyan('Reasoning Trace:'));
                        console.log(chalk.gray('─'.repeat(80)));
                        result.trace.forEach((step, i) => {
                            const indent = '  '.repeat(step.depth);
                            const duration = step.duration ? chalk.gray(` (${step.duration}ms)`) : '';
                            console.log(`${indent}${chalk.yellow(`${i + 1}.`)} ${chalk.cyan(step.taskType)}${duration}`);
                            console.log(`${indent}   ${chalk.gray(step.query.substring(0, 80))}${step.query.length > 80 ? '...' : ''}`);
                        });
                    }
                    // Show answer
                    console.log();
                    console.log(chalk.bold.cyan('Answer:'));
                    console.log(chalk.gray('─'.repeat(80)));
                    console.log();
                    console.log(result.answer);
                    console.log();
                    console.log(chalk.gray('─'.repeat(80)));
                    // Close connections
                    await graph.close();
                    if (vector)
                        await vector.close();
                    return;
                }
                catch (error) {
                    spinner.fail(chalk.red('Deep reasoning failed'));
                    console.error(chalk.red(`Error: ${error.message}`));
                    await graph.close();
                    if (vector)
                        await vector.close();
                    process.exit(1);
                }
            }
            spinner.text = 'Gathering context...';
            // Gather context for the target
            const context = await ai.gatherContext(target);
            if (context.chunks.length === 0 && context.symbols.length === 0) {
                spinner.warn(chalk.yellow('No relevant code found'));
                console.log();
                console.log(chalk.gray('Tips:'));
                console.log(chalk.gray('  • Make sure you have run `cv sync`'));
                console.log(chalk.gray('  • Try a different query or symbol name'));
                console.log(chalk.gray('  • Use `cv find` to search for code first'));
                console.log();
                await graph.close();
                if (vector)
                    await vector.close();
                process.exit(1);
            }
            spinner.succeed(chalk.green(`Found ${context.chunks.length} code chunks and ${context.symbols.length} symbols`));
            // Show context summary
            console.log();
            console.log(chalk.bold.cyan('Context:'));
            if (context.chunks.length > 0) {
                console.log(chalk.gray(`  📄 ${context.chunks.length} relevant code sections`));
                context.chunks.slice(0, 3).forEach(chunk => {
                    console.log(chalk.gray(`     • ${chunk.payload.symbolName || 'code'} in ${chunk.payload.file}`));
                });
            }
            if (context.symbols.length > 0) {
                console.log(chalk.gray(`  🔗 ${context.symbols.length} related symbols`));
            }
            console.log();
            // Generate explanation
            console.log(chalk.bold.cyan('Explanation:'));
            console.log(chalk.gray('─'.repeat(80)));
            console.log();
            if (options.stream) {
                // Stream the response
                await ai.explain(target, context, {
                    onToken: (token) => {
                        process.stdout.write(token);
                    },
                    onComplete: (fullText) => {
                        console.log();
                        console.log();
                        console.log(chalk.gray('─'.repeat(80)));
                    },
                    onError: (error) => {
                        console.error(chalk.red(`\nError: ${error.message}`));
                    }
                });
            }
            else {
                // Non-streaming
                spinner = ora('Asking Claude...').start();
                const explanation = await ai.explain(target, context);
                spinner.stop();
                console.log(explanation);
                console.log();
                console.log(chalk.gray('─'.repeat(80)));
            }
            // Close connections
            await graph.close();
            if (vector)
                await vector.close();
        }
        catch (error) {
            if (spinner) {
                spinner.fail(chalk.red('Explanation failed'));
            }
            console.error(chalk.red(`Error: ${error.message}`));
            if (error.message.includes('API key')) {
                console.error();
                console.error(chalk.yellow('Check your API key configuration'));
            }
            if (error.message.includes('rate limit')) {
                console.error();
                console.error(chalk.yellow('Rate limit exceeded - try again in a moment'));
            }
            if (process.env.CV_DEBUG) {
                console.error(chalk.gray(error.stack));
            }
            process.exit(1);
        }
    });
    return cmd;
}
//# sourceMappingURL=explain.js.map