import { Output, Group, ResolveNameParams, PluginFactoryOptions } from '@kubb/core';
import { Oas, contentType, SchemaObject } from '@kubb/oas';
import { Exclude, Include, Override, Schema, Generator, ResolvePathOptions } from '@kubb/plugin-oas';

type Options = {
    /**
     * Specify the export location for the files and define the behavior of the output
     * @default { path: 'handlers', barrelType: 'named' }
     */
    output?: Output<Oas>;
    /**
     * Define which contentType should be used.
     * By default, the first JSON valid mediaType will be used
     */
    contentType?: contentType;
    /**
     * Group the Faker mocks based on the provided name.
     */
    group?: Group;
    /**
     * Array containing exclude parameters to exclude/skip tags/operations/methods/paths.
     */
    exclude?: Array<Exclude>;
    /**
     * Array containing include parameters to include tags/operations/methods/paths.
     */
    include?: Array<Include>;
    /**
     * Array containing override parameters to override `options` based on tags/operations/methods/paths.
     */
    override?: Array<Override<ResolvedOptions>>;
    /**
     * Choose to use `date` or `datetime` as JavaScript `Date` instead of `string`.
     * @default 'string'
     */
    dateType?: 'string' | 'date';
    /**
     * Which parser should be used when dateType is set to 'string'.
     * - Schema with format 'date' will use ISO date format (YYYY-MM-DD)
     *   - `'dayjs'` will use `dayjs(faker.date.anytime()).format("YYYY-MM-DD")`.
     *   - `undefined` will use `faker.date.anytime().toString()`
     * - Schema with format 'time' will use ISO time format (HH:mm:ss[.SSSSSS])
     *   - `'dayjs'` will use `dayjs(faker.date.anytime()).format("HH:mm:ss")`.
     *   - `undefined` will use `faker.date.anytime().toString()`
     * * @default 'faker'
     */
    dateParser?: 'faker' | 'dayjs' | 'moment' | (string & {});
    /**
     * Which type to use when the Swagger/OpenAPI file is not providing more information
     * @default 'any'
     */
    unknownType?: 'any' | 'unknown' | 'void';
    /**
     * Choose which generator to use when using Regexp.
     *
     * `'faker'` will use `faker.helpers.fromRegExp(new RegExp(/test/))`
     * `'randexp'` will use `new RandExp(/test/).gen()`
     * @default 'faker'
     */
    regexGenerator?: 'faker' | 'randexp';
    mapper?: Record<string, string>;
    /**
     * The use of Seed is intended to allow for consistent values in a test.
     */
    seed?: number | number[];
    transformers?: {
        /**
         * Customize the names based on the type that is provided by the plugin.
         */
        name?: (name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string;
        /**
         * Receive schema and baseName(propertName) and return FakerMeta array
         * TODO TODO add docs
         * @beta
         */
        schema?: (props: {
            schema?: SchemaObject;
            name?: string;
            parentName?: string;
        }, defaultSchemas: Schema[]) => Schema[] | undefined;
    };
    /**
     * Define some generators next to the faker generators
     */
    generators?: Array<Generator<PluginFaker>>;
};
type ResolvedOptions = {
    output: Output<Oas>;
    group: Options['group'];
    override: NonNullable<Options['override']>;
    dateType: NonNullable<Options['dateType']>;
    dateParser: NonNullable<Options['dateParser']>;
    unknownType: NonNullable<Options['unknownType']>;
    transformers: NonNullable<Options['transformers']>;
    seed: NonNullable<Options['seed']> | undefined;
    mapper: NonNullable<Options['mapper']>;
    regexGenerator: NonNullable<Options['regexGenerator']>;
};
type PluginFaker = PluginFactoryOptions<'plugin-faker', Options, ResolvedOptions, never, ResolvePathOptions>;

export type { Options as O, PluginFaker as P };
