import { Db } from 'mongodb';

type ObjectType<T> = {
    new (): T;
};
type Dictionary = {
    [index: string]: any;
};

type Query = {
    [index: string]: any;
};
declare class QueryBuilder<T extends BaseModel> {
    private readonly ctor;
    private query;
    private queryLimit?;
    private queryOffset?;
    private queryOrder?;
    constructor(ctor: ObjectType<T>);
    aggregate(stages: Record<string, unknown>[]): Promise<unknown>;
    average<K extends keyof T>(key: K): Promise<number>;
    count(): Promise<number>;
    create(attributes: Record<string, any>): Promise<string>;
    delete(): Promise<number>;
    find(id: string): Promise<T | null>;
    findOne(query: Query): Promise<T | null>;
    first(): Promise<T | null>;
    get(): Promise<T[]>;
    limit(length: number): QueryBuilder<T>;
    max<K extends keyof T>(key: K): Promise<number>;
    min<K extends keyof T>(key: K): Promise<number>;
    orderBy(key: string, order?: 'asc' | 'desc'): QueryBuilder<T>;
    percentile<K extends keyof T>(key: K, n: number): Promise<number>;
    pluck<K extends keyof T>(key: K): Promise<T[K][]>;
    save(attributes: Dictionary): Promise<string>;
    skip(length: number): QueryBuilder<T>;
    sum<K extends keyof T>(key: K): Promise<number>;
    where(query: Query): QueryBuilder<T>;
    where(key: string, value: any): QueryBuilder<T>;
    whereIn(fieldName: string, values: any[]): QueryBuilder<T>;
    private createInstance;
    private execute;
    private useCollection;
}

declare class BaseModel {
    createdAt: number;
    id: string;
    updatedAt: number | null;
    static all<T extends BaseModel>(this: ObjectType<T>): Promise<T[]>;
    static create<T extends BaseModel>(this: ObjectType<T>, attributes: Partial<T>): Promise<T>;
    static find<T extends BaseModel>(this: ObjectType<T>, id: string): Promise<T | null>;
    static findBy<T extends BaseModel>(this: ObjectType<T>, key: string, value: any): Promise<T | null>;
    static limit<T extends BaseModel>(this: ObjectType<T>, length: number): QueryBuilder<T>;
    static orderBy<T extends BaseModel>(this: ObjectType<T>, key: string, order?: 'asc' | 'desc'): QueryBuilder<T>;
    static pluck<T extends BaseModel, K extends keyof T>(this: ObjectType<T>, key: K): Promise<T[K][]>;
    static skip<T extends BaseModel>(this: ObjectType<T>, length: number): QueryBuilder<T>;
    static where<T extends BaseModel>(this: ObjectType<T>, key: string, value: any): QueryBuilder<T>;
    static whereIn<T extends BaseModel>(this: ObjectType<T>, fieldName: string, values: any[]): QueryBuilder<T>;
    delete(): Promise<number>;
    hasMany<T extends BaseModel>(ctor: ObjectType<T>, foreignKey?: string, localKey?: string): QueryBuilder<T>;
    save(): Promise<void>;
}

declare class ConnectionHandler {
    private client?;
    closeConnections(): Promise<void>;
    getConnection(): Promise<Db>;
    private createClient;
    private getDatabase;
}
declare const connectionHandler: ConnectionHandler;

export { BaseModel, QueryBuilder, connectionHandler };
