import { Aggregate, BasicExpression } from '../ir.js';
import { IncludesRuntime } from '../live/includes-runtime.js';
import { RefProxy } from './ref-proxy.js';
import { ContainsAggregate, Context, RefLeaf, StringifiableScalar } from './types.js';
import { BaseQueryBuilder, QueryBuilder } from './index.js';
type WithAggregate<TResult, TInputs> = true extends ContainsAggregate<TInputs> ? TResult & {
    readonly __hasAggregate: true;
} : TResult;
type StringRef = RefLeaf<string> | RefLeaf<string | null> | RefLeaf<string | undefined>;
type StringRefProxy = RefProxy<string> | RefProxy<string | null> | RefProxy<string | undefined>;
type StringBasicExpression = BasicExpression<string> | BasicExpression<string | null> | BasicExpression<string | undefined>;
type StringLike = StringRef | StringRefProxy | StringBasicExpression | string | null | undefined;
type ComparisonOperand<T> = RefProxy<T> | RefLeaf<T> | T | BasicExpression<T> | undefined | null;
type ComparisonOperandPrimitive<T extends string | number | boolean> = T | BasicExpression<T> | undefined | null;
type ExpressionLike = Aggregate | BasicExpression | RefProxy<any> | RefLeaf<any> | string | number | boolean | bigint | Date | null | undefined | Array<unknown>;
export type CaseWhenValue = ExpressionLike | IncludeWrapper<any> | ToArrayWrapper<any> | ConcatToArrayWrapper<any> | (Record<string, any> & {
    _bindCollectionSources?: never;
});
type ExtractCaseWhenValue<T> = T extends CaseWhenWrapper<infer TResult> ? TResult : T;
type CaseWhenResult<TValues extends Array<CaseWhenValue>, THasDefault extends boolean, TConditions = never> = WithAggregate<TValues[number] extends ExpressionLike ? BasicExpression<ExtractType<TValues[number]> | (THasDefault extends true ? never : null)> : CaseWhenWrapper<ExtractCaseWhenValue<TValues[number]> | (THasDefault extends true ? never : undefined)>, [
    TValues,
    TConditions
]>;
type CaseWhenInputs<T extends Array<CaseWhenValue>, TPairs extends Array<unknown> = []> = TPairs[`length`] extends 6 ? T : T extends [unknown, unknown, ...infer Rest extends Array<CaseWhenValue>] ? [ExpressionLike, CaseWhenValue, ...CaseWhenInputs<Rest, [...TPairs, 0]>] : T;
type CaseWhenOutput<T extends Array<CaseWhenValue>, TValues extends Array<CaseWhenValue> = [], TConditions extends Array<ExpressionLike> = []> = T extends [infer Default extends CaseWhenValue] ? CaseWhenResult<[...TValues, Default], true, TConditions> : T extends [] ? CaseWhenResult<TValues, false, TConditions> : TConditions[`length`] extends 5 ? any : T extends [
    infer Condition extends ExpressionLike,
    infer Value extends CaseWhenValue,
    ...infer Rest extends Array<CaseWhenValue>
] ? CaseWhenOutput<Rest, [...TValues, Value], [...TConditions, Condition]> : never;
type ExtractType<T> = T extends RefProxy<infer U> ? U : T extends RefLeaf<infer U> ? U : T extends BasicExpression<infer U> | Aggregate<infer U> ? U : T;
type IsAny<T> = 0 extends 1 & T ? true : false;
type AggregateArgument<T, Domain> = T & (IsAny<ExtractType<T>> extends true ? unknown : [Exclude<ExtractType<T>, null | undefined>] extends [never] ? never : [Exclude<ExtractType<T>, null | undefined>] extends [Domain] ? unknown : never);
type OrderableAggregateValue = number | Date | bigint | string;
type AggregateWrapper<T> = RefProxy<T> | RefLeaf<T> | BasicExpression<T>;
type NumericAggregateWrapperArgument<T> = AggregateArgument<AggregateWrapper<T>, number>;
type OrderableAggregateWrapperArgument<T> = AggregateArgument<AggregateWrapper<T>, OrderableAggregateValue>;
type NumericAggregateArgument<T> = AggregateArgument<T, number>;
type OrderableAggregateArgument<T> = AggregateArgument<T, OrderableAggregateValue>;
type StringFunctionReturnType<T> = ExtractType<T> extends infer U ? U extends string | undefined | null ? BasicExpression<U> : BasicExpression<string | undefined | null> : BasicExpression<string | undefined | null>;
type NumericFunctionReturnType<T> = ExtractType<T> extends infer U ? U extends string | Array<any> | undefined | null | number ? BasicExpression<MapToNumber<U>> : BasicExpression<number | undefined | null> : BasicExpression<number | undefined | null>;
type MapToNumber<T> = T extends string | Array<any> ? number : T extends undefined ? undefined : T extends null ? null : T;
type BinaryNumericReturnType = BasicExpression<number>;
type DivideReturnType = BasicExpression<number | null>;
export declare function eq<L extends ExpressionLike, R extends ExpressionLike>(left: L & (true extends ContainsAggregate<[L, R]> ? unknown : never), right: R): WithAggregate<BasicExpression<boolean>, [L, R]>;
export declare function eq<T>(left: ComparisonOperand<T>, right: ComparisonOperand<T>): BasicExpression<boolean>;
export declare function eq<T extends string | number | boolean>(left: ComparisonOperandPrimitive<T>, right: ComparisonOperandPrimitive<T>): BasicExpression<boolean>;
export declare function eq<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>;
export declare function gt<L extends ExpressionLike, R extends ExpressionLike>(left: L & (true extends ContainsAggregate<[L, R]> ? unknown : never), right: R): WithAggregate<BasicExpression<boolean>, [L, R]>;
export declare function gt<T>(left: ComparisonOperand<T>, right: ComparisonOperand<T>): BasicExpression<boolean>;
export declare function gt<T extends string | number>(left: ComparisonOperandPrimitive<T>, right: ComparisonOperandPrimitive<T>): BasicExpression<boolean>;
export declare function gt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>;
export declare function gte<L extends ExpressionLike, R extends ExpressionLike>(left: L & (true extends ContainsAggregate<[L, R]> ? unknown : never), right: R): WithAggregate<BasicExpression<boolean>, [L, R]>;
export declare function gte<T>(left: ComparisonOperand<T>, right: ComparisonOperand<T>): BasicExpression<boolean>;
export declare function gte<T extends string | number>(left: ComparisonOperandPrimitive<T>, right: ComparisonOperandPrimitive<T>): BasicExpression<boolean>;
export declare function gte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>;
export declare function lt<L extends ExpressionLike, R extends ExpressionLike>(left: L & (true extends ContainsAggregate<[L, R]> ? unknown : never), right: R): WithAggregate<BasicExpression<boolean>, [L, R]>;
export declare function lt<T>(left: ComparisonOperand<T>, right: ComparisonOperand<T>): BasicExpression<boolean>;
export declare function lt<T extends string | number>(left: ComparisonOperandPrimitive<T>, right: ComparisonOperandPrimitive<T>): BasicExpression<boolean>;
export declare function lt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>;
export declare function lte<L extends ExpressionLike, R extends ExpressionLike>(left: L & (true extends ContainsAggregate<[L, R]> ? unknown : never), right: R): WithAggregate<BasicExpression<boolean>, [L, R]>;
export declare function lte<T>(left: ComparisonOperand<T>, right: ComparisonOperand<T>): BasicExpression<boolean>;
export declare function lte<T extends string | number>(left: ComparisonOperandPrimitive<T>, right: ComparisonOperandPrimitive<T>): BasicExpression<boolean>;
export declare function lte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>;
export declare function and<T extends [ExpressionLike, ExpressionLike, ...Array<ExpressionLike>]>(...args: T): WithAggregate<BasicExpression<boolean>, T>;
export declare function or<T extends [ExpressionLike, ExpressionLike, ...Array<ExpressionLike>]>(...args: T): WithAggregate<BasicExpression<boolean>, T>;
export declare function not<T extends ExpressionLike>(value: T): WithAggregate<BasicExpression<boolean>, T>;
export declare function isUndefined<T extends ExpressionLike>(value: T): WithAggregate<BasicExpression<boolean>, T>;
export declare function isNull<T extends ExpressionLike>(value: T): WithAggregate<BasicExpression<boolean>, T>;
export declare function inArray<L extends ExpressionLike, R extends ExpressionLike>(left: L, right: R): WithAggregate<BasicExpression<boolean>, [L, R]>;
export declare function like<L extends StringLike, R extends StringLike>(left: L, right: R): WithAggregate<BasicExpression<boolean>, [L, R]>;
export declare function like(left: StringLike, right: StringLike): BasicExpression<boolean>;
export declare function ilike<L extends StringLike, R extends StringLike>(left: L, right: R): WithAggregate<BasicExpression<boolean>, [L, R]>;
export declare function upper<T extends ExpressionLike>(arg: T): WithAggregate<StringFunctionReturnType<T>, T>;
export declare function lower<T extends ExpressionLike>(arg: T): WithAggregate<StringFunctionReturnType<T>, T>;
export declare function length<T extends ExpressionLike>(arg: T): WithAggregate<NumericFunctionReturnType<T>, T>;
export declare function concat<T extends StringifiableScalar>(arg: ToArrayWrapper<T>): ConcatToArrayWrapper<T>;
export declare function concat<T extends Array<ExpressionLike>>(...args: T): WithAggregate<BasicExpression<string>, T>;
type CoalesceArgTypes<T extends Array<ExpressionLike>> = {
    [K in keyof T]: NonNullable<ExtractType<T[K]>>;
}[number];
type HasGuaranteedNonNull<T extends Array<ExpressionLike>> = {
    [K in keyof T]: null extends ExtractType<T[K]> ? false : undefined extends ExtractType<T[K]> ? false : true;
}[number] extends false ? false : true;
type CoalesceReturnType<T extends Array<ExpressionLike>> = WithAggregate<HasGuaranteedNonNull<T> extends true ? BasicExpression<CoalesceArgTypes<T>> : BasicExpression<CoalesceArgTypes<T> | null>, T>;
export declare function coalesce<T extends [ExpressionLike, ...Array<ExpressionLike>]>(...args: T): CoalesceReturnType<T>;
/**
 * Returns the value for the first matching condition, similar to SQL
 * `CASE WHEN`.
 *
 * Arguments are evaluated as condition/value pairs followed by an optional
 * default value. Scalar branch values return a query expression and can be used
 * in expression contexts like `select`, `where`, `orderBy`, `groupBy`,
 * `having`, and equality join operands. If no scalar branch matches and no
 * default is provided, the result is `null`.
 *
 * When a branch value is a projection object, `caseWhen` becomes a select-only
 * projection value. Projection branches can include nested fields, ref spreads,
 * and includes. If no projection branch matches and no default is provided, the
 * result is `undefined`.
 *
 * @example
 * ```ts
 * caseWhen(gt(user.age, 18), `adult`, `minor`)
 * ```
 *
 * @example
 * ```ts
 * caseWhen(
 *   gt(user.age, 65),
 *   `senior`,
 *   gt(user.age, 18),
 *   `adult`,
 *   `minor`,
 * )
 * ```
 *
 * @example
 * ```ts
 * caseWhen(gt(user.age, 18), {
 *   ...user,
 *   posts: include(
 *     q
 *       .from({ post: postsCollection })
 *       .where(({ post }) => eq(post.userId, user.id)),
 *   ),
 * })
 * ```
 */
export declare function caseWhen<T extends [ExpressionLike, CaseWhenValue, ...Array<CaseWhenValue>]>(...args: T & CaseWhenInputs<T>): CaseWhenOutput<T>;
export declare function add<T1 extends ExpressionLike, T2 extends ExpressionLike>(left: T1, right: T2): WithAggregate<BinaryNumericReturnType, [T1, T2]>;
export declare function subtract<T1 extends ExpressionLike, T2 extends ExpressionLike>(left: T1, right: T2): WithAggregate<BinaryNumericReturnType, [T1, T2]>;
export declare function multiply<T1 extends ExpressionLike, T2 extends ExpressionLike>(left: T1, right: T2): WithAggregate<BinaryNumericReturnType, [T1, T2]>;
export declare function divide<T1 extends ExpressionLike, T2 extends ExpressionLike>(left: T1, right: T2): WithAggregate<DivideReturnType, [T1, T2]>;
export declare function count(arg: ExpressionLike): Aggregate<number>;
export declare function avg<T extends number>(arg: T): Aggregate<number>;
export declare function avg<T>(arg: NumericAggregateWrapperArgument<T>): Aggregate<number>;
export declare function avg<T extends ExpressionLike>(arg: NumericAggregateArgument<T>): Aggregate<number>;
export declare function sum<T extends number>(arg: T): Aggregate<number>;
export declare function sum<T>(arg: NumericAggregateWrapperArgument<T>): Aggregate<number>;
export declare function sum<T extends ExpressionLike>(arg: NumericAggregateArgument<T>): Aggregate<number>;
export declare function min<T extends OrderableAggregateValue>(arg: T): Aggregate<T>;
export declare function min<T>(arg: OrderableAggregateWrapperArgument<T>): Aggregate<T>;
export declare function min<T extends ExpressionLike>(arg: OrderableAggregateArgument<T>): Aggregate<ExtractType<T>>;
export declare function max<T extends OrderableAggregateValue>(arg: T): Aggregate<T>;
export declare function max<T>(arg: OrderableAggregateWrapperArgument<T>): Aggregate<T>;
export declare function max<T extends ExpressionLike>(arg: OrderableAggregateArgument<T>): Aggregate<ExtractType<T>>;
/**
 * List of comparison function names that can be used with indexes
 */
export declare const indexableOperations: readonly ["eq", "gt", "gte", "lt", "lte", "in"];
export declare const comparisonFunctions: readonly ["eq", "gt", "gte", "lt", "lte", "in", "like", "ilike"];
/**
 * All supported operator names in TanStack DB expressions
 */
export declare const operators: readonly ["eq", "gt", "gte", "lt", "lte", "in", "like", "ilike", "and", "or", "not", "isNull", "isUndefined", "upper", "lower", "length", "concat", "add", "subtract", "multiply", "divide", "coalesce", "caseWhen", "count", "avg", "sum", "min", "max"];
export type OperatorName = (typeof operators)[number];
export declare class ToArrayWrapper<_T = unknown> {
    readonly query: QueryBuilder<any>;
    readonly runtime: IncludesRuntime;
    readonly __brand: "ToArrayWrapper";
    readonly _type: `toArray`;
    readonly _result: _T;
    constructor(query: QueryBuilder<any>, runtime: IncludesRuntime);
}
export declare class ConcatToArrayWrapper<_T = unknown> {
    readonly query: QueryBuilder<any>;
    readonly runtime: IncludesRuntime;
    readonly __brand: "ConcatToArrayWrapper";
    readonly _type: `concatToArray`;
    readonly _result: _T;
    constructor(query: QueryBuilder<any>, runtime: IncludesRuntime);
}
export declare class CaseWhenWrapper<_T = any> {
    readonly args: Array<CaseWhenValue>;
    readonly __brand: "CaseWhenWrapper";
    readonly _type: `caseWhen`;
    readonly _result?: _T;
    constructor(args: Array<CaseWhenValue>);
}
export declare class MaterializeWrapper<_T = unknown, _IsSingle extends boolean = boolean> {
    readonly query: QueryBuilder<any>;
    readonly runtime: IncludesRuntime;
    readonly __brand: "MaterializeWrapper";
    readonly _type: `materialize`;
    readonly _result: _T;
    readonly _isSingle: _IsSingle;
    constructor(query: QueryBuilder<any>, runtime: IncludesRuntime);
}
export declare class IncludeWrapper<_TContext extends Context = any> {
    readonly query: BaseQueryBuilder<any>;
    readonly runtime: IncludesRuntime;
    readonly __brand: "IncludeWrapper";
    readonly _context: _TContext;
    constructor(query: BaseQueryBuilder<any>, runtime: IncludesRuntime);
}
export {};
