/**
 * Arithmetic expressions compute a value from two operands.
 * Both `left` and `right` can be field references or nested expressions.
 * When `right` is omitted, `value` provides a literal operand.
 */
declare type ArithmeticExpression = {
    operator: 'add' | 'sub' | 'mul' | 'div' | 'mod' | 'pow';
    left: Operand;
    right: Operand;
} | {
    operator: 'add' | 'sub' | 'mul' | 'div' | 'mod' | 'pow';
    left: Operand;
    value: any;
};

declare type ArrayObjectType = {
    [s: string]: any[];
};

/**
 * A comparison condition. `left` is the first operand (field reference or
 * expression). The second operand is either `right` (another field/expression)
 * or `value` (a literal). For `in`, use `values` (an array of literals).
 */
declare type ComparisonExpression = {
    operator: 'eq';
    left: Operand;
    value: any;
} | {
    operator: 'eq';
    left: Operand;
    right: Operand;
} | {
    operator: 'ne';
    left: Operand;
    value: any;
} | {
    operator: 'ne';
    left: Operand;
    right: Operand;
} | {
    operator: 'gt';
    left: Operand;
    value: any;
} | {
    operator: 'gt';
    left: Operand;
    right: Operand;
} | {
    operator: 'lt';
    left: Operand;
    value: any;
} | {
    operator: 'lt';
    left: Operand;
    right: Operand;
} | {
    operator: 'gte';
    left: Operand;
    value: any;
} | {
    operator: 'gte';
    left: Operand;
    right: Operand;
} | {
    operator: 'lte';
    left: Operand;
    value: any;
} | {
    operator: 'lte';
    left: Operand;
    right: Operand;
} | {
    operator: 'in';
    left: Operand;
    values: any[];
};

/**
 * Constraint builder with `$`-prefixed field references and type-safe
 * autocompletion via template literal types.
 *
 * ```typescript
 * const c = new Constraint<typeof factors>();
 * c.eq("$OS", "Mac")
 * c.gt(c.mul("$Price", "$Qty"), 10000)
 * c.sum("$A", "$B", "$C")
 * ```
 */
export declare class Constraint<T extends Record<string, readonly any[]> = ArrayObjectType> {
    eq(left: FieldOrExpr<T>, right: FieldOrExpr<T> | RightOperand<T>): Expression;
    ne(left: FieldOrExpr<T>, right: FieldOrExpr<T> | RightOperand<T>): Expression;
    gt(left: FieldOrExpr<T>, right: FieldOrExpr<T> | RightOperand<T>): Expression;
    lt(left: FieldOrExpr<T>, right: FieldOrExpr<T> | RightOperand<T>): Expression;
    gte(left: FieldOrExpr<T>, right: FieldOrExpr<T> | RightOperand<T>): Expression;
    lte(left: FieldOrExpr<T>, right: FieldOrExpr<T> | RightOperand<T>): Expression;
    in(left: FieldOrExpr<T>, values: any[]): Expression;
    and(...conditions: Expression[]): Expression;
    or(...conditions: Expression[]): Expression;
    not(condition: Expression): Expression;
    add(left: FieldOrExpr<T> | RightOperand<T>, right: FieldOrExpr<T> | RightOperand<T>): ArithmeticExpression;
    sub(left: FieldOrExpr<T> | RightOperand<T>, right: FieldOrExpr<T> | RightOperand<T>): ArithmeticExpression;
    mul(left: FieldOrExpr<T> | RightOperand<T>, right: FieldOrExpr<T> | RightOperand<T>): ArithmeticExpression;
    div(left: FieldOrExpr<T> | RightOperand<T>, right: FieldOrExpr<T> | RightOperand<T>): ArithmeticExpression;
    mod(left: FieldOrExpr<T> | RightOperand<T>, right: FieldOrExpr<T> | RightOperand<T>): ArithmeticExpression;
    pow(left: FieldOrExpr<T> | RightOperand<T>, right: FieldOrExpr<T> | RightOperand<T>): ArithmeticExpression;
    sum(...args: (FieldOrExpr<T> | RightOperand<T>)[]): ArithmeticExpression;
    product(...args: (FieldOrExpr<T> | RightOperand<T>)[]): ArithmeticExpression;
    fn(requires: (string & keyof T)[], evaluate: (row: {
        [K in keyof T]: any;
    }) => boolean): Expression;
    val(value: any): ValWrapper;
}

declare type Expression = ComparisonExpression | LogicalExpression | FnExpression;

/** A field reference or arithmetic expression (resolves to an Operand). */
declare type FieldOrExpr<T> = `$${string & keyof T}` | ArithmeticExpression;

/**
 * Escape hatch for constraints that cannot be expressed declaratively.
 * The engine cannot perform three-valued reasoning on these — when a
 * dependency key is missing the condition is treated as `null`.
 * Provide `requires` so the engine knows when it is safe to call `evaluate`.
 */
declare type FnExpression = {
    operator: 'fn';
    requires: string[];
    evaluate: (row: {
        [key: string]: any;
    }) => boolean;
};

/** A literal value (preserves template literal autocomplete via `string & {}`). */
declare type Literal = (string & {}) | number | boolean | null;

declare type LogicalExpression = {
    operator: 'not';
    condition: Expression;
} | {
    operator: 'and';
    conditions: Expression[];
} | {
    operator: 'or';
    conditions: Expression[];
};

/**
 * An operand is either a field reference (string, supports dot notation
 * like `"payment.method"`) or an arithmetic expression.
 */
declare type Operand = string | ArithmeticExpression;

/** Right-hand operand: field reference, expression, literal, or val-wrapped. */
declare type RightOperand<T> = FieldOrExpr<T> | Literal | ValWrapper;

/** Wrapper to force a value to be treated as a literal, not a field reference. */
declare type ValWrapper = {
    __val: true;
    value: any;
};

export { }
