import type { Compiler } from '@rspack/core';
import { Configuration } from '@rspack/core';
import type { MultiCompiler } from '@rspack/core';
import type { MultiRspackOptions } from '@rspack/core';
import type { MultiStats } from '@rspack/core';
import type { RspackOptions } from '@rspack/core';
import type { RspackPluginFunction } from '@rspack/core';
import type { RspackPluginInstance } from '@rspack/core';
import type { Stats } from '@rspack/core';

declare class CAC extends EventTarget {
    /** The program name to display in help and version message */
    name: string;
    commands: Command[];
    globalCommand: GlobalCommand;
    matchedCommand?: Command;
    matchedCommandName?: string;
    /**
     * Raw CLI arguments
     */
    rawArgs: string[];
    /**
     * Parsed CLI arguments
     */
    args: ParsedArgv["args"];
    /**
     * Parsed CLI options, camelCased
     */
    options: ParsedArgv["options"];
    showHelpOnExit?: boolean;
    showVersionOnExit?: boolean;
    /**
     * @param name The program name to display in help and version message
     */
    constructor(name?: string);
    /**
     * Add a global usage text.
     *
     * This is not used by sub-commands.
     */
    usage(text: string): this;
    /**
     * Add a sub-command
     */
    command(rawName: string, description?: string, config?: CommandConfig): Command;
    /**
     * Add a global CLI option.
     *
     * Which is also applied to sub-commands.
     */
    option(rawName: string, description: string, config?: OptionConfig): this;
    /**
     * Show help message when `-h, --help` flags appear.
     *
     */
    help(callback?: HelpCallback): this;
    /**
     * Show version number when `-v, --version` flags appear.
     *
     */
    version(version: string, customFlags?: string): this;
    /**
     * Add a global example.
     *
     * This example added here will not be used by sub-commands.
     */
    example(example: CommandExample): this;
    /**
     * Output the corresponding help message
     * When a sub-command is matched, output the help message for the command
     * Otherwise output the global one.
     *
     */
    outputHelp(): void;
    /**
     * Output the version number.
     *
     */
    outputVersion(): void;
    private setParsedInfo;
    unsetMatchedCommand(): void;
    /**
     * Parse argv
     */
    parse(argv?: string[], {
        run
    }?: {
        /** Whether to run the action for matched command */run?: boolean | undefined;
    }): ParsedArgv;
    private mri;
    runMatchedCommand(): any;
}

declare class Command {
    rawName: string;
    description: string;
    config: CommandConfig;
    cli: CAC;
    options: Option_2[];
    aliasNames: string[];
    name: string;
    args: CommandArg[];
    commandAction?: (...args: any[]) => any;
    usageText?: string;
    versionNumber?: string;
    examples: CommandExample[];
    helpCallback?: HelpCallback;
    globalCommand?: GlobalCommand;
    constructor(rawName: string, description: string, config: CommandConfig | undefined, cli: CAC);
    usage(text: string): this;
    allowUnknownOptions(): this;
    ignoreOptionDefaultValue(): this;
    version(version: string, customFlags?: string): this;
    example(example: CommandExample): this;
    /**
     * Add a option for this command
     * @param rawName Raw option name(s)
     * @param description Option description
     * @param config Option config
     */
    option(rawName: string, description: string, config?: OptionConfig): this;
    alias(name: string): this;
    action(callback: (...args: any[]) => any): this;
    /**
     * Check if a command name is matched by this command
     * @param name Command name
     */
    isMatched(name: string): boolean;
    get isDefaultCommand(): boolean;
    get isGlobalCommand(): boolean;
    /**
     * Check if an option is registered in this command
     * @param name Option name
     */
    hasOption(name: string): Option_2 | undefined;
    outputHelp(): void;
    outputVersion(): void;
    checkRequiredArgs(): void;
    /**
     * Check if the parsed options contain any unknown options
     *
     * Exit and output error when true
     */
    checkUnknownOptions(): void;
    /**
     * Check if the required string-type options exist
     */
    checkOptionValue(): void;
    /**
     * Check if the number of args is more than expected
     */
    checkUnusedArgs(): void;
}

declare type Command_2 = 'serve' | 'build';

declare interface CommandArg {
    required: boolean;
    value: string;
    variadic: boolean;
}

declare interface CommandConfig {
    allowUnknownOptions?: boolean;
    ignoreOptionDefaultValue?: boolean;
}

declare type CommandExample = ((bin: string) => string) | string;

declare type CommonOptions = {
    config?: string;
    configName?: string[];
    configLoader?: ConfigLoader;
    env?: Record<string, unknown> | string[];
    nodeEnv?: string;
};

declare type CommonOptionsForBuildAndServe = CommonOptions & {
    devtool?: string | boolean;
    entry?: string[];
    mode?: string;
    outputPath?: string;
    watch?: boolean;
};

declare type ConfigLoader = 'auto' | 'jiti' | 'native';

export { Configuration }

/**
 * This function helps you to autocomplete configuration types.
 * It accepts a Rspack config object, or a function that returns a config.
 */
export declare function defineConfig(config: RspackOptions): RspackOptions;

export declare function defineConfig(config: MultiRspackOptions): MultiRspackOptions;

export declare function defineConfig(config: RspackConfigFn): RspackConfigFn;

export declare function defineConfig(config: RspackConfigAsyncFn): RspackConfigAsyncFn;

export declare function defineConfig(config: RspackConfigExport): RspackConfigExport;

export declare function definePlugin(plugin: RspackPluginFunction): RspackPluginFunction;

export declare function definePlugin(plugin: RspackPluginInstance): RspackPluginInstance;

declare class GlobalCommand extends Command {
    constructor(cli: CAC);
}

declare type HelpCallback = (sections: HelpSection[]) => void | HelpSection[];

declare interface HelpSection {
    title?: string;
    body: string;
}

export declare type LogHandler = (value: any) => void;

declare class Option_2 {
    rawName: string;
    description: string;
    /** Option name */
    name: string;
    /** Option name and aliases */
    names: string[];
    isBoolean?: boolean;
    required?: boolean;
    config: OptionConfig;
    negated: boolean;
    constructor(rawName: string, description: string, config?: OptionConfig);
}

declare interface OptionConfig {
    default?: any;
    type?: any[];
}

declare interface ParsedArgv {
    args: ReadonlyArray<string>;
    options: {
        [k: string]: any;
    };
}

export declare class RspackCLI {
    colors: RspackCLIColors;
    program: CAC;
    _actionPromise: Promise<void> | undefined;
    constructor();
    /**
     * Wraps an async action handler so its promise is captured and can be
     * awaited in `run()`. CAC's `parse()` does not await async actions,
     * so without this wrapper, rejections become unhandled.
     */
    wrapAction<T extends (...args: any[]) => Promise<void>>(fn: T): T;
    buildCompilerConfig(options: CommonOptionsForBuildAndServe, rspackCommand: Command_2): Promise<RspackOptions | MultiRspackOptions>;
    createCompiler(config: RspackOptions | MultiRspackOptions, callback?: (e: Error | null, res?: Stats | MultiStats) => void): Compiler | MultiCompiler | null;
    private createColors;
    getLogger(): RspackCLILogger;
    run(argv: string[]): Promise<void>;
    private registerCommands;
    private buildConfig;
    loadConfig(options: CommonOptions): Promise<{
        config: RspackOptions | MultiRspackOptions;
        pathMap: WeakMap<RspackOptions, string[]>;
    }>;
    private filterConfig;
    isMultipleCompiler(compiler: Compiler | MultiCompiler): compiler is MultiCompiler;
    isWatch(compiler: Compiler | MultiCompiler): boolean;
}

export declare interface RspackCLIColors {
    isColorSupported: boolean;
    red(text: string): string;
    yellow(text: string): string;
    cyan(text: string): string;
    green(text: string): string;
}

export declare interface RspackCLILogger {
    error: LogHandler;
    warn: LogHandler;
    info: LogHandler;
    success: LogHandler;
    log: LogHandler;
    raw: LogHandler;
}

export declare interface RspackCommand {
    apply(cli: RspackCLI): void | Promise<void>;
}

declare type RspackConfigAsyncFn = (env: Record<string, any>, argv: Record<string, any>) => Promise<RspackOptions | MultiRspackOptions>;

declare type RspackConfigExport = RspackOptions | MultiRspackOptions | RspackConfigFn | RspackConfigAsyncFn;

declare type RspackConfigFn = (env: Record<string, any>, argv: Record<string, any>) => RspackOptions | MultiRspackOptions;

export { }
