import chalk from "chalk";
import { selectConfig } from "./cli/config-selector.js";
import { APP_NAME, getAgentDir } from "./config.js";
import { DefaultPackageManager } from "./core/package-manager.js";
import { SettingsManager } from "./core/settings-manager.js";
function reportSettingsErrors(settingsManager, context) {
    const errors = settingsManager.drainErrors();
    for (const { scope, error } of errors) {
        console.error(chalk.yellow(`Warning (${context}, ${scope} settings): ${error.message}`));
        if (error.stack) {
            console.error(chalk.dim(error.stack));
        }
    }
}
function getPackageCommandUsage(command) {
    switch (command) {
        case "install":
            return `${APP_NAME} install <source> [-l]`;
        case "remove":
            return `${APP_NAME} remove <source> [-l]`;
        case "update":
            return `${APP_NAME} update [source]`;
        case "list":
            return `${APP_NAME} list`;
    }
}
function printPackageCommandHelp(command) {
    switch (command) {
        case "install":
            console.log(`${chalk.bold("Usage:")}
  ${getPackageCommandUsage("install")}

Install a package and add it to settings.

Options:
  -l, --local    Install project-locally (.pi/settings.json)

Examples:
  ${APP_NAME} install npm:@foo/bar
  ${APP_NAME} install git:github.com/user/repo
  ${APP_NAME} install git:git@github.com:user/repo
  ${APP_NAME} install https://github.com/user/repo
  ${APP_NAME} install ssh://git@github.com/user/repo
  ${APP_NAME} install ./local/path
`);
            return;
        case "remove":
            console.log(`${chalk.bold("Usage:")}
  ${getPackageCommandUsage("remove")}

Remove a package and its source from settings.
Alias: ${APP_NAME} uninstall <source> [-l]

Options:
  -l, --local    Remove from project settings (.pi/settings.json)

Examples:
  ${APP_NAME} remove npm:@foo/bar
  ${APP_NAME} uninstall npm:@foo/bar
`);
            return;
        case "update":
            console.log(`${chalk.bold("Usage:")}
  ${getPackageCommandUsage("update")}

Update installed packages.
If <source> is provided, only that package is updated.
`);
            return;
        case "list":
            console.log(`${chalk.bold("Usage:")}
  ${getPackageCommandUsage("list")}

List installed packages from user and project settings.
`);
            return;
    }
}
function parsePackageCommand(args) {
    const [rawCommand, ...rest] = args;
    let command;
    if (rawCommand === "uninstall") {
        command = "remove";
    }
    else if (rawCommand === "install" || rawCommand === "remove" || rawCommand === "update" || rawCommand === "list") {
        command = rawCommand;
    }
    if (!command) {
        return undefined;
    }
    let local = false;
    let help = false;
    let invalidOption;
    let source;
    for (const arg of rest) {
        if (arg === "-h" || arg === "--help") {
            help = true;
            continue;
        }
        if (arg === "-l" || arg === "--local") {
            if (command === "install" || command === "remove") {
                local = true;
            }
            else {
                invalidOption = invalidOption ?? arg;
            }
            continue;
        }
        if (arg.startsWith("-")) {
            invalidOption = invalidOption ?? arg;
            continue;
        }
        if (!source) {
            source = arg;
        }
    }
    return { command, source, local, help, invalidOption };
}
export async function handleConfigCommand(args) {
    if (args[0] !== "config") {
        return false;
    }
    const cwd = process.cwd();
    const agentDir = getAgentDir();
    const settingsManager = SettingsManager.create(cwd, agentDir);
    reportSettingsErrors(settingsManager, "config command");
    const packageManager = new DefaultPackageManager({ cwd, agentDir, settingsManager });
    const resolvedPaths = await packageManager.resolve();
    await selectConfig({
        resolvedPaths,
        settingsManager,
        cwd,
        agentDir,
    });
    process.exit(0);
}
export async function handlePackageCommand(args) {
    const options = parsePackageCommand(args);
    if (!options) {
        return false;
    }
    if (options.help) {
        printPackageCommandHelp(options.command);
        return true;
    }
    if (options.invalidOption) {
        console.error(chalk.red(`Unknown option ${options.invalidOption} for "${options.command}".`));
        console.error(chalk.dim(`Use "${APP_NAME} --help" or "${getPackageCommandUsage(options.command)}".`));
        process.exitCode = 1;
        return true;
    }
    const source = options.source;
    if ((options.command === "install" || options.command === "remove") && !source) {
        console.error(chalk.red(`Missing ${options.command} source.`));
        console.error(chalk.dim(`Usage: ${getPackageCommandUsage(options.command)}`));
        process.exitCode = 1;
        return true;
    }
    const cwd = process.cwd();
    const agentDir = getAgentDir();
    const settingsManager = SettingsManager.create(cwd, agentDir);
    reportSettingsErrors(settingsManager, "package command");
    const packageManager = new DefaultPackageManager({ cwd, agentDir, settingsManager });
    packageManager.setProgressCallback((event) => {
        if (event.type === "start") {
            process.stdout.write(chalk.dim(`${event.message}\n`));
        }
    });
    try {
        switch (options.command) {
            case "install":
                await packageManager.installAndPersist(source, { local: options.local });
                console.log(chalk.green(`Installed ${source}`));
                return true;
            case "remove": {
                const removed = await packageManager.removeAndPersist(source, { local: options.local });
                if (!removed) {
                    console.error(chalk.red(`No matching package found for ${source}`));
                    process.exitCode = 1;
                    return true;
                }
                console.log(chalk.green(`Removed ${source}`));
                return true;
            }
            case "list": {
                const configuredPackages = packageManager.listConfiguredPackages();
                const userPackages = configuredPackages.filter((pkg) => pkg.scope === "user");
                const projectPackages = configuredPackages.filter((pkg) => pkg.scope === "project");
                if (configuredPackages.length === 0) {
                    console.log(chalk.dim("No packages installed."));
                    return true;
                }
                const formatPackage = (pkg) => {
                    const display = pkg.filtered ? `${pkg.source} (filtered)` : pkg.source;
                    console.log(`  ${display}`);
                    if (pkg.installedPath) {
                        console.log(chalk.dim(`    ${pkg.installedPath}`));
                    }
                };
                if (userPackages.length > 0) {
                    console.log(chalk.bold("User packages:"));
                    for (const pkg of userPackages) {
                        formatPackage(pkg);
                    }
                }
                if (projectPackages.length > 0) {
                    if (userPackages.length > 0)
                        console.log();
                    console.log(chalk.bold("Project packages:"));
                    for (const pkg of projectPackages) {
                        formatPackage(pkg);
                    }
                }
                return true;
            }
            case "update":
                await packageManager.update(source);
                if (source) {
                    console.log(chalk.green(`Updated ${source}`));
                }
                else {
                    console.log(chalk.green("Updated packages"));
                }
                return true;
        }
    }
    catch (error) {
        const message = error instanceof Error ? error.message : "Unknown package command error";
        console.error(chalk.red(`Error: ${message}`));
        process.exitCode = 1;
        return true;
    }
}
//# sourceMappingURL=package-manager-cli.js.map