/// <reference types="mongoose/types/aggregate" />
/// <reference types="mongoose/types/callback" />
/// <reference types="mongoose/types/collection" />
/// <reference types="mongoose/types/connection" />
/// <reference types="mongoose/types/cursor" />
/// <reference types="mongoose/types/document" />
/// <reference types="mongoose/types/error" />
/// <reference types="mongoose/types/expressions" />
/// <reference types="mongoose/types/helpers" />
/// <reference types="mongoose/types/middlewares" />
/// <reference types="mongoose/types/indexes" />
/// <reference types="mongoose/types/models" />
/// <reference types="mongoose/types/mongooseoptions" />
/// <reference types="mongoose/types/pipelinestage" />
/// <reference types="mongoose/types/populate" />
/// <reference types="mongoose/types/query" />
/// <reference types="mongoose/types/schemaoptions" />
/// <reference types="mongoose/types/schematypes" />
/// <reference types="mongoose/types/session" />
/// <reference types="mongoose/types/types" />
/// <reference types="mongoose/types/utility" />
/// <reference types="mongoose/types/validation" />
/// <reference types="mongoose/types/virtuals" />
/// <reference types="mongoose/types/inferschematype" />
import { Model, Schema } from 'mongoose';
import { CoreFixture, FieldPath, FixtureOptions, Value } from '@mocking-bird/core';
/**
 * ### Overview
 *
 * MongooseFixture class extending abstract CoreFixture class for generating mock data based on Mongoose models
 * or schemas.
 *
 * @see CoreFixture
 *
 * @typeParam T The type of the document corresponding to the Mongoose model or schema.
 *
 * @example
 * const Model = mongoose.model<IDocumentType>('ModelName', schema);
 * const Schema = new mongoose.Schema({ name: String, age: Number });
 *
 * const modelFixture = new MongooseFixture(Model);
 * const schemaFixture = new MongooseFixture(Schema);
 *
 * const data = modelFixture.generate();
 * const multiple = schemaFixture.bulkGenerate(10);
 */
export declare class MongooseFixture<T> extends CoreFixture<T> {
    private static readonly globalOptions;
    private static readonly MONGOOSE_SPECIAL_CHARS_REGEX;
    private static readonly NESTED_SCHEMA_INSTANCE;
    private static readonly ARRAY_SCHEMA_INSTANCE;
    private static readonly MAP_SCHEMA_INSTANCE;
    private static readonly VERSION_KEY;
    private readonly schema;
    private readonly mongooseValidator;
    /**
     * Constructs a MongooseFixture instance.
     *
     * @param target The Mongoose model or schema to generate fixtures for. If a model is provided, the schema is
     * extracted from it. If a schema is provided, it is used directly.
     */
    constructor(target: Model<T> | Schema<T>);
    /**
     * Sets global options for the fixture generation.
     *
     * @param options Fixture options to be set globally. If an option is provided per function call, options
     * provided via the parameter will override the global options.
     */
    static setGlobalOptions(options: FixtureOptions): void;
    /**
     * Generates an array of mock data based on the schema.
     *
     * @inheritDoc
     * @override
     *
     * @typeParam T The type of the document corresponding to the Mongoose model or schema.
     *
     * @throws {Error} same as {@link MongooseFixture#generate}
     *
     * @public
     */
    bulkGenerate(size: number, overrideValues?: Record<FieldPath, Value>, options?: FixtureOptions): T[];
    /**
     * Generates a single mock data based on the schema.
     *
     * @inheritDoc
     * @override
     *
     * @typeParam T The type of the document corresponding to the Mongoose model or schema.
     *
     * @throws {Error}
     * For the following reasons:
     *
     * - If multiple override values are found for the same path. For example, { 'address.*.buildingNo': 42,
     * 'address.street.buildingNo': 43 }.
     * - If override value breaks the schema rule.
     * - If a required field is excluded.
     * - If a custom rule has conflict with the schema rule.
     * - If the value generated does not match the custom rule or the schema rule.
     *
     * @public
     */
    generate(overrideValues?: Record<FieldPath, Value>, options?: FixtureOptions): T;
    /**
     * Recursively generates values for nested schema.
     * First, it iterates through each field in the schema and generates a value for each field.
     * If a field is a nested schema, it will recursively generate values for the nested schema.
     * During each iteration, it builds a sub path, e.g., 'address.street', 'address.street.city', etc.
     *
     * @example
     * const schema = new Schema({
     *   name: String,
     *   address: {
     *     street: String,
     *     city: String,
     *     country: {
     *      name: String,
     *      code: String,
     *     }
     *   },
     *   phone: String,
     * });
     *
     * For such a nested schema above, data will be generated for each child field in the schema.
     *
     * @param schemaNode The current level of the schema being processed.
     * @param rootPath The root path for the current schema node. If undefined, the current schema node is the root.
     * @param overrideValues Values to override in the schema.
     * @param options Fixture generation options.
     *
     * @returns The generated mock data for the current schema node.
     *
     * @private
     */
    private recursivelyGenerateValue;
    /**
     * Generates a value based on the schema type.
     *
     * We check if a field is nested by checking if it has a `schema` property.
     * If a field has basic types such as String, Number, etc., it will not have a schema property.
     * Whereas, if a field is an array or an embedded schema, it will have a schema property and will be recursively
     * processed.
     * Map types are also supported and processed in a special way, as they can be little more complex.
     *
     * @param path The path to the field.
     * @param schemaType The schema type of the field.
     * @param overrideValues Values to override in the schema.
     * @param options Fixture generation options.
     *
     * @returns A mock value for the field or `undefined` if the field is either excluded or explicitly set to
     * `undefined` in the override values.
     *
     * @private
     */
    private generateValueForSchemaType;
    /**
     * Generates a value for a nested schema.
     * Nested schema is a schema that either has an embedded schema or an array schema.
     * Values are generated recursively.
     *
     * @param path The path to the field.
     * @param schemaType The mongoose schema type of the field.
     * @param overrideValues Values to override in the schema.
     * @param options Fixture generation options.
     *
     * @returns A mock value for the field in the nested schema; `undefined` if the schema type is not a nested schema.
     *
     * @private
     */
    private generateValueForNestedSchema;
    /**
     * Generates a value for an array schema.
     * The process is similar to generating a value for a nested schema, except that it returns an array of values.
     * If a size is provided in the `rule`, the array will be generated with the specified size.
     *
     * @param path The path to the field.
     * @param schemaType The mongoose schema type of the field.
     * @param overrideValues Values to override in the schema.
     * @param options Fixture generation options.
     *
     * @returns An array of mock values
     *
     * @private
     */
    private generateValueForSchemaArray;
    /**
     * Generates a value for a map schema.
     * The types used in the map is separated into three main categories: array, schema and basic types.
     *
     * There are four special cases for processing a map:
     * 1. A map is of an array of schema -> { type: Map, of: [new Schema({ name: String, age: Number })] }
     * 2. A map is of an array of basic types -> { type: Map, of: [String] }
     * 3. A map is of a schema type -> { type: Map, of: new Schema({ name: String, age: Number }) }
     * 4. A map is of a basic type -> { type: Map, of: String }
     *
     * @param path The path to the field.
     * @param schemaType The mongoose schema type of the field.
     * @param overrideValues Values to override in the schema.
     * @param options Fixture generation options.
     *
     * @returns A key-value pair of mock values. Returns `undefined` if the map type is not defined.
     *
     * @private
     */
    private generateValueForMapType;
    /**
     * Generates a value for an array map type.
     *
     * @example
     * {
     *  basicArray: [1, 2, 3],
     *  schemaArray: [{ name: 'John', age: 30 }, { name: 'Jane', age: 25 }],
     * }
     *
     * @param mapDefinition Either based on schema or basic type. If based on basic type, we access the `name` property.
     * @param path The path to the field.
     * @param overrideValues Values to override in the schema.
     * @param options Fixture generation options.
     *
     * @returns An array of mock values, either an object of values or primitive values.
     *
     * @private
     */
    private generateArrayMapValues;
    /**
     * Generates a map value based on the basic type -> { type: Map, of: String }
     *
     * @param basicFieldType The basic type of the map value. String, Number, etc.
     *
     * @returns A mock value for the map value.
     *
     * @private
     */
    private generateBasicMapValue;
    /**
     * Generates a random map value which will be used for the map key.
     *
     * @returns A random map key.
     *
     * @private
     */
    private generateMapKey;
    /**
     * Generates a value for a field based on the schema type.
     * If a value is provided in the `overrideValues`, it will be used instead of generating a new value.
     * If a `rule` is provided, a value will be generated based on it.
     *
     * @param path The path to the field.
     * @param schemaType The mongoose schema type of the field.
     * @param overrideValues Values to override in the schema.
     * @param options Fixture generation options.
     *
     * @returns A mock value for the field or a value in the `overrideValues` if it exists.
     *
     * @throws {Error} If the value generated does not match the custom rule or the schema rule.
     *
     * @private
     */
    private generateValue;
    /**
     * Generates a mock value for a field based on the schema rule and the custom rule.
     *
     * @param path The path to the field.
     * @param schemaType The mongoose schema type of the field.
     * @param rule The custom rule to apply for the field.
     * @param isAccurate If set to `true`, the value will be generated based on the field name. {@link FakerFinder#search}
     *
     * @returns A mock value for the field or `undefined`.
     *
     * @throws {Error} If the schema rules and custom rules conflict each other
     *
     * @private
     */
    private generateMockValue;
    /**
     * Pre-generation routine to validate and extract paths and to set global options.
     *
     * @param overrideValues Values to override in the schema.in the schema
     * @param options Fixture generation options.
     *
     * @returns Merged fixture options.
     *
     * @throws {Error} If paths defined both in the `overrideValues` and the `options` are invalid.
     *
     * @private
     */
    private preGeneration;
    /**
     * Checks if a given field (path) is excluded from the fixture generation.
     *
     * @param path The path to the field.
     * @param schemaType The mongoose schema type of the field.
     * @param options Fixture generation options.
     *
     * @returns `true` if the field is excluded, `false` otherwise.
     *
     * @throws {Error} If a required field is excluded.
     *
     * @private
     */
    private isExcluded;
    /**
     * Checks if the path contains special characters.
     *
     * @param path The path to the field.
     *
     * @returns `true` if the path contains special characters, `false` otherwise.
     *
     * @private
     */
    private containsSpecialChars;
    /**
     * Checks if the target is a Mongoose model.
     * Model instances have a `schema` property, by which we can distinguish between a model and a schema.
     *
     * @param target Either a Mongoose model or a schema.
     *
     * @returns `true` if the target is a Mongoose model, `false` otherwise.
     *
     * @private
     */
    private isModel;
}
