/**
 * Explain Command - Explain code in files
 */
import chalk from 'chalk';
import { Marked } from 'marked';
import { markedTerminal } from 'marked-terminal';
import { createSpinner } from '../utils/logger.js';
import { APIClient, CLIError, classifyError, formatCLIError } from '../utils/api.js';
import { FileUtils } from '../utils/files.js';
export class ExplainCommand {
    config;
    logger;
    api;
    fileUtils;
    marked;
    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);
        this.marked = new Marked();
        this.marked.use(markedTerminal({
            showSectionPrefix: false,
            tab: 2,
            width: 80,
            reflowText: true,
        }));
    }
    async run(filePath, 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;
        }
        // Read file
        const file = this.fileUtils.readFile(filePath);
        if (!file) {
            this.logger.error(`File not found: ${filePath}`);
            return;
        }
        // Get code to explain
        let codeToExplain = file.content;
        let lineInfo = '';
        if (options.lines) {
            const [start, end] = options.lines.split('-').map(Number);
            const lines = this.fileUtils.readLines(filePath, start, end || start);
            if (lines) {
                codeToExplain = lines;
                lineInfo = ` (lines ${start}-${end || start})`;
            }
        }
        this.logger.section(`Explaining: ${file.relativePath}${lineInfo}`);
        console.log(chalk.gray(`Language: ${file.language} | Detail: ${options.detail}`));
        console.log();
        // Show the code being explained
        console.log(chalk.gray('─'.repeat(60)));
        codeToExplain.split('\n').forEach((line, i) => {
            const lineNum = chalk.gray(String(i + 1).padStart(4, ' ') + ' │ ');
            console.log(lineNum + line);
        });
        console.log(chalk.gray('─'.repeat(60)));
        console.log();
        const spinner = createSpinner({
            text: 'Analyzing code...',
            spinner: 'dots',
        }).start();
        try {
            const explanation = await this.api.explainCode(codeToExplain, file.language);
            spinner.stop();
            // Format based on detail level
            const formattedExplanation = this.formatExplanation(explanation, options.detail);
            this.logger.section('Explanation');
            console.log(this.cleanTerminalOutput(this.marked.parse(formattedExplanation)));
        }
        catch (error) {
            spinner.stop();
            const cliErr = error instanceof CLIError ? error : classifyError(error);
            this.logger.error(formatCLIError(cliErr));
        }
    }
    /**
     * Clean marked-terminal output for release-grade CLI presentation.
     * De-indents bullets, normalises bullet characters, and removes stray
     * ANSI-only lines that marked-terminal inserts between sub-items.
     */
    cleanTerminalOutput(raw) {
        let out = raw;
        // De-indent top-level bullets: '  * text' → '- text'
        out = out.replace(/^  \* /gm, '- ');
        // De-indent sub-level bullets: '    * text' → '  - text'
        out = out.replace(/^    \* /gm, '  - ');
        // Remove lines that are only whitespace + ANSI (no visible text)
        const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, '');
        out = out.split('\n').filter(line => {
            if (line === '')
                return true;
            return stripAnsi(line).trim().length > 0;
        }).join('\n');
        // Collapse 3+ consecutive newlines to 2
        out = out.replace(/\n{3,}/g, '\n\n');
        return out;
    }
    formatExplanation(explanation, detail) {
        // Normalize formatting: convert any numbered lists to bullet lists
        // to prevent broken nested numbering in terminal rendering.
        let cleaned = explanation.replace(/^(\s*)\d+\.\s+/gm, '$1- ');
        // Collapse excessive blank lines (3+ → 2)
        cleaned = cleaned.replace(/\n{3,}/g, '\n\n');
        switch (detail) {
            case 'brief':
                // Extract just the summary
                const lines = cleaned.split('\n');
                const summaryLines = lines.slice(0, Math.min(lines.length, 5));
                return summaryLines.join('\n');
            case 'detailed':
                return cleaned + '\n\n---\n*Detailed analysis by Vigthoria*';
            case 'normal':
            default:
                return cleaned;
        }
    }
}
