import { Command } from 'commander';

/**
 * 설정 객체의 유형을 설명하는 타입입니다.
 *
 * @category Types
 *
 * @typeParam Config - 설정 객체의 타입입니다.
 */
type ConfigType<Config> = {
    [key in keyof Config]?: {
        /**
         * 설정 객체의 키 이름입니다.
         */
        name: key;
        /**
         * 설정 객체의 키에 대한 별칭입니다.
         */
        alias?: string;
        /**
         * 설정 객체의 값의 유형을 설명합니다.
         */
        type?: NonNullable<Config[key]> extends string ? 'string' : NonNullable<Config[key]> extends boolean ? 'boolean' : NonNullable<Config[key]> extends number ? 'number' : NonNullable<Config[key]> extends string[] ? 'string[]' : NonNullable<Config[key]> extends boolean[] ? 'boolean[]' : NonNullable<Config[key]> extends number[] ? 'number[]' : NonNullable<Config[key]> extends any[][] ? 'array[]' : NonNullable<Config[key]> extends Record<any, any>[] ? 'object[]' : NonNullable<Config[key]> extends Record<any, any> ? 'object' : 'any';
        /**
         * 설정 객체의 키에 대한 설명입니다.
         */
        description?: string;
    };
};
/**
 * 사용자 정의 명령어를 나타내는 인터페이스입니다.
 *
 * @category Types
 *
 * @typeParam Config - 명령어의 구성을 나타내는 설정 객체의 타입입니다. 기본값은 `any`입니다.
 * @typeParam Name - 명령어의 이름의 타입입니다. 기본값은 `string`입니다.
 */
interface MyCommand<Config = any, Name extends string = string> {
    /**
     * 명령어의 이름입니다.
     */
    name: Name;
    /**
     * 명령어의 설명입니다.
     */
    description: string;
    /**
     * 명령어의 기본 구성입니다.
     */
    default: Partial<Config>;
    /**
     * 명령어를 실행하는 함수입니다.
     *
     * @param config - 명령어의 구성을 나타내는 설정 객체입니다.
     */
    run: (config: Config) => void;
    /**
     * 명령어의 CLI 옵션 목록입니다.
     */
    cliOptions?: ConfigType<Config>[keyof Config][];
}

/**
 * 루트 구성을 정의하는 타입입니다.
 *
 * @category Types
 *
 * @typeParam P - 플러그인 명령어 배열을 포함하는 객체의 타입입니다. 기본값은 `{ plugins: MyCommand[] }` 입니다.
 *
 * @typeParam P['plugins'] - 플러그인 명령어 배열의 타입입니다.
 *
 */
type RootConfig<P extends {
    plugins: MyCommand[];
} = {
    plugins: MyCommand[];
}> = {
    basePath?: string;
    plugins?: MyCommand[];
} & {
    [key in P['plugins'][number]['name']]?: Extract<P['plugins'][number], {
        name: key;
    }>['default'];
};

declare const registry: {
    (program: Command, config: RootConfig, command: MyCommand): void;
    (program: Command, config: RootConfig): (command: MyCommand) => void;
    (program: Command): (config: RootConfig, command: MyCommand) => void;
};

/**
 * 명령어를 정의하는 함수입니다.
 *
 * @category Utils
 *
 * @typeParam Name - 명령어의 이름 타입입니다.
 * @typeParam Config - 명령어의 구성 타입입니다.
 *
 * @param config - 명령어의 설정입니다.
 * @returns 정의된 명령어 설정을 반환합니다.
 */
declare const defineCommand: <Name extends string, Config extends Record<string, any>>(config: MyCommand<Config, Name>) => MyCommand<Config, Name>;

/**
 * 똑똑한개발자의 플러그인을 사용할 수 있는 **CLI TOOL**입니다.
 * `gen:api`, `gen:theme`, `gen:route`, `gen:sitemap` 등 다양한 플러그인을 지원하며, 사용자가 개발한 스크립트를 플러그인으로 등록할 수 있습니다.
 *
 * @packageDocumentation
 */
declare const cli: () => Promise<void>;

export { type ConfigType, type MyCommand, type RootConfig, cli, defineCommand, registry };
