import { StandardSchemaV1 } from '@standard-schema/spec';

interface EngineSingletonBase {
    context: Record<string, unknown>;
    globalSchema: StandardSchemaV1 | undefined;
    helpers: Record<string, Function>;
}
type Prettify<T> = {
    [K in keyof T]: T[K];
} & {};
type RecordKey = string | number | symbol;
type Reconcile<A extends Object, B extends Object, Override extends boolean = false, Stack extends number[] = []> = Stack["length"] extends 16 ? A : Override extends true ? {
    [key in keyof A as key extends keyof B ? never : key]: A[key];
} extends infer Collision ? {} extends Collision ? {
    [key in keyof B]: IsBothObject<A[key], B[key]> extends true ? Reconcile<A[key], B[key], Override, [
        0,
        ...Stack
    ]> : B[key];
} : Prettify<Collision & {
    [key in keyof B]: B[key];
}> : never : {
    [key in keyof B as key extends keyof A ? never : key]: B[key];
} extends infer Collision ? {} extends Collision ? {
    [key in keyof A]: IsBothObject<A[key], B[key]> extends true ? Reconcile<A[key], B[key], Override, [
        0,
        ...Stack
    ]> : A[key];
} : Prettify<{
    [key in keyof A]: A[key];
} & Collision> : never;
type IsBothObject<A, B> = A extends Record<RecordKey, unknown> ? B extends Record<RecordKey, unknown> ? IsClass<A> extends false ? IsClass<B> extends false ? true : false : false : false : false;
type IsClass<V> = V extends abstract new (...args: any) => any ? true : false;
type DeepReadonly<T> = T extends Function ? T : T extends Array<infer U> ? ReadonlyArray<DeepReadonly<U>> : T extends object ? {
    readonly [P in keyof T]: DeepReadonly<T[P]>;
} : T;

type AnyEngine = Engine<any>;
type Rule = {
    name: string;
    priority: number;
    handler: (...args: any[]) => void;
    schema?: StandardSchemaV1;
};
declare class Session<Context extends Record<string, unknown>, Helpers extends Record<string, Function>> {
    context: Context;
    private rules;
    private insertedFacts;
    private wrappedHelpers;
    constructor(context: Context, rules: Rule[], helpers?: Helpers);
    insert(facts: unknown): this;
    insertMany(facts: unknown[]): this;
    fire(): this;
}
declare class Engine<const in out Singleton extends EngineSingletonBase = {
    context: {};
    globalSchema: undefined;
    helpers: {};
}> {
    "~types": {
        Singleton: Singleton;
    };
    private initialContext;
    private rules;
    private globalSchema;
    private helpers;
    schema<const GlobalFactsSchema extends StandardSchemaV1>(schema: GlobalFactsSchema): Engine<{
        context: Singleton["context"];
        globalSchema: GlobalFactsSchema;
        helpers: Singleton["helpers"];
    }>;
    context<const Name extends string | number | symbol, Value>(name: Name, value: Value): Engine<{
        context: Reconcile<Singleton["context"], {
            [key in Name]: Value;
        }>;
        globalSchema: Singleton["globalSchema"];
        helpers: Singleton["helpers"];
    }>;
    context<IncomingContext extends Record<string, unknown>>(context: IncomingContext): Engine<{
        context: Reconcile<Singleton["context"], IncomingContext>;
        globalSchema: Singleton["globalSchema"];
        helpers: Singleton["helpers"];
    }>;
    helper<const Name extends string, Args extends any[], ReturnType>(name: Name, fn: (context: Singleton["context"], ...args: Args) => ReturnType): Engine<{
        context: Singleton["context"];
        globalSchema: Singleton["globalSchema"];
        helpers: Singleton["helpers"] & {
            [key in Name]: (...args: Args) => ReturnType;
        };
    }>;
    rule<const RuleName extends string, const FactsSchema extends Singleton["globalSchema"] extends undefined ? StandardSchemaV1 | undefined : Singleton["globalSchema"]>(name: RuleName, handler: (facts: DeepReadonly<FactsSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<FactsSchema> : unknown>, { context, helpers, }: {
        context: Singleton["context"];
        helpers: Singleton["helpers"];
    }) => void, meta?: {
        schema?: FactsSchema;
        priority?: number;
    }): Engine<{
        context: Singleton["context"];
        globalSchema: Singleton["globalSchema"];
        helpers: Singleton["helpers"];
    }>;
    use<const NewEngine extends AnyEngine>(instance: NewEngine): Engine<{
        context: Singleton["context"] & NewEngine["~types"]["Singleton"]["context"];
        globalSchema: Singleton["globalSchema"];
        helpers: Singleton["helpers"] & NewEngine["~types"]["Singleton"]["helpers"];
    }>;
    createSession(): Session<Singleton["context"], Singleton["helpers"]>;
}

export { type AnyEngine, Engine };
