package {{ package_name }}.client;

{%- for import in imports %}
import {{ import }};
{%- endfor %}

public final class {{ name }} extends AbstractDelegate<{{ model_name }}> {
    private static final int DEFAULT_STREAM_CHUNK_SIZE = 128;

    public {{ name }}(RpcCaller client) {
        super(client, "{{ model_name }}");
    }

    private CrudEventContext eventContext(
        String operation,
        EventPhase phase,
        Map<String, Object> args,
        ObjectNode payload,
        Map<String, Object> state,
        Object result,
        Throwable error
    ) {
        return new CrudEventContext(
            client(),
            {{ model_name }}.class,
            "{{ model_name }}",
            operation,
            phase,
            args,
            payload,
            result,
            error,
            transactionId(),
            state
        );
    }

{% if is_async %}
    public CompletableFuture<List<{{ model_name }}>> findMany() {
        return async(() -> findManyInternal(new {{ dsl_name }}.FindManyArgs()));
    }

    public CompletableFuture<List<{{ model_name }}>> findMany(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return findManyInternal(args);
        });
    }

    public CompletableFuture<List<{{ model_name }}>> findMany({{ dsl_name }}.FindManyArgs args) {
        return async(() -> findManyInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args));
    }

    public CompletableFuture<List<{{ projection_name }}>> findManySelect(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return findManySelect(spec, Function.identity());
    }

    public <R> CompletableFuture<List<R>> findManySelect(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return findManySelectInternal(args, mapper);
        });
    }

    public CompletableFuture<List<{{ projection_name }}>> findManySelect({{ dsl_name }}.FindManyArgs args) {
        return findManySelect(args, Function.identity());
    }

    public <R> CompletableFuture<List<R>> findManySelect(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        return async(() -> findManySelectInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args, mapper));
    }

    public CompletableFuture<List<JsonNode>> findManySelectRaw(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return findManySelectRawInternal(args);
        });
    }

    public CompletableFuture<List<JsonNode>> findManySelectRaw({{ dsl_name }}.FindManyArgs args) {
        return async(() -> findManySelectRawInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args));
    }

    public CompletableFuture<{{ model_name }}> findFirst(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return findFirstInternal(args);
        });
    }

    public CompletableFuture<{{ projection_name }}> findFirstSelect(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return findFirstSelect(spec, Function.identity());
    }

    public <R> CompletableFuture<R> findFirstSelect(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return findFirstSelectInternal(args, mapper);
        });
    }

    public CompletableFuture<{{ projection_name }}> findFirstSelect({{ dsl_name }}.FindManyArgs args) {
        return findFirstSelect(args, Function.identity());
    }

    public <R> CompletableFuture<R> findFirstSelect(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        return async(() -> findFirstSelectInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args, mapper));
    }

    public CompletableFuture<JsonNode> findFirstSelectRaw(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return findFirstSelectRawInternal(args);
        });
    }

    public CompletableFuture<JsonNode> findFirstSelectRaw({{ dsl_name }}.FindManyArgs args) {
        return async(() -> findFirstSelectRawInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args));
    }

    public CompletableFuture<{{ model_name }}> findUnique(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return findUniqueInternal(args);
        });
    }

    public CompletableFuture<{{ projection_name }}> findUniqueSelect(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return findUniqueSelect(spec, Function.identity());
    }

    public <R> CompletableFuture<R> findUniqueSelect(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return findUniqueSelectInternal(args, mapper);
        });
    }

    public CompletableFuture<{{ projection_name }}> findUniqueSelect({{ dsl_name }}.FindManyArgs args) {
        return findUniqueSelect(args, Function.identity());
    }

    public <R> CompletableFuture<R> findUniqueSelect(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        return async(() -> findUniqueSelectInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args, mapper));
    }

    public CompletableFuture<JsonNode> findUniqueSelectRaw(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return findUniqueSelectRawInternal(args);
        });
    }

    public CompletableFuture<JsonNode> findUniqueSelectRaw({{ dsl_name }}.FindManyArgs args) {
        return async(() -> findUniqueSelectRawInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args));
    }

    public CompletableFuture<{{ model_name }}> findFirstOrThrow(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return async(() -> {
            {{ model_name }} record = findFirst(spec).join();
            if (record == null) {
                throw new NotFoundException("findFirstOrThrow: no {{ model_name }} record found matching the given filter");
            }
            return record;
        });
    }

    public CompletableFuture<{{ projection_name }}> findFirstSelectOrThrow(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return findFirstSelectOrThrow(spec, Function.identity());
    }

    public <R> CompletableFuture<R> findFirstSelectOrThrow(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            R record = findFirstSelectInternal(args, mapper);
            if (record == null) {
                throw new NotFoundException("findFirstSelectOrThrow: no {{ model_name }} record found matching the given filter");
            }
            return record;
        });
    }

    public CompletableFuture<{{ model_name }}> findUniqueOrThrow(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return async(() -> {
            {{ model_name }} record = findUnique(spec).join();
            if (record == null) {
                throw new NotFoundException("findUniqueOrThrow: no {{ model_name }} record found matching the given filter");
            }
            return record;
        });
    }

    public CompletableFuture<{{ projection_name }}> findUniqueSelectOrThrow(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return findUniqueSelectOrThrow(spec, Function.identity());
    }

    public <R> CompletableFuture<R> findUniqueSelectOrThrow(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        return async(() -> {
            {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
            if (spec != null) {
                spec.accept(args);
            }
            R record = findUniqueSelectInternal(args, mapper);
            if (record == null) {
                throw new NotFoundException("findUniqueSelectOrThrow: no {{ model_name }} record found matching the given filter");
            }
            return record;
        });
    }

    public CompletableFuture<{{ model_name }}> create(Consumer<{{ dsl_name }}.CreateInput> spec) {
        return async(() -> {
            {{ dsl_name }}.CreateInput input = new {{ dsl_name }}.CreateInput();
            if (spec != null) {
                spec.accept(input);
            }
            return createInternal(input);
        });
    }

    public CompletableFuture<{{ model_name }}> create({{ dsl_name }}.CreateInput data) {
        return async(() -> createInternal(data == null ? new {{ dsl_name }}.CreateInput() : data));
    }

    public CompletableFuture<List<{{ model_name }}>> createMany(List<{{ dsl_name }}.CreateInput> data) {
        return async(() -> createManyInternal(data));
    }

    public CompletableFuture<List<{{ model_name }}>> update(Consumer<{{ dsl_name }}.UpdateArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.UpdateArgs args = new {{ dsl_name }}.UpdateArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return updateInternal(args);
        });
    }

    public CompletableFuture<{{ model_name }}> delete(Consumer<{{ dsl_name }}.DeleteArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.DeleteArgs args = new {{ dsl_name }}.DeleteArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return deleteInternal(args);
        });
    }

    public CompletableFuture<Long> deleteMany(Consumer<{{ dsl_name }}.DeleteArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.DeleteArgs args = new {{ dsl_name }}.DeleteArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return deleteManyInternal(args);
        });
    }

    public CompletableFuture<Long> count() {
        return async(() -> countInternal(new {{ dsl_name }}.CountArgs()));
    }

    public CompletableFuture<Long> count(Consumer<{{ dsl_name }}.CountArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.CountArgs args = new {{ dsl_name }}.CountArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return countInternal(args);
        });
    }

    public CompletableFuture<{{ model_name }}> upsert(Consumer<{{ dsl_name }}.UpsertArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.UpsertArgs args = new {{ dsl_name }}.UpsertArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return upsertInternal(args);
        });
    }

    public CompletableFuture<List<JsonNode>> groupBy(Consumer<{{ dsl_name }}.GroupByArgs> spec) {
        return async(() -> {
            {{ dsl_name }}.GroupByArgs args = new {{ dsl_name }}.GroupByArgs();
            if (spec != null) {
                spec.accept(args);
            }
            return groupByInternal(args);
        });
    }

    public CompletableFuture<List<JsonNode>> rawQuery(String sql) {
        return async(() -> rawQueryInternal(sql));
    }

    public CompletableFuture<List<JsonNode>> rawStmtQuery(String sql, List<?> params) {
        return async(() -> rawStmtQueryInternal(sql, params));
    }

{% else %}
    public List<{{ model_name }}> findMany() {
        return findMany(new {{ dsl_name }}.FindManyArgs());
    }

    public List<{{ model_name }}> findMany(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return findMany(args);
    }

    public List<{{ model_name }}> findMany({{ dsl_name }}.FindManyArgs args) {
        return findManyInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args);
    }

    public List<{{ projection_name }}> findManySelect(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return findManySelect(spec, Function.identity());
    }

    public <R> List<R> findManySelect(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return findManySelectInternal(args, mapper);
    }

    public List<{{ projection_name }}> findManySelect({{ dsl_name }}.FindManyArgs args) {
        return findManySelect(args, Function.identity());
    }

    public <R> List<R> findManySelect(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        return findManySelectInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args, mapper);
    }

    public List<JsonNode> findManySelectRaw(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return findManySelectRawInternal(args);
    }

    public List<JsonNode> findManySelectRaw({{ dsl_name }}.FindManyArgs args) {
        return findManySelectRawInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args);
    }

    public {{ model_name }} findFirst(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return findFirstInternal(args);
    }

    public {{ projection_name }} findFirstSelect(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return findFirstSelect(spec, Function.identity());
    }

    public <R> R findFirstSelect(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return findFirstSelectInternal(args, mapper);
    }

    public {{ projection_name }} findFirstSelect({{ dsl_name }}.FindManyArgs args) {
        return findFirstSelect(args, Function.identity());
    }

    public <R> R findFirstSelect(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        return findFirstSelectInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args, mapper);
    }

    public JsonNode findFirstSelectRaw(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return findFirstSelectRawInternal(args);
    }

    public JsonNode findFirstSelectRaw({{ dsl_name }}.FindManyArgs args) {
        return findFirstSelectRawInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args);
    }

    public {{ model_name }} findUnique(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return findUniqueInternal(args);
    }

    public {{ projection_name }} findUniqueSelect(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return findUniqueSelect(spec, Function.identity());
    }

    public <R> R findUniqueSelect(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return findUniqueSelectInternal(args, mapper);
    }

    public {{ projection_name }} findUniqueSelect({{ dsl_name }}.FindManyArgs args) {
        return findUniqueSelect(args, Function.identity());
    }

    public <R> R findUniqueSelect(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        return findUniqueSelectInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args, mapper);
    }

    public JsonNode findUniqueSelectRaw(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return findUniqueSelectRawInternal(args);
    }

    public JsonNode findUniqueSelectRaw({{ dsl_name }}.FindManyArgs args) {
        return findUniqueSelectRawInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args);
    }

    public {{ model_name }} findFirstOrThrow(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        {{ model_name }} record = findFirst(spec);
        if (record == null) {
            throw new NotFoundException("findFirstOrThrow: no {{ model_name }} record found matching the given filter");
        }
        return record;
    }

    public {{ projection_name }} findFirstSelectOrThrow(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return findFirstSelectOrThrow(spec, Function.identity());
    }

    public <R> R findFirstSelectOrThrow(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        R record = findFirstSelect(spec, mapper);
        if (record == null) {
            throw new NotFoundException("findFirstSelectOrThrow: no {{ model_name }} record found matching the given filter");
        }
        return record;
    }

    public {{ model_name }} findUniqueOrThrow(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        {{ model_name }} record = findUnique(spec);
        if (record == null) {
            throw new NotFoundException("findUniqueOrThrow: no {{ model_name }} record found matching the given filter");
        }
        return record;
    }

    public {{ projection_name }} findUniqueSelectOrThrow(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return findUniqueSelectOrThrow(spec, Function.identity());
    }

    public <R> R findUniqueSelectOrThrow(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        R record = findUniqueSelect(spec, mapper);
        if (record == null) {
            throw new NotFoundException("findUniqueSelectOrThrow: no {{ model_name }} record found matching the given filter");
        }
        return record;
    }

    public {{ model_name }} create(Consumer<{{ dsl_name }}.CreateInput> spec) {
        {{ dsl_name }}.CreateInput input = new {{ dsl_name }}.CreateInput();
        if (spec != null) {
            spec.accept(input);
        }
        return createInternal(input);
    }

    public {{ model_name }} create({{ dsl_name }}.CreateInput data) {
        return createInternal(data == null ? new {{ dsl_name }}.CreateInput() : data);
    }

    public List<{{ model_name }}> createMany(List<{{ dsl_name }}.CreateInput> data) {
        return createManyInternal(data);
    }

    public List<{{ model_name }}> update(Consumer<{{ dsl_name }}.UpdateArgs> spec) {
        {{ dsl_name }}.UpdateArgs args = new {{ dsl_name }}.UpdateArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return updateInternal(args);
    }

    public {{ model_name }} delete(Consumer<{{ dsl_name }}.DeleteArgs> spec) {
        {{ dsl_name }}.DeleteArgs args = new {{ dsl_name }}.DeleteArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return deleteInternal(args);
    }

    public long deleteMany(Consumer<{{ dsl_name }}.DeleteArgs> spec) {
        {{ dsl_name }}.DeleteArgs args = new {{ dsl_name }}.DeleteArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return deleteManyInternal(args);
    }

    public long count() {
        return countInternal(new {{ dsl_name }}.CountArgs());
    }

    public long count(Consumer<{{ dsl_name }}.CountArgs> spec) {
        {{ dsl_name }}.CountArgs args = new {{ dsl_name }}.CountArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return countInternal(args);
    }

    public {{ model_name }} upsert(Consumer<{{ dsl_name }}.UpsertArgs> spec) {
        {{ dsl_name }}.UpsertArgs args = new {{ dsl_name }}.UpsertArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return upsertInternal(args);
    }

    public List<JsonNode> groupBy(Consumer<{{ dsl_name }}.GroupByArgs> spec) {
        {{ dsl_name }}.GroupByArgs args = new {{ dsl_name }}.GroupByArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return groupByInternal(args);
    }

    public List<JsonNode> rawQuery(String sql) {
        return rawQueryInternal(sql);
    }

    public List<JsonNode> rawStmtQuery(String sql, List<?> params) {
        return rawStmtQueryInternal(sql, params);
    }

{% endif %}
    /**
     * Stream records incrementally from the engine.
     *
     * Prefer {@code findMany(...)} when the caller naturally wants a final
     * {@code List<{{ model_name }}>}, such as small pages or relation-heavy
     * reads. Prefer {@code streamMany(...)} for exports, scans, and early-exit
     * consumers that should avoid accumulating every row in memory first.
     *
     * Close the returned stream early, ideally via try-with-resources, to
     * propagate cancellation promptly to the engine.
     */
    public Stream<{{ model_name }}> streamMany() {
        return streamMany(new {{ dsl_name }}.FindManyArgs());
    }

    public Stream<{{ model_name }}> streamMany(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return streamMany(args);
    }

    public Stream<{{ model_name }}> streamMany({{ dsl_name }}.FindManyArgs args) {
        return streamManyInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args);
    }

    public Stream<{{ projection_name }}> streamManySelect(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        return streamManySelect(spec, Function.identity());
    }

    public <R> Stream<R> streamManySelect(
        Consumer<{{ dsl_name }}.FindManyArgs> spec,
        Function<{{ projection_name }}, R> mapper
    ) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return streamManySelect(args, mapper);
    }

    public Stream<{{ projection_name }}> streamManySelect({{ dsl_name }}.FindManyArgs args) {
        return streamManySelect(args, Function.identity());
    }

    public <R> Stream<R> streamManySelect(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        return streamManySelectInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args, mapper);
    }

    public Stream<JsonNode> streamManySelectRaw(Consumer<{{ dsl_name }}.FindManyArgs> spec) {
        {{ dsl_name }}.FindManyArgs args = new {{ dsl_name }}.FindManyArgs();
        if (spec != null) {
            spec.accept(args);
        }
        return streamManySelectRaw(args);
    }

    public Stream<JsonNode> streamManySelectRaw({{ dsl_name }}.FindManyArgs args) {
        return streamManySelectRawInternal(args == null ? new {{ dsl_name }}.FindManyArgs() : args);
    }

    private ObjectNode buildFindManyRequest({{ dsl_name }}.FindManyArgs args) {
        {{ dsl_name }}.FindManyArgs actual = args == null ? new {{ dsl_name }}.FindManyArgs() : args;
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        request.set("args", actual.node());
        if (actual.chunkSize() != null) {
            request.put("chunkSize", actual.chunkSize().intValue());
        }
        return request;
    }

    private void rejectSelectForModelResult({{ dsl_name }}.FindManyArgs args) {
        {{ dsl_name }}.FindManyArgs actual = args == null ? new {{ dsl_name }}.FindManyArgs() : args;
        if (actual.node().has("select")) {
            throw new IllegalArgumentException(
                "select returns partial rows and cannot be decoded as a full {{ model_name }} record; use findManySelect, findFirstSelect, or findUniqueSelect instead"
            );
        }
    }

    private void requireSelectForProjection({{ dsl_name }}.FindManyArgs args) {
        {{ dsl_name }}.FindManyArgs actual = args == null ? new {{ dsl_name }}.FindManyArgs() : args;
        if (!actual.node().has("select")) {
            throw new IllegalArgumentException(
                "select projection APIs require select(...); use findMany/findFirst/findUnique for full {{ model_name }} records"
            );
        }
    }

    private JsonNode rawProjectionRow(JsonNode row) {
        if (row == null || row.isNull()) {
            return null;
        }
        return row.deepCopy();
    }

    private <R> R mapProjectionRow(JsonNode row, Function<{{ projection_name }}, R> mapper) {
        {{ projection_name }} projection = {{ projection_name }}.fromJsonNode(row);
        if (projection == null) {
            return null;
        }
        Function<{{ projection_name }}, R> actualMapper = Objects.requireNonNull(mapper, "mapper");
        return actualMapper.apply(projection);
    }

    private List<{{ model_name }}> findManyInternal({{ dsl_name }}.FindManyArgs args) {
        rejectSelectForModelResult(args);
        ObjectNode request = buildFindManyRequest(args);
        JsonNode result = rpc("query.findMany", request);
        return rows(result, {{ model_name }}::fromJsonNode);
    }

    private <R> List<R> findManySelectInternal(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        requireSelectForProjection(args);
        Function<{{ projection_name }}, R> actualMapper = Objects.requireNonNull(mapper, "mapper");
        ObjectNode request = buildFindManyRequest(args);
        JsonNode result = rpc("query.findMany", request);
        return rows(result, row -> actualMapper.apply({{ projection_name }}.fromJsonNode(row)));
    }

    private List<JsonNode> findManySelectRawInternal({{ dsl_name }}.FindManyArgs args) {
        requireSelectForProjection(args);
        ObjectNode request = buildFindManyRequest(args);
        JsonNode result = rpc("query.findMany", request);
        return rows(result, JsonNode::deepCopy);
    }

    private Stream<{{ model_name }}> streamManyInternal({{ dsl_name }}.FindManyArgs args) {
        rejectSelectForModelResult(args);
        Integer configuredChunkSize = args == null ? null : args.chunkSize();
        int chunkSize = configuredChunkSize == null
            ? DEFAULT_STREAM_CHUNK_SIZE
            : configuredChunkSize.intValue();
        if (chunkSize < 1) {
            throw new IllegalArgumentException("streamMany chunkSize must be a positive integer");
        }

        ObjectNode request = buildFindManyRequest(args);
        request.put("chunkSize", chunkSize);
        return rows(streamRpc("query.findMany", request), {{ model_name }}::fromJsonNode);
    }

    private <R> Stream<R> streamManySelectInternal(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        requireSelectForProjection(args);
        Function<{{ projection_name }}, R> actualMapper = Objects.requireNonNull(mapper, "mapper");
        Integer configuredChunkSize = args == null ? null : args.chunkSize();
        int chunkSize = configuredChunkSize == null
            ? DEFAULT_STREAM_CHUNK_SIZE
            : configuredChunkSize.intValue();
        if (chunkSize < 1) {
            throw new IllegalArgumentException("streamManySelect chunkSize must be a positive integer");
        }

        ObjectNode request = buildFindManyRequest(args);
        request.put("chunkSize", chunkSize);
        return rows(streamRpc("query.findMany", request), row -> actualMapper.apply({{ projection_name }}.fromJsonNode(row)));
    }

    private Stream<JsonNode> streamManySelectRawInternal({{ dsl_name }}.FindManyArgs args) {
        requireSelectForProjection(args);
        Integer configuredChunkSize = args == null ? null : args.chunkSize();
        int chunkSize = configuredChunkSize == null
            ? DEFAULT_STREAM_CHUNK_SIZE
            : configuredChunkSize.intValue();
        if (chunkSize < 1) {
            throw new IllegalArgumentException("streamManySelectRaw chunkSize must be a positive integer");
        }

        ObjectNode request = buildFindManyRequest(args);
        request.put("chunkSize", chunkSize);
        return rows(streamRpc("query.findMany", request), JsonNode::deepCopy);
    }

    private {{ model_name }} findFirstInternal({{ dsl_name }}.FindManyArgs args) {
        rejectSelectForModelResult(args);
        {{ dsl_name }}.FindManyArgs actual = args == null ? new {{ dsl_name }}.FindManyArgs() : args;
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        ObjectNode requestArgs = actual.node();
        requestArgs.put("take", 1);
        request.set("args", requestArgs);
        JsonNode result = rpc("query.findFirst", request);
        JsonNode row = JsonSupport.firstDataRow(result);
        return row == null || row.isNull() ? null : {{ model_name }}.fromJsonNode(row);
    }

    private <R> R findFirstSelectInternal(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        requireSelectForProjection(args);
        {{ dsl_name }}.FindManyArgs actual = args == null ? new {{ dsl_name }}.FindManyArgs() : args;
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        ObjectNode requestArgs = actual.node();
        requestArgs.put("take", 1);
        request.set("args", requestArgs);
        JsonNode result = rpc("query.findFirst", request);
        return mapProjectionRow(JsonSupport.firstDataRow(result), mapper);
    }

    private JsonNode findFirstSelectRawInternal({{ dsl_name }}.FindManyArgs args) {
        requireSelectForProjection(args);
        {{ dsl_name }}.FindManyArgs actual = args == null ? new {{ dsl_name }}.FindManyArgs() : args;
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        ObjectNode requestArgs = actual.node();
        requestArgs.put("take", 1);
        request.set("args", requestArgs);
        JsonNode result = rpc("query.findFirst", request);
        return rawProjectionRow(JsonSupport.firstDataRow(result));
    }

    private {{ model_name }} findUniqueInternal({{ dsl_name }}.FindManyArgs args) {
        rejectSelectForModelResult(args);
        {{ dsl_name }}.FindManyArgs actual = args == null ? new {{ dsl_name }}.FindManyArgs() : args;
        ObjectNode node = actual.node();
        if (node.size() == 1 && node.has("where")) {
            ObjectNode request = JsonSupport.object();
            request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
            request.put("model", "{{ model_name }}");
            request.set("filter", actual.whereNode());
            JsonNode result = rpc("query.findUnique", request);
            JsonNode row = JsonSupport.firstDataRow(result);
            return row == null || row.isNull() ? null : {{ model_name }}.fromJsonNode(row);
        }
        return findFirstInternal(actual);
    }

    private <R> R findUniqueSelectInternal(
        {{ dsl_name }}.FindManyArgs args,
        Function<{{ projection_name }}, R> mapper
    ) {
        return findFirstSelectInternal(args, mapper);
    }

    private JsonNode findUniqueSelectRawInternal({{ dsl_name }}.FindManyArgs args) {
        return findFirstSelectRawInternal(args);
    }

    private {{ model_name }} createInternal({{ dsl_name }}.CreateInput data) {
        Map<String, Object> eventArgs = new HashMap<>();
        eventArgs.put("data", data);
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        request.set("data", data == null ? JsonSupport.object() : data.node());
        request.put("returnData", true);
        Map<String, Object> state = new HashMap<>();
        try {
            StopPropagation stop = events().run(eventContext("create", EventPhase.BEFORE, eventArgs, request, state, null, null));
            if (stop != null) {
                return ({{ model_name }}) stop.resolve(null);
            }
            JsonNode result = rpc("query.create", request);
            JsonNode row = JsonSupport.firstDataRow(result);
            if (row == null || row.isNull()) {
                throw new NautilusException("create: engine returned no data");
            }
            {{ model_name }} decoded = {{ model_name }}.fromJsonNode(row);
            stop = events().run(eventContext("create", EventPhase.AFTER, eventArgs, request, state, decoded, null));
            if (stop != null) {
                return ({{ model_name }}) stop.resolve(null);
            }
            return decoded;
        } catch (RuntimeException error) {
            events().run(eventContext("create", EventPhase.ERROR, eventArgs, request, state, null, error), false);
            throw error;
        }
    }

    private List<{{ model_name }}> createManyInternal(List<{{ dsl_name }}.CreateInput> data) {
        Map<String, Object> eventArgs = new HashMap<>();
        eventArgs.put("data", data);
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        ArrayNode items = JsonSupport.array();
        for ({{ dsl_name }}.CreateInput item : data) {
            items.add(item.node());
        }
        request.set("data", items);
        request.put("returnData", true);
        Map<String, Object> state = new HashMap<>();
        try {
            StopPropagation stop = events().run(eventContext("createMany", EventPhase.BEFORE, eventArgs, request, state, null, null));
            if (stop != null) {
                return (List<{{ model_name }}>) stop.resolve(List.of());
            }
            JsonNode result = rpc("query.createMany", request);
            List<{{ model_name }}> decoded = rows(result, {{ model_name }}::fromJsonNode);
            stop = events().run(eventContext("createMany", EventPhase.AFTER, eventArgs, request, state, decoded, null));
            if (stop != null) {
                return (List<{{ model_name }}>) stop.resolve(List.of());
            }
            return decoded;
        } catch (RuntimeException error) {
            events().run(eventContext("createMany", EventPhase.ERROR, eventArgs, request, state, null, error), false);
            throw error;
        }
    }

    private List<{{ model_name }}> updateInternal({{ dsl_name }}.UpdateArgs args) {
        Map<String, Object> eventArgs = new HashMap<>();
        eventArgs.put("where", args == null ? null : args.whereNode());
        eventArgs.put("data", args == null ? null : args.dataNode());
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        request.set("filter", args == null ? JsonSupport.object() : args.whereNode());
        request.set("data", args == null ? JsonSupport.object() : args.dataNode());
        request.put("returnData", true);
        Map<String, Object> state = new HashMap<>();
        try {
            StopPropagation stop = events().run(eventContext("update", EventPhase.BEFORE, eventArgs, request, state, null, null));
            if (stop != null) {
                return (List<{{ model_name }}>) stop.resolve(List.of());
            }
            JsonNode result = rpc("query.update", request);
            List<{{ model_name }}> decoded = rows(result, {{ model_name }}::fromJsonNode);
            stop = events().run(eventContext("update", EventPhase.AFTER, eventArgs, request, state, decoded, null));
            if (stop != null) {
                return (List<{{ model_name }}>) stop.resolve(List.of());
            }
            return decoded;
        } catch (RuntimeException error) {
            events().run(eventContext("update", EventPhase.ERROR, eventArgs, request, state, null, error), false);
            throw error;
        }
    }

    private {{ model_name }} deleteInternal({{ dsl_name }}.DeleteArgs args) {
        Map<String, Object> eventArgs = new HashMap<>();
        eventArgs.put("where", args == null ? null : args.whereNode());
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        request.set("filter", args == null ? JsonSupport.object() : args.whereNode());
        request.put("returnData", true);
        Map<String, Object> state = new HashMap<>();
        try {
            StopPropagation stop = events().run(eventContext("delete", EventPhase.BEFORE, eventArgs, request, state, null, null));
            if (stop != null) {
                return ({{ model_name }}) stop.resolve(null);
            }
            JsonNode result = rpc("query.delete", request);
            JsonNode row = JsonSupport.firstDataRow(result);
            if (row == null || row.isNull()) {
                throw new NotFoundException("delete: no {{ model_name }} record found matching the given filter");
            }
            {{ model_name }} decoded = {{ model_name }}.fromJsonNode(row);
            stop = events().run(eventContext("delete", EventPhase.AFTER, eventArgs, request, state, decoded, null));
            if (stop != null) {
                return ({{ model_name }}) stop.resolve(null);
            }
            return decoded;
        } catch (RuntimeException error) {
            events().run(eventContext("delete", EventPhase.ERROR, eventArgs, request, state, null, error), false);
            throw error;
        }
    }

    private long deleteManyInternal({{ dsl_name }}.DeleteArgs args) {
        Map<String, Object> eventArgs = new HashMap<>();
        eventArgs.put("where", args == null ? null : args.whereNode());
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        request.set("filter", args == null ? JsonSupport.object() : args.whereNode());
        request.put("returnData", false);
        Map<String, Object> state = new HashMap<>();
        try {
            StopPropagation stop = events().run(eventContext("deleteMany", EventPhase.BEFORE, eventArgs, request, state, null, null));
            if (stop != null) {
                Object stopped = stop.resolve(0L);
                return stopped instanceof Number number ? number.longValue() : 0L;
            }
            JsonNode result = rpc("query.delete", request);
            long decoded = JsonSupport.count(result);
            stop = events().run(eventContext("deleteMany", EventPhase.AFTER, eventArgs, request, state, decoded, null));
            if (stop != null) {
                Object stopped = stop.resolve(0L);
                return stopped instanceof Number number ? number.longValue() : 0L;
            }
            return decoded;
        } catch (RuntimeException error) {
            events().run(eventContext("deleteMany", EventPhase.ERROR, eventArgs, request, state, null, error), false);
            throw error;
        }
    }

    private long countInternal({{ dsl_name }}.CountArgs args) {
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        request.set("args", args == null ? JsonSupport.object() : args.node());
        JsonNode result = rpc("query.count", request);
        return JsonSupport.count(result);
    }

    private {{ model_name }} upsertInternal({{ dsl_name }}.UpsertArgs args) {
        List<{{ model_name }}> existing = findManyInternal(new {{ dsl_name }}.FindManyArgs().where(w -> w.raw(args.whereNode())).take(1));
        if (!existing.isEmpty()) {
            List<{{ model_name }}> updated = updateInternal(new {{ dsl_name }}.UpdateArgs().where(w -> w.raw(args.whereNode())).data(args.updateNode()));
            return updated.isEmpty() ? existing.get(0) : updated.get(0);
        }
        return createInternal(new {{ dsl_name }}.CreateInput(args.createNode()));
    }

    private List<JsonNode> groupByInternal({{ dsl_name }}.GroupByArgs args) {
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("model", "{{ model_name }}");
        request.set("args", args == null ? JsonSupport.object() : args.node());
        JsonNode result = rpc("query.groupBy", request);
        return JsonSupport.dataList(result, JsonNode::deepCopy);
    }

    private List<JsonNode> rawQueryInternal(String sql) {
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("sql", sql);
        JsonNode result = rpc("query.rawQuery", request);
        return JsonSupport.dataList(result, JsonNode::deepCopy);
    }

    private List<JsonNode> rawStmtQueryInternal(String sql, List<?> params) {
        ObjectNode request = JsonSupport.object();
        request.put("protocolVersion", JsonSupport.PROTOCOL_VERSION);
        request.put("sql", sql);
        request.set("params", JsonSupport.toJsonNode(params));
        JsonNode result = rpc("query.rawStmtQuery", request);
        return JsonSupport.dataList(result, JsonNode::deepCopy);
    }
}
