import {
  type CountOptions,
  type DeleteOptions,
  type DriverMethodOptions,
  EntityManagerType,
  type FindOneOptions,
  type FindOptions,
  type IDatabaseDriver,
  type LockOptions,
  type NativeInsertUpdateManyOptions,
  type NativeInsertUpdateOptions,
  type OrderDefinition,
  type StreamOptions,
} from './IDatabaseDriver.js';
import type {
  ConnectionType,
  Constructor,
  Dictionary,
  EntityData,
  EntityDictionary,
  EntityMetadata,
  EntityName,
  EntityProperty,
  FilterQuery,
  PopulateOptions,
  Primary,
} from '../typings.js';
import type { MetadataStorage } from '../metadata/MetadataStorage.js';
import type { Connection, QueryResult, Transaction } from '../connections/Connection.js';
import { type Configuration, type ConnectionOptions } from '../utils/Configuration.js';
import { EntityComparator } from '../utils/EntityComparator.js';
import { type QueryOrder } from '../enums.js';
import type { Platform } from '../platforms/Platform.js';
import type { Collection } from '../entity/Collection.js';
import { EntityManager } from '../EntityManager.js';
import { DriverException } from '../exceptions.js';
import { MikroORM } from '../MikroORM.js';
/** Abstract base class for all database drivers, implementing common driver logic. */
export declare abstract class DatabaseDriver<C extends Connection> implements IDatabaseDriver<C> {
  readonly config: Configuration;
  protected readonly dependencies: string[];
  [EntityManagerType]: EntityManager<this>;
  protected readonly connection: C;
  protected readonly replicas: C[];
  protected readonly platform: Platform;
  protected comparator: EntityComparator;
  protected metadata: MetadataStorage;
  protected constructor(config: Configuration, dependencies: string[]);
  abstract find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(
    entityName: EntityName<T>,
    where: FilterQuery<T>,
    options?: FindOptions<T, P, F, E>,
  ): Promise<EntityData<T>[]>;
  abstract findOne<T extends object, P extends string = never, F extends string = '*', E extends string = never>(
    entityName: EntityName<T>,
    where: FilterQuery<T>,
    options?: FindOneOptions<T, P, F, E>,
  ): Promise<EntityData<T> | null>;
  abstract nativeInsert<T extends object>(
    entityName: EntityName<T>,
    data: EntityDictionary<T>,
    options?: NativeInsertUpdateOptions<T>,
  ): Promise<QueryResult<T>>;
  abstract nativeInsertMany<T extends object>(
    entityName: EntityName<T>,
    data: EntityDictionary<T>[],
    options?: NativeInsertUpdateManyOptions<T>,
    transform?: (sql: string) => string,
  ): Promise<QueryResult<T>>;
  abstract nativeUpdate<T extends object>(
    entityName: EntityName<T>,
    where: FilterQuery<T>,
    data: EntityDictionary<T>,
    options?: NativeInsertUpdateOptions<T>,
  ): Promise<QueryResult<T>>;
  nativeUpdateMany<T extends object>(
    entityName: EntityName<T>,
    where: FilterQuery<T>[],
    data: EntityDictionary<T>[],
    options?: NativeInsertUpdateManyOptions<T>,
  ): Promise<QueryResult<T>>;
  abstract nativeDelete<T extends object>(
    entityName: EntityName<T>,
    where: FilterQuery<T>,
    options?: DeleteOptions<T>,
  ): Promise<QueryResult<T>>;
  abstract count<T extends object, P extends string = never>(
    entityName: EntityName<T>,
    where: FilterQuery<T>,
    options?: CountOptions<T, P>,
  ): Promise<number>;
  /** Creates a new EntityManager instance bound to this driver. */
  createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
  findVirtual<T extends object>(
    entityName: EntityName<T>,
    where: FilterQuery<T>,
    options: FindOptions<T, any, any, any>,
  ): Promise<EntityData<T>[]>;
  countVirtual<T extends object>(
    entityName: EntityName<T>,
    where: FilterQuery<T>,
    options: CountOptions<T, any>,
  ): Promise<number>;
  aggregate(entityName: EntityName, pipeline: any[]): Promise<any[]>;
  loadFromPivotTable<T extends object, O extends object>(
    prop: EntityProperty,
    owners: Primary<O>[][],
    where?: FilterQuery<any>,
    orderBy?: OrderDefinition<T>,
    ctx?: Transaction,
    options?: FindOptions<T, any, any, any>,
    pivotJoin?: boolean,
  ): Promise<Dictionary<T[]>>;
  syncCollections<T extends object, O extends object>(
    collections: Iterable<Collection<T, O>>,
    options?: DriverMethodOptions,
  ): Promise<void>;
  /** Maps raw database result to entity data, converting column names to property names. */
  mapResult<T extends object>(
    result: EntityDictionary<T>,
    meta?: EntityMetadata<T>,
    populate?: PopulateOptions<T>[],
  ): EntityData<T> | null;
  /** Opens the primary connection and all read replicas. */
  connect(options?: { skipOnConnect?: boolean }): Promise<C>;
  /** Closes all connections and re-establishes them. */
  reconnect(options?: { skipOnConnect?: boolean }): Promise<C>;
  /** Returns the write connection or a random read replica. */
  getConnection(type?: ConnectionType): C;
  /** Closes the primary connection and all read replicas. */
  close(force?: boolean): Promise<void>;
  /** Returns the database platform abstraction for this driver. */
  getPlatform(): Platform;
  /** Sets the metadata storage and initializes the comparator for all connections. */
  setMetadata(metadata: MetadataStorage): void;
  /** Returns the metadata storage used by this driver. */
  getMetadata(): MetadataStorage;
  /** Returns the names of native database dependencies required by this driver. */
  getDependencies(): string[];
  protected isPopulated<T extends object>(
    meta: EntityMetadata<T>,
    prop: EntityProperty<T>,
    hint: PopulateOptions<T>,
    name?: string,
  ): boolean;
  protected processCursorOptions<T extends object, P extends string>(
    meta: EntityMetadata<T>,
    options: FindOptions<T, P, any, any>,
    orderBy: OrderDefinition<T>,
  ): {
    orderBy: OrderDefinition<T>[];
    where: FilterQuery<T>;
  };
  protected createCursorCondition<T extends object>(
    definition: (readonly [keyof T & string, QueryOrder])[],
    offsets: Dictionary[],
    inverse: boolean,
    meta: EntityMetadata<T>,
  ): FilterQuery<T>;
  /** @internal */
  mapDataToFieldNames(
    data: Dictionary,
    stringifyJsonArrays: boolean,
    properties?: Record<string, EntityProperty>,
    convertCustomTypes?: boolean,
    object?: boolean,
  ): Dictionary;
  protected inlineEmbeddables<T extends object>(meta: EntityMetadata<T>, data: T, where?: boolean): void;
  protected getPrimaryKeyFields<T>(meta: EntityMetadata<T>): string[];
  protected createReplicas(cb: (c: ConnectionOptions) => C): C[];
  /** Acquires a pessimistic lock on the given entity. */
  lockPessimistic<T extends object>(entity: T, options: LockOptions): Promise<void>;
  abstract stream<T extends object>(
    entityName: EntityName<T>,
    where: FilterQuery<T>,
    options: StreamOptions<T>,
  ): AsyncIterableIterator<T>;
  /**
   * @inheritDoc
   */
  convertException(exception: Error): DriverException;
  protected rethrow<T>(promise: Promise<T>): Promise<T>;
  /**
   * @internal
   */
  getTableName<T>(meta: EntityMetadata<T>, options: NativeInsertUpdateManyOptions<T>, quote?: boolean): string;
  /**
   * @internal
   */
  getSchemaName(
    meta?: EntityMetadata,
    options?: {
      schema?: string;
      parentSchema?: string;
    },
  ): string | undefined;
  /** @internal */
  getORMClass(): Constructor<MikroORM>;
}
