/**
 * @athenna/database
 *
 * (c) João Lenon <lenon@athenna.io>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
import { Collection, type PaginationOptions } from '@athenna/common';
import type { Direction, Operations, ModelColumns, ModelRelations } from '#src/types';
import type { BaseModel } from '#src/models/BaseModel';
import type { Driver } from '#src/database/drivers/Driver';
import { QueryBuilder } from '#src/database/builders/QueryBuilder';
import type { Transaction } from '#src/database/transactions/Transaction';
export declare class ModelQueryBuilder<M extends BaseModel = any, D extends Driver = any> extends QueryBuilder<M, D> {
    private Model;
    private schema;
    private generator;
    private primaryKeyName;
    private primaryKeyProperty;
    private isToSetAttributes;
    private isToValidateUnique;
    private isToValidateNullable;
    private selectColumns;
    private DELETED_AT_PROP;
    private DELETED_AT_NAME;
    private isSoftDelete;
    private hasCustomSelect;
    constructor(model: any, driver: D);
    /**
     * Define a transaction to be used by the model query builder.
     */
    setTransaction(trx: Transaction): this;
    /**
     * Set a different driver to the model query builder.
     */
    setDriver(driver: Driver, tableName?: string): this;
    /**
     * Calculate the average of a given column.
     */
    avg(column: ModelColumns<M>): Promise<number>;
    /**
     * Calculate the average of a given column.
     */
    avgDistinct(column: ModelColumns<M>): Promise<number>;
    /**
     * Get the max number of a given column.
     */
    max(column: ModelColumns<M>): Promise<number>;
    /**
     * Get the min number of a given column.
     */
    min(column: ModelColumns<M>): Promise<number>;
    /**
     * Sum all numbers of a given column.
     */
    sum(column: ModelColumns<M>): Promise<number>;
    /**
     * Sum all numbers of a given column.
     */
    sumDistinct(column: ModelColumns<M>): Promise<number>;
    /**
     * Increment a value of a given column.
     */
    increment(column: ModelColumns<M>): Promise<void>;
    /**
     * Decrement a value of a given column.
     */
    decrement(column: ModelColumns<M>): Promise<void>;
    /**
     * Calculate the average of a given column using distinct.
     */
    count(column?: ModelColumns<M>): Promise<number>;
    /**
     * Calculate the average of a given column using distinct.
     */
    countDistinct(column: ModelColumns<M>): Promise<number>;
    /**
     * Find value in database but returns only the value of
     * selected column directly.
     */
    pluck<K extends Extract<ModelColumns<M>, keyof M>>(column: K): Promise<M[K]>;
    pluck(column: ModelColumns<M>): Promise<any>;
    /**
     * Find many values in database but returns only the
     * values of selected column directly.
     */
    pluckMany<K extends Extract<ModelColumns<M>, keyof M>>(column: K): Promise<M[K][]>;
    pluckMany(column: ModelColumns<M>): Promise<any[]>;
    /**
     * Find a value in database.
     */
    find(): Promise<M>;
    /**
     * Find a value in database or throw exception if undefined.
     */
    findOrFail(): Promise<M>;
    /**
     * Find a value in database or create a new one if it doesn't exist.
     */
    findOrCreate(data?: Partial<M>): Promise<M>;
    /**
     * Return a single data or, if no results are found,
     * execute the given closure.
     */
    findOr<T = M>(closure: () => T | Promise<T>): Promise<T>;
    /**
     * Find a value in database and return as boolean.
     */
    exists(): Promise<boolean>;
    /**
     * Find many values in database.
     */
    findMany(): Promise<M[]>;
    /**
     * Find many values in database and return paginated.
     */
    paginate(page?: PaginationOptions | number, limit?: number, resourceUrl?: string): Promise<import("@athenna/common").PaginatedResponse<any>>;
    /**
     * Find many values in database and return
     * as a collection instance.
     */
    collection(): Promise<Collection<M>>;
    /**
     * Create a value in database.
     */
    create(data?: Partial<M>, cleanPersist?: boolean): Promise<M>;
    /**
     * Create many values in database.
     */
    createMany(data: Partial<M>[], cleanPersist?: boolean): Promise<M[]>;
    /**
     * Create or update a value in database.
     */
    createOrUpdate(data: Partial<M>, cleanPersist?: boolean): Promise<M>;
    /**
     * Update a value in database.
     */
    update(data: Partial<M>, cleanPersist?: boolean): Promise<M | M[]>;
    /**
     * Delete or soft delete a value in database.
     */
    delete(force?: boolean): Promise<void>;
    /**
     * Restore one or multiple soft deleted models.
     */
    restore(data?: Partial<M>): Promise<M | M[]>;
    /**
     * Retrieve only the values that are soft deleted in
     * database.
     */
    onlyTrashed(): this;
    /**
     * Retrieve active and soft deleted values from database.
     */
    withTrashed(): this;
    /**
     * Enable/disable setting the default attributes properties
     * when creating/updating models.
     */
    setAttributes(value: boolean): this;
    /**
     * Enable/disable the `isUnique` property validation of
     * models columns.
     */
    uniqueValidation(value: boolean): this;
    /**
     * Enable/disable the `isNullable` property validation of
     * models columns.
     */
    nullableValidation(value: boolean): this;
    with(relation: string): this;
    with<K extends ModelRelations<M>>(relation: K, closure?: (query: ModelQueryBuilder<Extract<M[K] extends BaseModel[] ? M[K][0] : M[K], BaseModel>, Driver>) => any): this;
    /**
     * Only returns the data if the closure returns a result.
     */
    whereHas<K extends ModelRelations<M>>(relation: K | string, closure?: (query: ModelQueryBuilder<Extract<M[K] extends BaseModel[] ? M[K][0] : M[K], BaseModel>, Driver>) => any): this;
    /**
     * Same as {@link ModelQueryBuilder.whereHas}, but joins the resulting
     * `EXISTS (...)` clause to the surrounding WHERE with `OR` instead of `AND`.
     *
     * Useful inside a grouped `where(qb => ...)` closure to build expressions
     * like `(directCol ILIKE x OR relation.col ILIKE x)` without resorting to
     * raw SQL.
     */
    orWhereHas<K extends ModelRelations<M>>(relation: K | string, closure?: (query: ModelQueryBuilder<Extract<M[K] extends BaseModel[] ? M[K][0] : M[K], BaseModel>, Driver>) => any): this;
    /**
     * Build a grouped OR search across any mix of direct columns and
     * relation columns in a single `WHERE (...)` clause.
     *
     * Each entry in `fields` is either a direct column property (e.g. `name`)
     * or a `relation.column` path (e.g. `profile.bio`). The resulting SQL is a
     * single parenthesized group joined exclusively by `OR`. Passing a falsy
     * `term` short-circuits and the query is left untouched.
     *
     * @example
     * ```ts
     * User.query().search(['name', 'email', 'profile.bio'], 'john')
     * ```
     */
    search(fields: (ModelColumns<M> | ModelRelations<M> | string)[], term: string): this;
    /**
     * Executes the given closure when the first argument is true.
     */
    when(criteria: any, closure: (query: this, criteriaValue: any) => any | Promise<any>): this;
    /**
     * Set the columns that should be selected on query.
     */
    select(...columns: ModelColumns<M>[]): this;
    /**
     * Set the columns that should be selected on query raw.
     */
    selectRaw(sql: string, bindings?: any): this;
    /**
     * Set a group by statement in your query.
     */
    groupBy(...columns: ModelColumns<M>[]): this;
    having(column: ModelColumns<M>): this;
    having(column: ModelColumns<M>, value: any): this;
    having(column: ModelColumns<M>, operation: Operations, value: any): this;
    /**
     * Set a having in statement in your query.
     */
    havingIn(column: ModelColumns<M>, values: any[]): this;
    /**
     * Set a having not in statement in your query.
     */
    havingNotIn(column: ModelColumns<M>, values: any[]): this;
    /**
     * Set a having between statement in your query.
     */
    havingBetween(column: ModelColumns<M>, values: [any, any]): this;
    /**
     * Set a having not between statement in your query.
     */
    havingNotBetween(column: ModelColumns<M>, values: [any, any]): this;
    /**
     * Set a having null statement in your query.
     */
    havingNull(column: ModelColumns<M>): this;
    /**
     * Set a having not null statement in your query.
     */
    havingNotNull(column: ModelColumns<M>): this;
    orHaving(column: ModelColumns<M>): this;
    orHaving(column: ModelColumns<M>, value: any): this;
    orHaving(column: ModelColumns<M>, operation: Operations, value: any): this;
    /**
     * Set a orHaving not in statement in your query.
     */
    orHavingNotIn(column: ModelColumns<M>, values: any[]): this;
    /**
     * Set a orHaving between statement in your query.
     */
    orHavingBetween(column: ModelColumns<M>, values: [any, any]): this;
    /**
     * Set a orHaving not between statement in your query.
     */
    orHavingNotBetween(column: ModelColumns<M>, values: [any, any]): this;
    /**
     * Set a orHaving null statement in your query.
     */
    orHavingNull(column: ModelColumns<M>): this;
    /**
     * Set a orHaving not null statement in your query.
     */
    orHavingNotNull(column: ModelColumns<M>): this;
    where(statement: (query: this) => void): this;
    where(statement: Partial<M>): this;
    where(statement: Record<string, any>): this;
    where(key: ModelColumns<M>, value: any): this;
    where(key: ModelColumns<M>, operation: Operations, value: any): this;
    whereNot(statement: (query: this) => void): this;
    whereNot(statement: Partial<M>): this;
    whereNot(statement: Record<string, any>): this;
    whereNot(key: ModelColumns<M>, value: any): this;
    /**
     * Set a where like statement in your query.
     */
    whereLike(column: ModelColumns<M>, value: any): this;
    /**
     * Set a where ILike statement in your query.
     */
    whereILike(column: ModelColumns<M>, value: any): this;
    /**
     * Set a where in statement in your query.
     */
    whereIn(column: ModelColumns<M>, values: any[]): this;
    /**
     * Set a where not in statement in your query.
     */
    whereNotIn(column: ModelColumns<M>, values: any[]): this;
    /**
     * Set a where between statement in your query.
     */
    whereBetween(column: ModelColumns<M>, values: [any, any]): this;
    /**
     * Set a where not between statement in your query.
     */
    whereNotBetween(column: ModelColumns<M>, values: [any, any]): this;
    /**
     * Set a where null statement in your query.
     */
    whereNull(column: ModelColumns<M>): this;
    /**
     * Set a where not null statement in your query.
     */
    whereNotNull(column: ModelColumns<M>): this;
    whereJson(column: ModelColumns<M>, value: any): this;
    whereJson(column: ModelColumns<M>, operation: Operations, value: any): this;
    orWhere(statement: (query: this) => void): this;
    orWhere(statement: Partial<M>): this;
    orWhere(statement: Record<string, any>): this;
    orWhere(key: ModelColumns<M>, value: any): this;
    orWhere(key: ModelColumns<M>, operation: Operations, value: any): this;
    orWhereNot(statement: (query: this) => void): this;
    orWhereNot(statement: Partial<M>): this;
    orWhereNot(statement: Record<string, any>): this;
    orWhereNot(key: ModelColumns<M>, value: any): this;
    orWhereLike(statement: Partial<M>): this;
    orWhereLike(statement: Record<string, any>): this;
    orWhereLike(key: ModelColumns<M>, value: any): this;
    orWhereILike(statement: Partial<M>): this;
    orWhereILike(statement: Record<string, any>): this;
    orWhereILike(key: ModelColumns<M>, value: any): this;
    /**
     * Set a orWhere in statement in your query.
     */
    orWhereIn(column: ModelColumns<M>, values: any[]): this;
    /**
     * Set a orWhere not in statement in your query.
     */
    orWhereNotIn(column: ModelColumns<M>, values: any[]): this;
    /**
     * Set a orWhere between statement in your query.
     */
    orWhereBetween(column: ModelColumns<M>, values: [any, any]): this;
    /**
     * Set a orWhere not between statement in your query.
     */
    orWhereNotBetween(column: ModelColumns<M>, values: [any, any]): this;
    /**
     * Set a orWhere null statement in your query.
     */
    orWhereNull(column: ModelColumns<M>): this;
    /**
     * Set a orWhere not null statement in your query.
     */
    orWhereNotNull(column: ModelColumns<M>): this;
    orWhereJson(column: ModelColumns<M>, value: any): this;
    orWhereJson(column: ModelColumns<M>, operation: Operations, value: any): this;
    /**
     * Set an order by statement in your query.
     */
    orderBy(column: ModelColumns<M>, direction?: Direction): this;
    /**
     * Order the results easily by the latest date. By default, the result will
     * be ordered by the table's "createdAt" column.
     */
    latest(column?: ModelColumns<M>): this;
    /**
     * Order the results easily by the oldest date. By default, the result will
     * be ordered by the table's "createdAt" column.
     */
    oldest(column?: ModelColumns<M>): this;
    /**
     * Set the internal selected properties and soft delete
     * queries.
     */
    private setInternalQueries;
    /**
     * Reset select state after terminal custom select queries.
     */
    private resetCustomSelect;
    /**
     * Verify that columns with `isNullable` property
     * can be created in database.
     */
    private validateNullable;
    /**
     * Verify that columns with isUnique property
     * can be created in database.
     */
    private validateUnique;
}
