import fs from 'fs/promises';
import { existsSync } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import chalk from 'chalk';
import { renderMarkdown } from '../output/markdown.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const ONLINE_BASE = 'https://developers.openrainbow.com/doc/sdk/cli-ng';

const GUIDE_ORDER = ['home', 'installation', 'configuration', 'usage', 'troubleshooting'];

const GUIDE_TITLES = {
    fr: {
        home: 'Accueil',
        installation: 'Installation',
        configuration: 'Configuration',
        usage: "Guide d'utilisation",
        troubleshooting: 'Dépannage',
    },
    en: {
        home: 'Home',
        installation: 'Installation',
        configuration: 'Configuration',
        usage: 'Usage Guide',
        troubleshooting: 'Troubleshooting',
    },
    de: {
        home: 'Startseite',
        installation: 'Installation',
        configuration: 'Konfiguration',
        usage: 'Benutzerhandbuch',
        troubleshooting: 'Fehlerbehebung',
    },
};

export class Docs {
    constructor(program, logger, services) {
        this.logger = logger;
        this.services = services;
        services['docs'] = this;

        const docsCmd = program
            .command('docs')
            .description('Browse the Rainbow CLI NG documentation');

        docsCmd
            .command('list')
            .description('List available documentation guides')
            .option('--lang <lang>', 'language: fr, en, de', 'fr')
            .action((opts) => this._cmdList(opts));

        docsCmd
            .command('show')
            .argument('<guide>', 'guide: home, installation, configuration, usage, troubleshooting')
            .description('Display a documentation guide in the terminal')
            .option('--lang <lang>', 'language: fr, en, de', 'fr')
            .option('-s, --section <text>', 'show only the section matching this text')
            .action((guide, opts) => this._cmdShow(guide, opts));

        docsCmd
            .command('browse')
            .description('Interactive TUI browser for the documentation')
            .option('--lang <lang>', 'language: fr, en, de', 'fr')
            .option('-q, --query <text>', 'initial search filter')
            .action(async (opts) => this._cmdBrowse(opts));

        docsCmd
            .command('open')
            .argument('[guide]', 'guide to open (default: home)')
            .description('Open the online documentation in a browser')
            .option('--lang <lang>', 'language: fr, en, de', 'fr')
            .action(async (guide, opts) => this._cmdOpen(guide, opts));
    }

    // ---------------------------------------------------------------------------
    // Chargement
    // ---------------------------------------------------------------------------

    _docsDir(lang) {
        return path.join(__dirname, '..', 'docs', lang);
    }

    async _loadGuides(lang) {
        const dir = this._docsDir(lang);
        if (!existsSync(dir)) return [];

        const sections = [];
        const titles = {};

        for (const name of GUIDE_ORDER) {
            const filepath = path.join(dir, `${name}.md`);
            try {
                const content = await fs.readFile(filepath, 'utf-8');
                const parsed = this._parseMarkdown(name, content);
                titles[name] = parsed.title;
                sections.push(...parsed.sections);
            } catch {
                // guide non disponible, on skip silencieusement
            }
        }

        return { sections, titles };
    }

    _parseMarkdown(guideName, content) {
        const lines = content.split('\n');
        let title = (GUIDE_TITLES.fr[guideName] ?? guideName);
        const sections = [];
        let currentTitle = null;
        let currentLevel = 0;
        let currentLines = [];

        const flush = () => {
            if (currentTitle !== null) {
                const sectionContent = currentLines.join('\n').trim();
                sections.push({
                    guide: guideName,
                    guideTitle: title,
                    section: currentTitle,
                    level: currentLevel,
                    content: sectionContent,
                    searchText: (guideName + ' ' + title + ' ' + currentTitle + ' ' + sectionContent).toLowerCase(),
                });
                currentLines = [];
            }
        };

        for (const line of lines) {
            const h1 = line.match(/^## (.+)/);   // les guides utilisent ## comme titre principal
            const h2 = line.match(/^### (.+)/);
            if (h1) { title = h1[1]; }
            else if (h2) { flush(); currentTitle = h2[1]; currentLevel = 3; }
            else { currentLines.push(line); }
        }
        flush();

        if (!sections.length) {
            sections.push({ guide: guideName, guideTitle: title, section: title, level: 2, content: content.trim(), searchText: (guideName + ' ' + title + ' ' + content).toLowerCase() });
        }

        return { title, sections };
    }

    // ---------------------------------------------------------------------------
    // Commandes
    // ---------------------------------------------------------------------------

    async _cmdList(opts) {
        const lang = (opts.lang || 'fr').toLowerCase();
        const data = await this._loadGuides(lang);
        const labels = GUIDE_TITLES[lang] ?? GUIDE_TITLES.en;

        console.log('');
        console.log(chalk.bold.white('  Rainbow CLI NG — Documentation'));
        console.log(chalk.dim('  ' + '─'.repeat(40)));
        console.log('');

        for (const name of GUIDE_ORDER) {
            const label = labels[name] ?? name;
            if (!data.titles?.[name]) continue;
            console.log(`  ${chalk.bold.cyan(label)}  ${chalk.dim(name + '.md')}`);
        }

        console.log('');
        console.log(chalk.dim(`  rbw docs show <name> [--lang ${lang}]`));
        console.log(chalk.dim(`  rbw docs browse      [--lang ${lang}]`));
        console.log(chalk.dim(`  rbw docs open        [--lang ${lang}]`));
        console.log('');
    }

    async _cmdShow(guideQuery, opts) {
        const lang = (opts.lang || 'fr').toLowerCase();
        const dir = this._docsDir(lang);

        const name = GUIDE_ORDER.find(n => n.toLowerCase().startsWith(guideQuery.toLowerCase()))
            ?? GUIDE_ORDER.find(n => (GUIDE_TITLES[lang]?.[n] ?? '').toLowerCase().includes(guideQuery.toLowerCase()));

        if (!name) {
            console.log(chalk.red(`  Guide inconnu : "${guideQuery}"`));
            console.log(chalk.dim(`  Disponibles : ${GUIDE_ORDER.join(', ')}`));
            return;
        }

        const filepath = path.join(dir, `${name}.md`);
        if (!existsSync(filepath)) {
            console.log(chalk.yellow(`  Guide "${name}" non disponible en ${lang}.`));
            return;
        }

        const content = await fs.readFile(filepath, 'utf-8');

        if (opts.section) {
            const filter = opts.section.toLowerCase();
            const parsed = this._parseMarkdown(name, content);
            const matched = parsed.sections.filter(s => s.section.toLowerCase().includes(filter));
            if (!matched.length) {
                console.log(chalk.yellow(`  Aucune section contenant "${opts.section}".`));
                return;
            }
            for (const s of matched) {
                console.log(renderMarkdown(`### ${s.section}\n\n${s.content}`));
            }
        } else {
            console.log(renderMarkdown(content));
        }
    }

    async _cmdBrowse(opts) {
        const lang = (opts.lang || 'fr').toLowerCase();
        const data = await this._loadGuides(lang);

        if (!data.sections?.length) {
            console.log(chalk.yellow(`  Aucune documentation disponible en ${lang}.`));
            return;
        }

        const blessed = (await import('blessed')).default;
        const { GuideBrowser } = await import('../output/GuideBrowser.js');

        const screen = blessed.screen({ smartCSR: true, title: 'Rainbow CLI NG — Documentation' });
        new GuideBrowser({
            screen,
            sections: data.sections,
            guideTitles: data.titles,
            initialQuery: opts.query || '',
        });
        screen.render();
    }

    async _cmdOpen(guide, opts) {
        const lang = (opts.lang || 'fr').toLowerCase();
        const name = guide
            ? (GUIDE_ORDER.find(n => n.toLowerCase().startsWith(guide.toLowerCase())) ?? guide)
            : 'home';

        const url = `${ONLINE_BASE}/${lang}/guides/${name}`;
        console.log(chalk.dim(`  Ouverture de : ${url}`));

        try {
            const { default: open } = await import('open');
            await open(url);
        } catch (err) {
            console.log(chalk.yellow(`  Impossible d'ouvrir le navigateur automatiquement.`));
            console.log(chalk.white(`  URL : ${url}`));
        }
    }
}
