"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WhereQueryBuilder = exports.FilterableQueryBuilder = void 0;
const selection_builder_js_1 = require("./selection-builder.js");
/**
 * A base class for query builders that support filtering.
 * It provides the `where` and `orWhere` methods.
 * @template DB - The database type.
 * @template TableName - The name of the table to query.
 */
class FilterableQueryBuilder {
    _executor;
    constructor(node, executor) {
        this._node = node;
        this._executor = executor;
    }
    where(fieldOrFn, operator, value) {
        if (typeof fieldOrFn === 'function') {
            const builder = new WhereQueryBuilder({
                ...this._node,
                filtersSet: { conjunction: 'and', filtersSet: [] },
            }, this._executor);
            const result = fieldOrFn(builder);
            const newNode = {
                ...this._node,
                filtersSet: {
                    ...this._node.filtersSet,
                    filtersSet: [
                        ...this._node.filtersSet.filtersSet,
                        result._node.filtersSet,
                    ],
                },
            };
            // @ts-expect-error cannot instantiate an abstract class
            return new this.constructor(newNode, this._executor);
        }
        if (typeof value === 'function') {
            const selectionBuilder = new selection_builder_js_1.SelectionBuilder(this._executor);
            const initialSubQueryBuilder = selectionBuilder.useLink(fieldOrFn);
            const configuredSubQueryBuilder = value(initialSubQueryBuilder);
            const newFilter = {
                field: fieldOrFn,
                operator: operator,
                value: ['cross-table', configuredSubQueryBuilder._node.filtersSet],
            };
            const newNode = {
                ...this._node,
                filtersSet: {
                    ...this._node.filtersSet,
                    filtersSet: [...this._node.filtersSet.filtersSet, newFilter],
                },
            };
            // @ts-expect-error cannot instantiate an abstract class
            return new this.constructor(newNode, this._executor);
        }
        const newFilter = {
            field: fieldOrFn,
            operator: operator,
            value,
        };
        const newNode = {
            ...this._node,
            filtersSet: {
                ...this._node.filtersSet,
                filtersSet: [...this._node.filtersSet.filtersSet, newFilter],
            },
        };
        // @ts-expect-error cannot instantiate an abstract class
        return new this.constructor(newNode, this._executor);
    }
    orWhere(fieldOrFn, operator, value) {
        // Keeping a basic implementation for orWhere from what was in the file
        const newFilters = this._node.filtersSet.filtersSet;
        if (typeof fieldOrFn === 'function') {
            const builder = new WhereQueryBuilder({
                ...this._node,
                filtersSet: { conjunction: 'and', filtersSet: [] },
            }, this._executor);
            const result = fieldOrFn(builder);
            newFilters.push(result._node.filtersSet);
        }
        else {
            newFilters.push({
                field: fieldOrFn,
                operator: operator,
                value,
            });
        }
        // @ts-expect-error cannot instantiate an abstract class
        return new this.constructor({
            ...this._node,
            filtersSet: {
                conjunction: 'or',
                filtersSet: newFilters,
            },
        }, this._executor);
    }
}
exports.FilterableQueryBuilder = FilterableQueryBuilder;
class WhereQueryBuilder extends FilterableQueryBuilder {
}
exports.WhereQueryBuilder = WhereQueryBuilder;
//# sourceMappingURL=where-query-builder.js.map