import { ComplexType } from '@opra/common';
import { ExecutionContext, ServiceBase } from '@opra/core';
import { SqlElement } from '@sqb/builder';
import { EntityMetadata, Repository } from '@sqb/connect';
import type { Nullish, PartialDTO, PatchDTO, RequiredSome, StrictOmit, Type } from 'ts-gems';
import { vg } from 'valgen';
import { SQBAdapter } from './sqb-adapter.js';
import { SqbServiceBase } from './sqb-service-base.js';
/**
 * Namespace containing types and options for SqbEntityService.
 */
export declare namespace SqbEntityService {
    /**
     * Configuration options for SqbEntityService.
     */
    interface Options extends SqbServiceBase.Options {
        /**
         * The name of the resource managed by this service.
         */
        resourceName?: SqbEntityService<any>['resourceName'];
        /**
         * Optional error handler.
         */
        onError?: SqbEntityService<any>['onError'];
        /**
         * Optional common filter applied to all read/write operations.
         */
        commonFilter?: SqbEntityService<any>['commonFilter'];
        /**
         * Optional interceptor for the service operations.
         */
        interceptor?: SqbEntityService<any>['interceptor'];
        /**
         * Optional scope for the service.
         */
        scope?: SqbEntityService<any>['scope'];
    }
    /**
     * Represents the CRUD operation types.
     */
    type CrudOp = 'create' | 'read' | 'update' | 'delete';
    /**
     * Information about the command being executed.
     */
    interface CommandInfo {
        crud: SqbEntityService.CrudOp;
        method: string;
        byId: boolean;
        documentId?: SQBAdapter.IdOrIds;
        input?: Record<string, any>;
        options?: Record<string, any>;
    }
    /**
     * Type definition for a common filter.
     */
    type CommonFilter = SQBAdapter.FilterInput | ((args: SqbEntityService.CommandInfo, _this: SqbEntityService<any>) => SQBAdapter.FilterInput | Promise<SQBAdapter.FilterInput> | undefined);
    interface CreateOptions extends Repository.CreateOptions {
    }
    interface CountOptions extends StrictOmit<Repository.CountOptions, 'filter'> {
        filter?: Repository.CountOptions['filter'] | string;
    }
    interface DeleteOptions extends StrictOmit<Repository.DeleteOptions, 'filter'> {
        filter?: Repository.DeleteOptions['filter'] | string;
    }
    interface DeleteManyOptions extends StrictOmit<Repository.DeleteManyOptions, 'filter'> {
        filter?: Repository.DeleteManyOptions['filter'] | string;
    }
    interface ExistsOptions extends StrictOmit<Repository.ExistsOptions, 'filter'> {
        filter?: Repository.ExistsOptions['filter'] | string;
    }
    interface FindOneOptions extends StrictOmit<Repository.FindOneOptions, 'filter' | 'offset'> {
        filter?: Repository.FindOneOptions['filter'] | string;
        skip?: number;
    }
    interface FindManyOptions extends StrictOmit<Repository.FindManyOptions, 'filter' | 'offset'> {
        filter?: Repository.FindManyOptions['filter'] | string;
        skip?: number;
    }
    interface UpdateOneOptions extends StrictOmit<Repository.UpdateOptions, 'filter'> {
        filter?: Repository.UpdateOptions['filter'] | string;
    }
    interface UpdateManyOptions extends StrictOmit<Repository.UpdateManyOptions, 'filter'> {
        filter?: Repository.UpdateManyOptions['filter'] | string;
    }
    interface CreateCommand<T> extends StrictOmit<RequiredSome<CommandInfo, 'input'>, 'documentId'> {
        crud: 'create';
        input: PatchDTO<T>;
        options?: CreateOptions;
    }
    interface CountCommand extends StrictOmit<CommandInfo, 'documentId' | 'input'> {
        crud: 'read';
        options?: CountOptions;
    }
    interface DeleteOneCommand extends StrictOmit<CommandInfo, 'input'> {
        crud: 'delete';
        options?: DeleteOptions;
    }
    interface DeleteManyCommand extends StrictOmit<CommandInfo, 'input'> {
        crud: 'delete';
        options?: DeleteManyOptions;
    }
    interface ExistsCommand extends StrictOmit<CommandInfo, 'input'> {
        crud: 'read';
        options?: ExistsOptions;
    }
    interface FindOneCommand extends StrictOmit<CommandInfo, 'input'> {
        crud: 'read';
        options?: FindOneOptions;
    }
    interface FindManyCommand extends StrictOmit<CommandInfo, 'input'> {
        crud: 'read';
        options?: FindManyOptions;
    }
    interface UpdateOneCommand<T> extends CommandInfo {
        crud: 'update';
        input: PatchDTO<T, SqlElement>;
        options?: UpdateOneOptions;
    }
    interface UpdateManyCommand<T> extends CommandInfo {
        crud: 'update';
        input: PatchDTO<T, SqlElement>;
        options?: UpdateManyOptions;
    }
}
export interface SqbEntityService {
    /**
     * Optional interceptor that wraps every command execution.
     *
     * @param next - Calls the next interceptor or the actual command handler.
     * @param command - Metadata describing the current operation.
     * @param _this - Reference to the service instance.
     * @returns The result of the command execution.
     */
    interceptor?(next: () => any, command: SqbEntityService.CommandInfo, _this: any): Promise<any>;
}
/**
 * Base service providing CRUD operations over an SQB entity.
 *
 * @typeParam T - The entity type managed by this service
 */
export declare class SqbEntityService<T extends object = object> extends SqbServiceBase {
    protected _dataTypeScope?: string;
    protected _dataType_: Type | string;
    protected _dataType?: ComplexType;
    protected _dataTypeClass?: Type;
    protected _entityMetadata?: EntityMetadata;
    protected _inputCodecs: Record<string, vg.isObject.Validator<T>>;
    protected _outputCodecs: Record<string, vg.isObject.Validator<T>>;
    /**
     * Comma-delimited scopes used to filter the API document.
     */
    scope?: string;
    /**
     * Override for the resource name exposed in error messages and API metadata.
     * Accepts a static string or a function that returns one.
     */
    resourceName?: string | ((_this: this) => string);
    /**
     * Filter(s) automatically applied to every query for this service.
     * Useful for multi-tenant isolation or other cross-cutting constraints.
     */
    commonFilter?: SqbEntityService.CommonFilter | SqbEntityService.CommonFilter[];
    /**
     * Called whenever a command throws. Useful for logging or transforming errors.
     *
     * @param error - The thrown error.
     * @param command - The service command during which the error was thrown.
     * @param _this - The service instance.
     */
    onError?: (error: unknown, command: SqbEntityService.CommandInfo, _this: any) => void | Promise<void>;
    /**
     * Constructs a new instance.
     *
     * @param dataType - The entity class or its registered name.
     * @param options - Options for the service.
     */
    constructor(dataType: Type<T> | string, options?: SqbEntityService.Options);
    /**
     * Returns the resolved OPRA `ComplexType` for this service's entity.
     *
     * @throws If the data type is not registered as a `ComplexType`.
     */
    get dataType(): ComplexType;
    /**
     * Returns the constructor class of the entity data type.
     *
     * @throws If the data type is not registered as a `ComplexType`.
     */
    get dataTypeClass(): Type;
    /**
     * Returns the SQB `EntityMetadata` for the entity class.
     *
     * @throws If the class is not decorated with `@Entity()`.
     */
    get entityMetadata(): EntityMetadata;
    for<C extends ExecutionContext, P extends Partial<this>>(context: C | ServiceBase, overwriteProperties?: Nullish<P>, overwriteContext?: Partial<C>): this & Required<P>;
    /**
     * Returns the resource name used in error messages and API metadata.
     *
     * @throws If neither `resourceName` nor the data type name is available.
     */
    getResourceName(): string;
    /**
     * Returns the input codec for the given operation (e.g. `'create'`, `'update'`).
     *
     * @param operation - The operation name.
     */
    getInputCodec(operation: string): vg.isObject.Validator<T>;
    /**
     * Returns the output codec for the given operation.
     *
     * @param operation - The operation name.
     */
    getOutputCodec(operation: string): vg.isObject.Validator<T>;
    /**
     * Inserts a new record into the database and returns the created document.
     *
     * @param command - The create command.
     * @returns The created document.
     * @protected
     */
    protected _create(command: SqbEntityService.CreateCommand<T>): Promise<PartialDTO<T>>;
    /**
     * Inserts a new record into the database without returning it.
     *
     * @param command - The create command.
     * @protected
     */
    protected _createOnly(command: SqbEntityService.CreateCommand<T>): Promise<any>;
    /**
     * Returns the count of records matching the command options.
     *
     * @param command - The count command.
     * @protected
     */
    protected _count(command: SqbEntityService.CountCommand): Promise<number>;
    /**
     * Deletes the record identified by `command.documentId`.
     *
     * @param command - The delete command.
     * @returns The number of records deleted.
     * @protected
     */
    protected _delete(command: SqbEntityService.DeleteOneCommand): Promise<number>;
    /**
     * Deletes all records matching the command filter.
     *
     * @param command - The deleteMany command.
     * @returns The number of records deleted.
     * @protected
     */
    protected _deleteMany(command: SqbEntityService.DeleteManyCommand): Promise<number>;
    /**
     * Checks whether the record identified by `command.documentId` exists.
     *
     * @param command - The exists command.
     * @protected
     */
    protected _exists(command: SqbEntityService.ExistsCommand): Promise<boolean>;
    /**
     * Checks whether any record matching the command filter exists.
     *
     * @param command - The existsOne command.
     * @protected
     */
    protected _existsOne(command: SqbEntityService.ExistsCommand): Promise<boolean>;
    /**
     * Finds the record identified by `command.documentId`.
     *
     * @param command - The findById command.
     * @returns The found record, or `undefined` if not found.
     * @protected
     */
    protected _findById(command: SqbEntityService.FindOneCommand): Promise<PartialDTO<T> | undefined>;
    /**
     * Finds the first record matching the command filter.
     *
     * @param command - The findOne command.
     * @returns The found record, or `undefined` if not found.
     * @protected
     */
    protected _findOne(command: SqbEntityService.FindOneCommand): Promise<PartialDTO<T> | undefined>;
    /**
     * Finds all records matching the command filter.
     *
     * @param command - The findMany command.
     * @returns An array of matching records.
     * @protected
     */
    protected _findMany(command: SqbEntityService.FindManyCommand): Promise<PartialDTO<T>[]>;
    /**
     * Updates the record identified by `command.documentId` and returns it.
     *
     * @param command - The update command.
     * @returns The updated record, or `undefined` if not found.
     * @protected
     */
    protected _update(command: SqbEntityService.UpdateOneCommand<T>): Promise<PartialDTO<T> | undefined>;
    /**
     * Updates the record identified by `command.documentId` without returning it.
     *
     * @param command - The updateOnly command.
     * @returns The number of records modified.
     * @protected
     */
    protected _updateOnly(command: SqbEntityService.UpdateOneCommand<T>): Promise<number>;
    /**
     * Updates all records matching the command filter.
     *
     * @param command - The updateMany command.
     * @returns The number of records modified.
     * @protected
     */
    protected _updateMany(command: SqbEntityService.UpdateOneCommand<T>): Promise<number>;
    /**
     * Acquires a connection and performs `Repository.create`.
     *
     * @param input - The document to insert.
     * @param options - Optional settings.
     * @protected
     */
    protected _dbCreate(input: PartialDTO<T>, options?: Repository.CreateOptions): Promise<PartialDTO<T>>;
    /**
     * Acquires a connection and performs `Repository.count`.
     *
     * @param options - Optional settings.
     * @protected
     */
    protected _dbCount(options?: Repository.CountOptions): Promise<number>;
    /**
     * Acquires a connection and performs `Repository.delete`.
     *
     * @param id - The key field value identifying the record.
     * @param options - Optional settings.
     * @protected
     */
    protected _dbDelete(id: SQBAdapter.IdOrIds, options?: Repository.DeleteOptions): Promise<number>;
    /**
     * Acquires a connection and performs `Repository.deleteMany`.
     *
     * @param options - Optional settings.
     * @protected
     */
    protected _dbDeleteMany(options?: Repository.DeleteManyOptions): Promise<number>;
    /**
     * Acquires a connection and performs `Repository.exists`.
     *
     * @param id - The key field value identifying the record.
     * @param options - Optional settings.
     * @protected
     */
    protected _dbExists(id: SQBAdapter.IdOrIds, options?: Repository.ExistsOptions): Promise<boolean>;
    /**
     * Acquires a connection and performs `Repository.existsOne`.
     *
     * @param options - Optional settings.
     * @protected
     */
    protected _dbExistsOne(options?: Repository.ExistsOptions): Promise<boolean>;
    /**
     * Acquires a connection and performs `Repository.findById`.
     *
     * @param id - The key field value identifying the record.
     * @param options - Optional settings.
     * @protected
     */
    protected _dbFindById(id: SQBAdapter.IdOrIds, options?: Repository.FindOptions): Promise<PartialDTO<T> | undefined>;
    /**
     * Acquires a connection and performs `Repository.findOne`.
     *
     * @param options - Optional settings.
     * @protected
     */
    protected _dbFindOne(options?: StrictOmit<Repository.FindOneOptions, 'offset'> & {
        skip?: number;
    }): Promise<PartialDTO<T> | undefined>;
    /**
     * Acquires a connection and performs `Repository.findMany`.
     *
     * @param options - Optional settings.
     * @protected
     */
    protected _dbFindMany(options?: StrictOmit<Repository.FindManyOptions, 'offset'> & {
        skip?: number;
    }): Promise<PartialDTO<T>[]>;
    /**
     * Acquires a connection and performs `Repository.update`.
     *
     * @param id - The key field value identifying the record.
     * @param data - The update values.
     * @param options - Optional settings.
     * @protected
     */
    protected _dbUpdate(id: SQBAdapter.IdOrIds, data: PatchDTO<T>, options?: Repository.UpdateOptions): Promise<PartialDTO<T> | undefined>;
    /**
     * Acquires a connection and performs `Repository.updateOnly`.
     *
     * @param id - The key field value identifying the record.
     * @param data - The update values.
     * @param options - Optional settings.
     * @protected
     */
    protected _dbUpdateOnly(id: SQBAdapter.IdOrIds, data: PatchDTO<T>, options?: Repository.UpdateOptions): Promise<number>;
    /**
     * Acquires a connection and performs `Repository.updateMany`.
     *
     * @param data - The update values.
     * @param options - Optional settings.
     * @protected
     */
    protected _dbUpdateMany(data: PatchDTO<T>, options?: Repository.UpdateManyOptions): Promise<number>;
    /**
     * Builds the common filter for the given command.
     * Used primarily for multi-tenant isolation and similar cross-cutting concerns.
     *
     * @protected
     * @returns The resolved filter input, or `undefined` if none is configured.
     */
    protected _getCommonFilter(command: SqbEntityService.CommandInfo): SQBAdapter.FilterInput | Promise<SQBAdapter.FilterInput> | undefined;
    protected _executeCommand(command: SqbEntityService.CommandInfo, commandFn: () => any): Promise<any>;
    protected _beforeCreate(command: SqbEntityService.CreateCommand<T>): Promise<void>;
    protected _beforeUpdate(command: SqbEntityService.UpdateOneCommand<T>): Promise<void>;
    protected _beforeUpdateMany(command: SqbEntityService.UpdateManyCommand<T>): Promise<void>;
    protected _beforeDelete(command: SqbEntityService.DeleteOneCommand): Promise<void>;
    protected _beforeDeleteMany(command: SqbEntityService.DeleteManyCommand): Promise<void>;
    protected _afterCreate(command: SqbEntityService.CreateCommand<T>, result: PartialDTO<T>): Promise<void>;
    protected _afterUpdate(command: SqbEntityService.UpdateOneCommand<T>, result?: PartialDTO<T>): Promise<void>;
    protected _afterUpdateMany(command: SqbEntityService.UpdateManyCommand<T>, affected: number): Promise<void>;
    protected _afterDelete(command: SqbEntityService.DeleteOneCommand, affected: number): Promise<void>;
    protected _afterDeleteMany(command: SqbEntityService.DeleteManyCommand, affected: number): Promise<void>;
}
