import { discoverShowcases, findShowcase } from '../utils/discover-showcases.js';
import { runMinimalChecks, detectPackageManager, buildInstallCommand } from '../utils/check-system-deps.js';
import { spawn } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { readFileSync } from 'node:fs';
function readCliVersion() {
    try {
        const pkgUrl = new URL('../../package.json', import.meta.url);
        const pkg = JSON.parse(readFileSync(pkgUrl, 'utf8'));
        return typeof pkg.version === 'string' ? pkg.version : undefined;
    }
    catch {
        return undefined;
    }
}
export const showcaseCommand = {
    command: 'showcase [name]',
    description: 'List or run curated gjsify showcase applications.',
    builder: (yargs) => yargs
        .positional('name', {
        description: 'Showcase name to run (omit to list all)',
        type: 'string',
    })
        .option('json', {
        description: 'Output as JSON',
        type: 'boolean',
        default: false,
    })
        .option('list', {
        description: 'List available showcases',
        type: 'boolean',
        default: false,
    }),
    handler: async (args) => {
        // List mode: no name given, or --list flag
        if (!args.name || args.list) {
            const showcases = discoverShowcases();
            if (args.json) {
                console.log(JSON.stringify(showcases, null, 2));
                return;
            }
            if (showcases.length === 0) {
                console.log('No showcases found. The CLI ships a curated list in `showcases.json`; if it is missing the CLI install is incomplete.');
                return;
            }
            const grouped = new Map();
            for (const sc of showcases) {
                const list = grouped.get(sc.category) ?? [];
                list.push(sc);
                grouped.set(sc.category, list);
            }
            console.log('Available gjsify showcases:\n');
            for (const [category, list] of grouped) {
                console.log(`  ${category.toUpperCase()}:`);
                const maxNameLen = Math.max(...list.map((e) => e.name.length));
                for (const sc of list) {
                    const pad = ' '.repeat(maxNameLen - sc.name.length + 2);
                    const desc = sc.description ? `${pad}${sc.description}` : '';
                    console.log(`    ${sc.name}${desc}`);
                }
                console.log('');
            }
            console.log('Run a showcase:  gjsify showcase <name>');
            return;
        }
        const showcase = findShowcase(args.name);
        if (!showcase) {
            console.error(`Unknown showcase: "${args.name}"`);
            console.error('Run "gjsify showcase" to list available showcases.');
            process.exit(1);
        }
        // System dependency check before delegating — only system libs (gjs,
        // gtk4, …). The showcase's npm deps (incl. `@gjsify/webgl` with the
        // gwebgl Vala prebuild) are fetched by `gjsify dlx` into the npm
        // cache, and `runGjsBundle()` picks the prebuild up from the bundle
        // dir via `detectNativePackages()`. Pre-flight-checking npm deps
        // here would fail for `npx @gjsify/cli showcase` (no project
        // node_modules, CLI doesn't dep on the showcase libs).
        const results = runMinimalChecks();
        const missingHard = results.filter((r) => !r.found && r.severity === 'required');
        if (missingHard.length > 0) {
            console.error('Missing system dependencies:\n');
            for (const dep of missingHard) {
                console.error(`  ✗  ${dep.name}`);
            }
            const pm = detectPackageManager();
            const cmd = buildInstallCommand(pm, missingHard);
            if (cmd) {
                console.error(`\nInstall with:\n  ${cmd}`);
            }
            process.exit(1);
        }
        // Delegate to `gjsify dlx <package>@<cli-version>` — same npm-cache,
        // same atomic symlink-swap, same `gjsify.main` resolution. Re-spawning
        // the CLI keeps the dlx logic in one place.
        //
        // Pinning to the CLI's own version is load-bearing: showcases ship in
        // lockstep with the CLI, so users running `npx @gjsify/cli@X showcase
        // <name>` expect the matching `@gjsify/example-*@X`. Without the pin,
        // dlx caches the first resolved-latest on disk; subsequent CLI
        // releases leave that cache untouched until the 7-day TTL expires,
        // and the user gets a stale showcase that may be missing deps the
        // newer CLI assumes (the `@gjsify/http-soup-bridge` regression
        // reported against `@gjsify/cli@0.3.17`).
        const cliVersion = readCliVersion();
        const dlxSpec = cliVersion ? `${showcase.packageName}@${cliVersion}` : showcase.packageName;
        console.log(`Running showcase: ${showcase.name} (via gjsify dlx ${dlxSpec})\n`);
        const cliBin = fileURLToPath(new URL('../index.js', import.meta.url));
        const child = spawn(process.execPath, [cliBin, 'dlx', dlxSpec], {
            stdio: 'inherit',
        });
        await new Promise((resolvePromise, reject) => {
            child.on('close', (code) => {
                if (code !== 0) {
                    reject(new Error(`gjsify dlx exited with code ${code}`));
                }
                else {
                    resolvePromise();
                }
            });
            child.on('error', reject);
        }).catch((err) => {
            console.error(err.message);
            process.exit(1);
        });
    },
};
