import { EntityMetadata, type AnyEntity, type EntityKey, type Constructor, type DeepPartial, type EntityName, type EntityProperty, type CleanKeys, type ExpandProperty, type IsNever, type EntityCtor } from '../typings.js';
import { type EventType, ReferenceKind } from '../enums.js';
import type { EventArgs } from '../events/EventSubscriber.js';
import { Type } from '../types/Type.js';
import type { PropertyOptions, ManyToOneOptions, OneToOneOptions, OneToManyOptions, ManyToManyOptions, EmbeddedOptions, EnumOptions, PrimaryKeyOptions, SerializedPrimaryKeyOptions, IndexOptions, UniqueOptions } from './types.js';
type TypeType = string | NumberConstructor | StringConstructor | BooleanConstructor | DateConstructor | ArrayConstructor | Constructor<Type<any>> | Type<any>;
type TypeDef<Target> = {
    type: TypeType;
} | {
    entity: () => EntityName<Target> | EntityName[];
};
type EmbeddedTypeDef<Target> = {
    type: TypeType;
} | {
    entity: () => EntityName<Target> | EntityName[];
};
/** Union type representing all possible property definition shapes in an EntitySchema. */
export type EntitySchemaProperty<Target, Owner> = ({
    kind: ReferenceKind.MANY_TO_ONE | 'm:1';
} & TypeDef<Target> & ManyToOneOptions<Owner, Target>) | ({
    kind: ReferenceKind.ONE_TO_ONE | '1:1';
} & TypeDef<Target> & OneToOneOptions<Owner, Target>) | ({
    kind: ReferenceKind.ONE_TO_MANY | '1:m';
} & TypeDef<Target> & OneToManyOptions<Owner, Target>) | ({
    kind: ReferenceKind.MANY_TO_MANY | 'm:n';
} & TypeDef<Target> & ManyToManyOptions<Owner, Target>) | ({
    kind: ReferenceKind.EMBEDDED | 'embedded';
} & EmbeddedTypeDef<Target> & EmbeddedOptions<Owner, Target> & PropertyOptions<Owner>) | ({
    enum: true;
} & EnumOptions<Owner>) | (TypeDef<Target> & PropertyOptions<Owner>);
type OmitBaseProps<Entity, Base> = IsNever<Base> extends true ? Entity : Omit<Entity, keyof Base>;
/** Configuration object for defining an entity via EntitySchema. */
export type EntitySchemaMetadata<Entity, Base = never, Class extends EntityCtor = EntityCtor<Entity>> = Omit<Partial<EntityMetadata<Entity>>, 'name' | 'properties' | 'extends'> & ({
    name: string;
} | {
    class: Class;
    name?: string;
}) & {
    extends?: EntityName<Base>;
} & {
    properties?: {
        [Key in keyof OmitBaseProps<Entity, Base> as CleanKeys<OmitBaseProps<Entity, Base>, Key>]-?: EntitySchemaProperty<ExpandProperty<NonNullable<Entity[Key]>>, Entity>;
    };
} & {
    inheritance?: 'tpt';
};
/** Class-less entity definition that provides a programmatic API for defining entities without decorators. */
export declare class EntitySchema<Entity = any, Base = never, Class extends EntityCtor = EntityCtor<Entity>> {
    /**
     * When schema links the entity class via `class` option, this registry allows the lookup from opposite side,
     * so we can use the class in `entities` option just like the EntitySchema instance.
     *
     * Stored on `globalThis` via `Symbol.for` to survive the CJS/ESM dual-package hazard
     * (e.g. when `tsx` loads the same package in both module systems).
     */
    static get REGISTRY(): Map<AnyEntity, EntitySchema>;
    /** @internal Type-level marker for fast entity type inference */
    readonly '~entity': Entity;
    private readonly _meta;
    private internal;
    private initialized;
    constructor(meta: EntitySchemaMetadata<Entity, Base, Class>);
    /**
     * Checks if the given value is an EntitySchema instance, using duck-typing
     * as a fallback when `instanceof` fails due to CJS/ESM dual-package hazard
     * (e.g. when using `tsx` or `@swc-node/register` with `"type": "commonjs"` projects).
     */
    static is(item: unknown): item is EntitySchema;
    /** Creates an EntitySchema from existing EntityMetadata (used internally). */
    static fromMetadata<T = AnyEntity, U = never>(meta: EntityMetadata<T> | DeepPartial<EntityMetadata<T>>): EntitySchema<T, U>;
    /** Adds a scalar property to the entity schema. */
    addProperty(name: EntityKey<Entity>, type?: TypeType, options?: PropertyOptions<Entity> | EntityProperty<Entity>): void;
    /** Adds an enum property to the entity schema. */
    addEnum(name: EntityKey<Entity>, type?: TypeType, options?: EnumOptions<Entity>): void;
    /** Adds a version property for optimistic locking. */
    addVersion(name: EntityKey<Entity>, type: TypeType, options?: PropertyOptions<Entity>): void;
    /** Adds a primary key property to the entity schema. */
    addPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: PrimaryKeyOptions<Entity>): void;
    /** Adds a serialized primary key property (e.g. for MongoDB ObjectId). */
    addSerializedPrimaryKey(name: EntityKey<Entity>, type: TypeType, options?: SerializedPrimaryKeyOptions<Entity>): void;
    /** Adds an embedded property to the entity schema. */
    addEmbedded<Target = AnyEntity>(name: EntityKey<Entity>, options: EmbeddedOptions<Entity, Target>): void;
    /** Adds a many-to-one relation to the entity schema. */
    addManyToOne<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToOneOptions<Entity, Target>): void;
    /** Adds a many-to-many relation to the entity schema. */
    addManyToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: ManyToManyOptions<Entity, Target>): void;
    /** Adds a one-to-many relation to the entity schema. */
    addOneToMany<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: OneToManyOptions<Entity, Target>): void;
    /** Adds a one-to-one relation to the entity schema. */
    addOneToOne<Target = AnyEntity>(name: EntityKey<Entity>, type: TypeType, options: OneToOneOptions<Entity, Target>): void;
    /** Adds an index definition to the entity schema. */
    addIndex<Key extends string>(options: IndexOptions<Entity, Key>): void;
    /** Adds a unique constraint definition to the entity schema. */
    addUnique<Key extends string>(options: UniqueOptions<Entity, Key>): void;
    /** Sets a custom repository class for this entity. */
    setCustomRepository(repository: () => Constructor): void;
    /** Sets the base entity that this schema extends. */
    setExtends(base: EntityName): void;
    /** Sets or replaces the entity class associated with this schema. */
    setClass(cls: Class): void;
    /** Returns the underlying EntityMetadata. */
    get meta(): EntityMetadata<Entity, Class>;
    /** Returns the entity class name. */
    get name(): string | EntityName<Entity>;
    /** Returns the database table name. */
    get tableName(): string;
    get class(): Class;
    get properties(): Record<string, any>;
    new(...params: ConstructorParameters<Class>): Entity;
    /**
     * @internal
     */
    init(): this;
    /**
     * Check if this entity is part of a TPT hierarchy by walking up the extends chain.
     * This handles mid-level abstract entities (e.g., Animal -> Mammal -> Dog where Mammal is abstract).
     */
    private isPartOfTPTHierarchy;
    private initProperties;
    private initPrimaryKeys;
    private normalizeType;
    private createProperty;
    private rename;
    private renameCompositeOptions;
    /**
     * Adds a lifecycle hook handler to the entity schema.
     * This method allows registering hooks after the entity is defined,
     * which can be useful for avoiding circular type references.
     *
     * @example
     * ```ts
     * export const Article = defineEntity({
     *   name: 'Article',
     *   properties: { ... },
     * });
     *
     * Article.addHook('beforeCreate', async args => {
     *   args.entity.slug = args.entity.title.toLowerCase();
     * });
     * ```
     */
    addHook<T extends Entity = Entity>(event: EventType | `${EventType}`, handler: (args: EventArgs<T>) => void | Promise<void>): this;
}
export {};
