import { installAgentsCommand } from "../agents/command.js";
import { HEAVY_NPM_DEPS } from "./heavyDeps.js";
// Re-register the agents command under the bare name `agents` for use inside
// the `install <subcommand>` group. The original `install-agents` registration
// remains in cli.ts as a hidden top-level alias for back-compat.
const agentsSubcommand = {
    ...installAgentsCommand,
    command: "agents",
};
function pickLogLevel(argv) {
    if (argv.silent || argv.quiet)
        return "error";
    if (argv.verbose)
        return "debug";
    return "info";
}
function makeLogger(level) {
    const order = {
        debug: 0,
        info: 1,
        warn: 2,
        error: 3,
    };
    const threshold = order[level];
    return (msg, lvl = "info") => {
        if (order[lvl] < threshold)
            return;
        if (lvl === "error")
            console.error(msg);
        else
            console.log(msg);
    };
}
const sharedInstallOptions = (yargs) => yargs
    .option("yes", {
    alias: "y",
    type: "boolean",
    default: false,
    describe: "Skip interactive prompts (auto-install missing assets without confirming).",
})
    .option("force", {
    alias: "f",
    type: "boolean",
    default: false,
    describe: "Reinstall even if the asset is already present and current. Prunes any older versions in the cache.",
})
    .option("dry-run", {
    type: "boolean",
    default: false,
    describe: "Report the actions that would be taken without executing them.",
})
    .option("silent", {
    type: "boolean",
    default: false,
    describe: "Suppress all output except errors. Alias: --quiet.",
})
    .option("quiet", {
    type: "boolean",
    default: false,
    describe: "Same as --silent.",
})
    .option("verbose", {
    type: "boolean",
    default: false,
    describe: "Emit debug-level output, including child-process (npm) stdout/stderr.",
})
    .option("cache-dir", {
    type: "string",
    describe: "Override the cache root for this invocation (also DOC_DETECTIVE_CACHE_DIR env var).",
});
function ctxFromArgv(argv) {
    return argv.cacheDir ? { cacheDir: argv.cacheDir } : {};
}
function printReports(reports, logger) {
    for (const r of reports) {
        const ver = r.installedVersion ? ` @ ${r.installedVersion}` : "";
        const notes = r.notes && r.notes.length > 0 ? ` (${r.notes.join("; ")})` : "";
        logger(`  [${r.kind}] ${r.assetId} — ${r.action}${ver}${notes}`, "info");
    }
}
const runtimeSubcommand = {
    command: "runtime [packages..]",
    describe: `Install heavy npm packages into <cacheDir>/runtime. Supported: ${HEAVY_NPM_DEPS.join(", ")}.`,
    builder: (yargs) => sharedInstallOptions(yargs).positional("packages", {
        describe: "Package names to install (defaults to every heavy dep when omitted).",
        type: "string",
        array: true,
    }),
    handler: async (argv) => {
        const logger = makeLogger(pickLogLevel(argv));
        const requested = Array.isArray(argv.packages)
            ? argv.packages
            : undefined;
        if (requested && requested.length > 0) {
            // Validate up front so an unknown name yields a user-friendly error
            // listing supported values, rather than the developer-facing
            // `getDeclaredVersion()` "not declared in package.json" exception
            // deep inside the installer.
            const supported = new Set(HEAVY_NPM_DEPS);
            const unknown = requested.filter((name) => !supported.has(name));
            if (unknown.length > 0) {
                logger(`Unknown runtime package(s): ${unknown.join(", ")}. Supported names: ${HEAVY_NPM_DEPS.join(", ")}.`, "error");
                process.exitCode = 1;
                return;
            }
        }
        const { installRuntime } = await import("./installer.js");
        const reports = await installRuntime({
            packages: requested,
            force: Boolean(argv.force),
            dryRun: Boolean(argv["dry-run"]),
            ctx: ctxFromArgv(argv),
            deps: { logger },
        });
        printReports(reports, logger);
    },
};
const browsersSubcommand = {
    command: "browsers [names..]",
    describe: "Install browsers + drivers (chrome, firefox, chromedriver, geckodriver) into <cacheDir>/browsers.",
    builder: (yargs) => sharedInstallOptions(yargs).positional("names", {
        describe: "Browser/driver names to install (defaults to all when omitted).",
        type: "string",
        array: true,
        choices: ["chrome", "firefox", "chromedriver", "geckodriver"],
    }),
    handler: async (argv) => {
        const logger = makeLogger(pickLogLevel(argv));
        const { installBrowsers } = await import("./installer.js");
        const reports = await installBrowsers({
            names: Array.isArray(argv.names) ? argv.names : undefined,
            force: Boolean(argv.force),
            dryRun: Boolean(argv["dry-run"]),
            ctx: ctxFromArgv(argv),
            deps: { logger },
        });
        printReports(reports, logger);
    },
};
const statusSubcommand = {
    command: "status",
    describe: "Report what's installed in <cacheDir>/runtime and <cacheDir>/browsers vs. the shim's declared versions.",
    builder: (yargs) => sharedInstallOptions(yargs),
    handler: async (argv) => {
        const logger = makeLogger(pickLogLevel(argv));
        const { status } = await import("./installer.js");
        const rows = status(ctxFromArgv(argv));
        for (const r of rows) {
            const present = r.installed ? r.installedVersion ?? "?" : "—";
            const expected = r.expectedVersion ?? r.latestKnownVersion ?? "—";
            const note = r.outdated ? " (outdated)" : "";
            logger(`  [${r.kind}] ${r.assetId}: installed=${present} expected=${expected}${note}`, "info");
        }
    },
};
const allSubcommand = {
    command: "all",
    describe: "Install all lazy-installed runtime assets: runtime npm packages and browser binaries. Agent tools are installed separately via `install agents` (they require an interactive picker for per-agent scope choices).",
    builder: (yargs) => sharedInstallOptions(yargs),
    handler: async (argv) => {
        const logger = makeLogger(pickLogLevel(argv));
        const { installRuntime, installBrowsers } = await import("./installer.js");
        logger("Installing runtime…", "info");
        printReports(await installRuntime({
            force: Boolean(argv.force),
            dryRun: Boolean(argv["dry-run"]),
            ctx: ctxFromArgv(argv),
            deps: { logger },
        }), logger);
        logger("Installing browsers…", "info");
        printReports(await installBrowsers({
            force: Boolean(argv.force),
            dryRun: Boolean(argv["dry-run"]),
            ctx: ctxFromArgv(argv),
            deps: { logger },
        }), logger);
    },
};
/**
 * The `doc-detective install` command group. Registers four subcommands and
 * a bare `install` form that prints help. The existing `install-agents`
 * command keeps its top-level registration as a permanent hidden alias
 * (configured in cli.ts).
 */
export const installCommand = {
    command: "install <subcommand>",
    describe: "Install doc-detective's lazy-loaded assets: agents, runtime, browsers.",
    builder: (yargs) => yargs
        .command(agentsSubcommand)
        .command(runtimeSubcommand)
        .command(browsersSubcommand)
        .command(statusSubcommand)
        .command(allSubcommand)
        .demandCommand(1, "Specify a subcommand: agents | runtime | browsers | status | all."),
    handler: () => {
        // Each subcommand registers its own handler; this top-level handler is
        // only reached when yargs falls through (demandCommand should prevent
        // that, but in defensive coding we still print help).
    },
};
//# sourceMappingURL=installCommand.js.map