import { Buffer } from 'node:buffer';

type Agent = 'npm' | 'yarn' | 'yarn@berry' | 'pnpm' | 'pnpm@6' | 'bun' | 'deno';
type AgentName = 'npm' | 'yarn' | 'pnpm' | 'bun' | 'deno';
type AgentCommandValue = (string | number)[] | ((args: string[]) => string[]) | null;
interface AgentCommands {
    'agent': AgentCommandValue;
    'run': AgentCommandValue;
    'install': AgentCommandValue;
    'frozen': AgentCommandValue;
    'global': AgentCommandValue;
    'add': AgentCommandValue;
    'upgrade': AgentCommandValue;
    'upgrade-interactive': AgentCommandValue;
    'execute': AgentCommandValue;
    'execute-local': AgentCommandValue;
    'uninstall': AgentCommandValue;
    'global_uninstall': AgentCommandValue;
}
type Command = keyof AgentCommands;
interface ResolvedCommand {
    /**
     * CLI command.
     */
    command: string;
    /**
     * Arguments for the CLI command, merged with user arguments.
     */
    args: string[];
}

declare const COMMANDS: {
    npm: AgentCommands;
    yarn: AgentCommands;
    'yarn@berry': AgentCommands;
    pnpm: AgentCommands;
    'pnpm@6': AgentCommands;
    bun: AgentCommands;
    deno: AgentCommands;
};
/**
 * Resolve the command for the agent merging the command arguments with the provided arguments.
 *
 * For example, to show how to install `@antfu/ni` globally using `pnpm`:
 * ```js
 * import { resolveCommand } from 'package-manager-detector/commands'
 * const { command, args } = resolveCommand('pnpm', 'global', ['@antfu/ni'])
 * console.log(`${command} ${args.join(' ')}`) // 'pnpm add -g @antfu/ni'
 * ```
 *
 * @param agent The agent to use.
 * @param command the command to resolve.
 * @param args The arguments to pass to the command.
 * @returns {ResolvedCommand} The resolved command or `null` if the agent command is not found.
 */
declare function resolveCommand(agent: Agent, command: Command, args: string[]): ResolvedCommand | null;
/**
 * Construct the command from the agent command merging the command arguments with the provided arguments.
 * @param value {AgentCommandValue} The agent command to use.
 * @param args The arguments to pass to the command.
 * @returns {ResolvedCommand} The resolved command or `null` if the command is `null`.
 */
declare function constructCommand(value: AgentCommandValue, args: string[]): ResolvedCommand | null;

declare const AGENTS: Agent[];
declare const LOCKS: Record<string, AgentName>;
declare const INSTALL_PAGE: Record<Agent, string>;

interface Config {
    defaultAgent: Agent | 'prompt';
    globalAgent: Agent;
}
declare function getConfig(): Promise<Config>;
declare function getDefaultAgent(programmatic?: boolean): Promise<Agent | "prompt">;
declare function getGlobalAgent(): Promise<Agent>;

interface DetectOptions {
    autoInstall?: boolean;
    programmatic?: boolean;
    cwd?: string;
    /**
     * Should use Volta when present
     *
     * @see https://volta.sh/
     * @default true
     */
    detectVolta?: boolean;
}
declare function detect({ autoInstall, programmatic, cwd }?: DetectOptions): Promise<Agent | undefined>;

interface RunnerContext {
    programmatic?: boolean;
    hasLock?: boolean;
    cwd?: string;
}
type Runner = (agent: Agent, args: string[], ctx?: RunnerContext) => Promise<ResolvedCommand | undefined> | ResolvedCommand | undefined;
declare function runCli(fn: Runner, options?: DetectOptions & {
    args?: string[];
}): Promise<void>;
declare function getCliCommand(fn: Runner, args: string[], options?: DetectOptions, cwd?: string): Promise<ResolvedCommand | undefined>;
declare function run(fn: Runner, args: string[], options?: DetectOptions): Promise<void>;

declare class UnsupportedCommand extends Error {
    constructor({ agent, command }: {
        agent: Agent;
        command: Command;
    });
}
declare function getCommand(agent: Agent, command: Command, args?: string[]): ResolvedCommand;
declare const parseNi: Runner;
declare const parseNr: Runner;
declare const parseNu: Runner;
declare const parseNun: Runner;
declare const parseNlx: Runner;
declare const parseNa: Runner;
declare function serializeCommand(command?: ResolvedCommand): string | undefined;

declare const CLI_TEMP_DIR: string;
declare function remove<T>(arr: T[], v: T): T[];
declare function exclude<T>(arr: T[], ...v: T[]): T[];
declare function cmdExists(cmd: string): boolean;
/**
 * Write file safely avoiding conflicts
 */
declare function writeFileSafe(path: string, data?: string | Buffer): Promise<boolean>;
declare function limitText(text: string, maxWidth: number): string;
declare function formatPackageWithUrl(pkg: string, url?: string, limits?: number): string;

export { AGENTS, CLI_TEMP_DIR, COMMANDS, type DetectOptions, INSTALL_PAGE, LOCKS, type Runner, type RunnerContext, UnsupportedCommand, cmdExists, constructCommand, detect, exclude, formatPackageWithUrl, getCliCommand, getCommand, getConfig, getDefaultAgent, getGlobalAgent, limitText, parseNa, parseNi, parseNlx, parseNr, parseNu, parseNun, remove, resolveCommand, run, runCli, serializeCommand, writeFileSafe };
