import type { ColumnDef } from '../schema/columns';
import type { Condition } from './conditions';
import type { AnyTable, InferRow, InsertRow } from '../schema/table';
import type { Executor } from '../executor';
/**
 * Narrow a row type to specific columns using a mapped type.
 * Unlike Pick, TypeScript eagerly evaluates { [K in C]: T[K] } to a concrete
 * shape in hover info: { id: string; name: string } instead of Pick<...>.
 */
export type NarrowRow<T, C extends keyof T> = {
    [K in C]: T[K];
};
/**
 * Force TypeScript to expand intersection/mapped types into a flat object
 * in hover info: Prettify<{ id: string } & { name: string }> → { id: string; name: string }.
 */
export type Prettify<T> = {
    [K in keyof T]: T[K];
} & {};
/** Anything that can produce SQL — used by `db.batch()`. */
export interface Executable {
    toSQL(): {
        sql: string;
        params: unknown[];
    };
}
/**
 * Full SELECT builder — created directly via `db.selectFrom(table)`.
 * Entry point: `db.selectFrom(table)`.
 * Returns `InferRow<T>[]` (all columns) from `execute()`.
 * Call `.columns()` to narrow — returns a `NarrowedSelectBuilder`.
 */
export declare class SelectBuilder<T extends AnyTable> implements Executable {
    #private;
    constructor(executor: Executor, tableName: string, table: T, conditions?: Condition[], selectedColumns?: (keyof InferRow<T>)[] | null, orderByClauses?: {
        column: ColumnDef<any, any>;
        direction: 'asc' | 'desc';
    }[], limitValue?: number | null, offsetValue?: number | null, distinct?: boolean);
    /** Add a WHERE condition. Multiple calls stack. */
    where(condition: Condition): SelectBuilder<T>;
    /**
     * Narrow which columns appear in the result.
     * Returns a `NarrowedSelectBuilder` with a clean `{ id: string; name: string }` return type.
     *
     * @example
     * db.selectFrom(users).columns(["id", "name"]).execute()
     * // ^? { id: string; name: string }[]
     */
    columns<K extends keyof InferRow<T>>(keys: K[]): NarrowedSelectBuilder<T, K>;
    /** Return a single row or null instead of an array. Adds `LIMIT 1` to the SQL. */
    single(): SingleSelectBuilder<T>;
    /** Return only distinct (unique) rows. */
    distinct(): SelectBuilder<T>;
    /** Add an ORDER BY clause. Multiple calls stack. */
    orderBy<K extends keyof InferRow<T>>(key: K, direction?: 'asc' | 'desc'): SelectBuilder<T>;
    /** Limit the number of results. */
    limit(n: number): SelectBuilder<T>;
    /** Skip N rows before returning results. */
    offset(n: number): SelectBuilder<T>;
    toSQL(): {
        sql: string;
        params: unknown[];
    };
    /** Execute the query and return all matching rows. */
    execute(): Promise<InferRow<T>[]>;
}
/**
 * Narrowed SELECT builder — after `.columns()` has been called.
 * Returns `NarrowRow<InferRow<T>, C>[]` from `execute()` — a clean
 * `{ id: string; name: string }` shape, no Pick wrapper.
 */
export declare class NarrowedSelectBuilder<T extends AnyTable, C extends keyof InferRow<T>> implements Executable {
    #private;
    constructor(executor: Executor, tableName: string, table: T, conditions: Condition[], selectedColumns: C[], orderByClauses: {
        column: ColumnDef<any, any>;
        direction: 'asc' | 'desc';
    }[], limitValue: number | null, offsetValue: number | null, distinct: boolean);
    where(condition: Condition): NarrowedSelectBuilder<T, C>;
    distinct(): NarrowedSelectBuilder<T, C>;
    single(): NarrowedSingleSelectBuilder<T, C>;
    orderBy<K extends keyof InferRow<T>>(key: K, direction?: 'asc' | 'desc'): NarrowedSelectBuilder<T, C>;
    limit(n: number): NarrowedSelectBuilder<T, C>;
    offset(n: number): NarrowedSelectBuilder<T, C>;
    toSQL(): {
        sql: string;
        params: unknown[];
    };
    /** Execute the query and return narrowed rows. */
    execute(): Promise<Prettify<NarrowRow<InferRow<T>, C>>[]>;
}
/**
 * Single-row SELECT builder — after `.single()` on a `SelectBuilder`.
 * Returns `InferRow<T> | null` from `execute()`.
 */
export declare class SingleSelectBuilder<T extends AnyTable> implements Executable {
    #private;
    constructor(executor: Executor, tableName: string, table: T, conditions: Condition[], selectedColumns?: (keyof InferRow<T>)[] | null, orderByClauses?: {
        column: ColumnDef<any, any>;
        direction: 'asc' | 'desc';
    }[], offsetValue?: number | null, distinct?: boolean);
    where(condition: Condition): SingleSelectBuilder<T>;
    orderBy<K extends keyof InferRow<T>>(key: K, direction?: 'asc' | 'desc'): SingleSelectBuilder<T>;
    offset(n: number): SingleSelectBuilder<T>;
    toSQL(): {
        sql: string;
        params: unknown[];
    };
    /** Returns a single row or null, never throws on empty results. */
    execute(): Promise<InferRow<T> | null>;
}
/**
 * Narrowed single-row SELECT builder — after `.single()` on a `NarrowedSelectBuilder`.
 * Returns `NarrowRow<InferRow<T>, C> | null` from `execute()`.
 */
export declare class NarrowedSingleSelectBuilder<T extends AnyTable, C extends keyof InferRow<T>> implements Executable {
    #private;
    constructor(executor: Executor, tableName: string, table: T, conditions: Condition[], selectedColumns: C[], orderByClauses: {
        column: ColumnDef<any, any>;
        direction: 'asc' | 'desc';
    }[], offsetValue: number | null, distinct: boolean);
    where(condition: Condition): NarrowedSingleSelectBuilder<T, C>;
    orderBy<K extends keyof InferRow<T>>(key: K, direction?: 'asc' | 'desc'): NarrowedSingleSelectBuilder<T, C>;
    offset(n: number): NarrowedSingleSelectBuilder<T, C>;
    toSQL(): {
        sql: string;
        params: unknown[];
    };
    /** Returns a single narrowed row or null. */
    execute(): Promise<Prettify<NarrowRow<InferRow<T>, C>> | null>;
}
/** Phase 1 of a JOIN — only `.on()` is available. */
export interface JoinSelectStage1<Parent extends AnyTable> {
    on<Child extends AnyTable>(child: Child, condition: Condition): JoinBuilder<Parent, [Child]>;
    /** Auto-join: infer condition from foreign key references. */
    on<Child extends AnyTable>(child: Child): JoinBuilder<Parent, [Child]>;
}
/** Full join builder — chain more `.on()` calls or call `.execute()`. */
export interface JoinBuilder<Parent extends AnyTable, Joined extends AnyTable[], ParentCols extends keyof InferRow<Parent> = keyof InferRow<Parent>> {
    on<NewChild extends AnyTable>(child: NewChild, condition: Condition): JoinBuilder<Parent, [...Joined, NewChild], ParentCols>;
    /** Auto-join: infer condition from foreign key references. */
    on<NewChild extends AnyTable>(child: NewChild): JoinBuilder<Parent, [...Joined, NewChild], ParentCols>;
    columns<K extends keyof InferRow<Parent>>(keys: K[]): JoinBuilder<Parent, Joined, K>;
    where(condition: Condition): JoinBuilder<Parent, Joined, ParentCols>;
    orderBy<K extends keyof InferRow<Parent>>(key: K, direction?: 'asc' | 'desc'): JoinBuilder<Parent, Joined, ParentCols>;
    limit(n: number): JoinBuilder<Parent, Joined, ParentCols>;
    offset(n: number): JoinBuilder<Parent, Joined, ParentCols>;
    single(): SingleJoinBuilder<Parent, Joined, ParentCols>;
    toSQL(): {
        sql: string;
        params: unknown[];
    };
    execute(): Promise<JoinResult<Parent, Joined, ParentCols>[]>;
}
/** The result type for joined queries. Parent fields are narrowed by `.columns()`; each joined table's data is nested under its table name. */
export type JoinResult<Parent extends AnyTable, _Joined extends AnyTable[], ParentCols extends keyof InferRow<Parent> = keyof InferRow<Parent>> = Prettify<Pick<InferRow<Parent>, ParentCols>> & Record<string, unknown>;
/** Phase 1 of an INSERT — only `.values()` is available. */
export interface InsertStage1<T extends AnyTable> {
    values(row: InsertRow<T>): InsertBuilder<T>;
    values(rows: InsertRow<T>[]): InsertBuilder<T>;
}
type OnConflictDoUpdate<T extends AnyTable> = {
    mode: 'update';
    target: ColumnDef<any, any> | ColumnDef<any, any>[];
    set: Partial<InferRow<T>>;
};
type OnConflictStrategy<T extends AnyTable> = OnConflictDoNothing | OnConflictDoUpdate<T>;
/** Full INSERT builder — available after `.values()` has been called. */
export declare class InsertBuilder<T extends AnyTable, R extends boolean = false, K extends keyof InferRow<T> = keyof InferRow<T>> implements Executable {
    #private;
    constructor(executor: Executor, tableName: string, table: T, rowOrRows: InsertRow<T> | InsertRow<T>[], returning?: boolean | K[], onConflict?: OnConflictStrategy<T>);
    /**
     * Return the inserted row(s) instead of void.
     * Pass an array of column names to narrow the result shape.
     *
     * @example
     * db.insert(users).values({ id: "u1", name: "Alice" }).returning()
     * db.insert(users).values({ id: "u1", name: "Alice" }).returning(["id", "name"])
     */
    returning(): InsertBuilder<T, true>;
    returning<NewK extends keyof InferRow<T>>(keys: NewK[]): InsertBuilder<T, true, NewK>;
    /**
     * On conflict, do nothing (ignore the insert).
     *
     * @example
     * db.insert(users).values(row).onConflictDoNothing()
     */
    onConflictDoNothing(): InsertBuilder<T, R, K>;
    /**
     * On conflict, update specified columns with the proposed values.
     *
     * @example
     * db.insert(users).values(row).onConflictDoUpdate({
     *   target: users.id,
     *   set: { name: "Alice" },
     * })
     */
    onConflictDoUpdate<C extends ColumnDef<any, any>>(options: {
        target: C | C[];
        set: Partial<InferRow<T>>;
    }): InsertBuilder<T, R, K>;
    toSQL(): {
        sql: string;
        params: unknown[];
    };
    execute(): Promise<R extends true ? Prettify<NarrowRow<InferRow<T>, K>>[] : {
        rowsAffected: number;
    }>;
}
/** Phase 1 of an UPDATE — only `.set()` is available. */
export interface UpdateStage1<T extends AnyTable> {
    set(partial: Partial<InferRow<T>>): UpdateBuilder<T>;
}
/** Full UPDATE builder — available after `.set()` has been called. */
export declare class UpdateBuilder<T extends AnyTable, R extends boolean = false, K extends keyof InferRow<T> = keyof InferRow<T>> implements Executable {
    #private;
    constructor(executor: Executor, tableName: string, table: T, set: Partial<InferRow<T>>, conditions?: Condition[], returning?: boolean | K[]);
    set(partial: Partial<InferRow<T>>): UpdateBuilder<T, R, K>;
    where(condition: Condition): UpdateBuilder<T, R, K>;
    /**
     * Return the updated row(s) instead of void.
     * Pass an array of column names to narrow the result shape.
     *
     * @example
     * db.update(users).set({ name: "Bob" }).where(eq(users.id, "u1")).returning()
     * db.update(users).set({ name: "Bob" }).where(eq(users.id, "u1")).returning(["id", "name"])
     */
    returning(): UpdateBuilder<T, true>;
    returning<NewK extends keyof InferRow<T>>(keys: NewK[]): UpdateBuilder<T, true, NewK>;
    toSQL(): {
        sql: string;
        params: unknown[];
    };
    execute(): Promise<R extends true ? Prettify<NarrowRow<InferRow<T>, K>>[] : {
        rowsAffected: number;
    }>;
}
/** Full DELETE builder — chain `.where()` calls then `.execute()`. */
export declare class DeleteBuilder<T extends AnyTable, R extends boolean = false, K extends keyof InferRow<T> = keyof InferRow<T>> implements Executable {
    #private;
    constructor(executor: Executor, tableName: string, table: T, conditions?: Condition[], returning?: boolean | K[]);
    where(condition: Condition): DeleteBuilder<T, R, K>;
    /**
     * Return the deleted row(s) instead of void.
     * Pass an array of column names to narrow the result shape.
     *
     * @example
     * db.delete(users).where(eq(users.id, "u1")).returning()
     * db.delete(users).where(eq(users.id, "u1")).returning(["id", "name"])
     */
    returning(): DeleteBuilder<T, true>;
    returning<NewK extends keyof InferRow<T>>(keys: NewK[]): DeleteBuilder<T, true, NewK>;
    toSQL(): {
        sql: string;
        params: unknown[];
    };
    execute(): Promise<R extends true ? Prettify<NarrowRow<InferRow<T>, K>>[] : {
        rowsAffected: number;
    }>;
}
export {};
