/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.ignite.internal.table;

import static java.util.Spliterators.spliteratorUnknownSize;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
import static org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrowsWithCode;
import static org.apache.ignite.internal.testframework.IgniteTestUtils.await;
import static org.apache.ignite.internal.testframework.matchers.TupleMatcher.tupleValue;
import static org.apache.ignite.internal.util.IgniteUtils.closeAll;
import static org.apache.ignite.lang.ErrorGroups.Common.INTERNAL_ERR;
import static org.apache.ignite.lang.ErrorGroups.Sql.STMT_VALIDATION_ERR;
import static org.apache.ignite.lang.util.IgniteNameUtils.quote;
import static org.apache.ignite.table.criteria.Criteria.columnValue;
import static org.apache.ignite.table.criteria.Criteria.equalTo;
import static org.apache.ignite.table.criteria.Criteria.greaterThan;
import static org.apache.ignite.table.criteria.Criteria.greaterThanOrEqualTo;
import static org.apache.ignite.table.criteria.Criteria.in;
import static org.apache.ignite.table.criteria.Criteria.lessThan;
import static org.apache.ignite.table.criteria.Criteria.lessThanOrEqualTo;
import static org.apache.ignite.table.criteria.Criteria.notEqualTo;
import static org.apache.ignite.table.criteria.Criteria.notIn;
import static org.apache.ignite.table.criteria.Criteria.notNullValue;
import static org.apache.ignite.table.criteria.Criteria.nullValue;
import static org.apache.ignite.table.criteria.CriteriaQueryOptions.builder;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.aMapWithSize;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.anEmptyMap;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Spliterator;
import java.util.function.Function;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.apache.ignite.client.IgniteClient;
import org.apache.ignite.internal.ClusterPerClassIntegrationTest;
import org.apache.ignite.internal.lang.IgniteBiTuple;
import org.apache.ignite.lang.AsyncCursor;
import org.apache.ignite.lang.Cursor;
import org.apache.ignite.lang.CursorClosedException;
import org.apache.ignite.lang.ErrorGroups.Common;
import org.apache.ignite.table.Table;
import org.apache.ignite.table.Tuple;
import org.apache.ignite.table.criteria.CriteriaException;
import org.apache.ignite.table.criteria.CriteriaQuerySource;
import org.apache.ignite.table.mapper.Mapper;
import org.apache.ignite.tx.Transaction;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

/**
 * Tests for the criteria query API.
 */
public class ItCriteriaQueryTest extends ClusterPerClassIntegrationTest {
    /** Table name. */
    private static final String TABLE_NAME = "tbl";

    /** Table with quoted name. */
    private static final String QUOTED_TABLE_NAME = quote("TaBleName");

    private static IgniteClient CLIENT;

    /** {@inheritDoc} */
    @Override
    protected int initialNodes() {
        return 1;
    }

    /** {@inheritDoc} */
    @BeforeAll
    @Override
    protected void beforeAll(TestInfo testInfo) {
        super.beforeAll(testInfo);

        CLIENT = IgniteClient.builder()
                .addresses("127.0.0.1:" + CLUSTER.aliveNode().clientAddress().port()).build();

        sql(format("CREATE TABLE {} (id INT PRIMARY KEY, name VARCHAR, salary DOUBLE, hash VARBINARY)", TABLE_NAME));

        insertData(
                TABLE_NAME,
                List.of("ID", "name", "salary", "hash"),
                new Object[]{0, null, 0.0d, "hash0".getBytes()},
                new Object[]{1, "name1", 10.0d, "hash1".getBytes()},
                new Object[]{2, "name2", 20.0d, "hash2".getBytes()}
        );

        sql(format("CREATE TABLE {} (id INT PRIMARY KEY, \"colUmn\" VARCHAR)", QUOTED_TABLE_NAME));

        insertData(
                QUOTED_TABLE_NAME,
                List.of("id", quote("colUmn")),
                new Object[]{0, "name0"},
                new Object[]{1, "name1"},
                new Object[]{2, "name2"}
        );
    }

    @AfterAll
    void stopClient() throws Exception {
        closeAll(CLIENT);
    }

    private static Stream<Arguments> testRecordViewQuery() {
        Table table = CLUSTER.aliveNode().tables().table(TABLE_NAME);
        Table clientTable = CLIENT.tables().table(TABLE_NAME);

        Function<TestObject, Tuple> objMapper = (obj) -> Tuple.create().set("id", obj.id).set("name", obj.name)
                .set("salary", obj.salary).set("hash", obj.hash);

        return Stream.of(
                Arguments.of(table.recordView(), identity()),
                Arguments.of(table.recordView(TestObject.class), objMapper),
                Arguments.of(clientTable.recordView(), identity()),
                Arguments.of(clientTable.recordView(TestObject.class), objMapper)
        );
    }

    @ParameterizedTest
    @MethodSource
    public <T> void testRecordViewQuery(CriteriaQuerySource<T> view, Function<T, Tuple> mapper) {
        assertThrowsWithCode(
                CriteriaException.class,
                STMT_VALIDATION_ERR,
                () -> view.query(null, columnValue("id", equalTo("2"))),
                "Dynamic parameter requires adding explicit type cast"
        );

        Matcher<Tuple> person0 = allOf(tupleValue("id", is(0)), tupleValue("name", Matchers.nullValue()), tupleValue("salary", is(0.0d)),
                tupleValue("hash", is("hash0".getBytes())));
        Matcher<Tuple> person1 = allOf(tupleValue("id", is(1)), tupleValue("name", is("name1")), tupleValue("salary", is(10.0d)),
                tupleValue("hash", is("hash1".getBytes())));
        Matcher<Tuple> person2 = allOf(tupleValue("id", is(2)), tupleValue("name", is("name2")), tupleValue("salary", is(20.0d)),
                tupleValue("hash", is("hash2".getBytes())));

        try (Cursor<T> cur = view.query(null, null)) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person0, person1, person2));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", equalTo(2)))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person2));
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", equalTo("hash2".getBytes())))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person2));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", notEqualTo(2)))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person0, person1));
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", notEqualTo("hash2".getBytes())))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person0, person1));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", greaterThan(1)))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person2));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", greaterThanOrEqualTo(1)))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person1, person2));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", lessThan(1)))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person0));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", lessThanOrEqualTo(1)))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person0, person1));
        }

        try (Cursor<T> cur = view.query(null, columnValue("name", nullValue()))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person0));
        }

        try (Cursor<T> cur = view.query(null, columnValue("name", notNullValue()))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person1, person2));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", in(1, 2)))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person1, person2));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", notIn(1, 2)))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person0));
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", in("hash1".getBytes(), "hash2".getBytes())))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person1, person2));
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", in((byte[]) null)))) {
            assertThat(mapToTupleList(cur, mapper), empty());
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", notIn("hash1".getBytes(), "hash2".getBytes())))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person0));
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", notIn((byte[]) null)))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(person0, person1, person2));
        }
    }

    private static Stream<Arguments> testKeyValueView() {
        Table table = CLUSTER.aliveNode().tables().table(TABLE_NAME);
        Table clientTable = CLIENT.tables().table(TABLE_NAME);

        Function<Entry<TestObjectKey, TestObject>, Entry<Tuple, Tuple>> kvMapper = (entry) -> {
            TestObjectKey key = entry.getKey();
            TestObject val = entry.getValue();

            return new IgniteBiTuple<>(Tuple.create().set("id", key.id), Tuple.create().set("name", val.name).set("salary", val.salary)
                    .set("hash", val.hash));
        };

        return Stream.of(
                Arguments.of(table.keyValueView(), identity()),
                Arguments.of(table.keyValueView(TestObjectKey.class, TestObject.class), kvMapper),
                Arguments.of(clientTable.keyValueView(), identity()),
                Arguments.of(clientTable.keyValueView(TestObjectKey.class, TestObject.class), kvMapper)
        );
    }

    @ParameterizedTest
    @MethodSource
    public <T> void testKeyValueView(CriteriaQuerySource<T> view, Function<T, Entry<Tuple, Tuple>> mapper) {
        assertThrowsWithCode(
                CriteriaException.class,
                STMT_VALIDATION_ERR,
                () -> view.query(null, columnValue("id", equalTo("2"))),
                "Dynamic parameter requires adding explicit type cast"
        );

        Matcher<Tuple> personKey0 = tupleValue("id", is(0));
        Matcher<Tuple> person0 = allOf(tupleValue("name", Matchers.nullValue()), tupleValue("salary", is(0.0d)),
                tupleValue("hash", is("hash0".getBytes())));

        Matcher<Tuple> personKey1 = tupleValue("id", is(1));
        Matcher<Tuple> person1 = allOf(tupleValue("name", is("name1")), tupleValue("salary", is(10.0d)),
                tupleValue("hash", is("hash1".getBytes())));

        Matcher<Tuple> personKey2 = tupleValue("id", is(2));
        Matcher<Tuple> person2 = allOf(tupleValue("name", is("name2")), tupleValue("salary", is(20.0d)),
                tupleValue("hash", is("hash2".getBytes())));

        try (Cursor<T> cur = view.query(null, null)) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(3),
                    hasEntry(personKey0, person0),
                    hasEntry(personKey1, person1),
                    hasEntry(personKey2, person2)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", equalTo(2)))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(1),
                    hasEntry(personKey2, person2)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", equalTo("hash2".getBytes())))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(1),
                    hasEntry(personKey2, person2)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", notEqualTo(2)))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(2),
                    hasEntry(personKey0, person0),
                    hasEntry(personKey1, person1)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", notEqualTo("hash2".getBytes())))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(2),
                    hasEntry(personKey0, person0),
                    hasEntry(personKey1, person1)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", greaterThan(1)))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(1),
                    hasEntry(personKey2, person2)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", greaterThanOrEqualTo(1)))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(2),
                    hasEntry(personKey1, person1),
                    hasEntry(personKey2, person2)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", lessThan(1)))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(1),
                    hasEntry(personKey0, person0)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", lessThanOrEqualTo(1)))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(2),
                    hasEntry(personKey0, person0),
                    hasEntry(personKey1, person1)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("name", nullValue()))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(1),
                    hasEntry(personKey0, person0)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("name", notNullValue()))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(2),
                    hasEntry(personKey1, person1),
                    hasEntry(personKey2, person2)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", in(1, 2)))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(2),
                    hasEntry(personKey1, person1),
                    hasEntry(personKey2, person2)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("id", notIn(1, 2)))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(1),
                    hasEntry(personKey0, person0)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", in("hash1".getBytes(), "hash2".getBytes())))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(2),
                    hasEntry(personKey1, person1),
                    hasEntry(personKey2, person2)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", in((byte[]) null)))) {
            assertThat(mapToTupleMap(cur, mapper), anEmptyMap());
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", notIn("hash1".getBytes(), "hash2".getBytes())))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(1),
                    hasEntry(personKey0, person0)
            ));
        }

        try (Cursor<T> cur = view.query(null, columnValue("hash", notIn((byte[]) null)))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(3),
                    hasEntry(personKey0, person0),
                    hasEntry(personKey1, person1),
                    hasEntry(personKey2, person2)
            ));
        }
    }

    private static Stream<Arguments> clientViews() {
        Table clientTable = CLIENT.tables().table(TABLE_NAME);

        return Stream.of(
                Arguments.of(clientTable.recordView()),
                Arguments.of(clientTable.recordView(TestObject.class)),
                Arguments.of(clientTable.keyValueView()),
                Arguments.of(clientTable.keyValueView(TestObjectKey.class, TestObject.class))
        );
    }

    @ParameterizedTest
    @MethodSource("clientViews")
    public <T> void testPageOption(CriteriaQuerySource<T> view) {
        AsyncCursor<T> ars = await(view.queryAsync(null, null, null, builder().pageSize(2).build()));

        assertNotNull(ars);
        assertEquals(2, ars.currentPageSize());

        AsyncCursor<T> ars1 = await(ars.fetchNextPage());

        assertNotNull(ars1);
        assertEquals(1, ars1.currentPageSize());

        assertEquals(ars, ars1);

        await(ars.closeAsync());
    }

    private static Stream<Arguments> allViews() {
        Table table = CLUSTER.aliveNode().tables().table(TABLE_NAME);
        Table clientTable = CLIENT.tables().table(TABLE_NAME);

        return Stream.of(
                Arguments.of(table.keyValueView()),
                Arguments.of(table.keyValueView(TestObjectKey.class, TestObject.class)),
                Arguments.of(clientTable.keyValueView()),
                Arguments.of(clientTable.keyValueView(TestObjectKey.class, TestObject.class))
        );
    }

    @ParameterizedTest
    @MethodSource("allViews")
    void testFetchCursorIsClosed(CriteriaQuerySource<TestObject> view) {
        AsyncCursor<TestObject> ars1 = await(view.queryAsync(null, null, null, builder().pageSize(2).build()));

        assertNotNull(ars1);
        await(ars1.closeAsync());
        assertThrowsWithCode(CursorClosedException.class, Common.CURSOR_ALREADY_CLOSED_ERR,
                () -> await(ars1.fetchNextPage()), "Cursor is closed");

        AsyncCursor<TestObject> ars2 = await(view.queryAsync(null, null, null, builder().pageSize(3).build()));

        assertNotNull(ars2);
        assertThrowsWithCode(CursorClosedException.class, Common.CURSOR_ALREADY_CLOSED_ERR,
                () -> await(ars2.fetchNextPage()), "Cursor is closed");
    }

    @ParameterizedTest
    @MethodSource("allViews")
    <T> void testInvalidColumnName(CriteriaQuerySource<T> view) {
        assertThrowsWithCode(CriteriaException.class, INTERNAL_ERR,
                () -> await(view.queryAsync(null, columnValue("id1", equalTo(2)))), "Unexpected column name: ID1");
    }

    private static Stream<Arguments> testRecordViewWithQuotes() {
        Table table = CLUSTER.aliveNode().tables().table(QUOTED_TABLE_NAME);
        Table clientTable = CLIENT.tables().table(QUOTED_TABLE_NAME);

        Mapper<QuotedObject> recMapper = Mapper.builder(QuotedObject.class)
                .map("colUmn", quote("colUmn"))
                .automap()
                .build();

        Function<QuotedObject, Tuple> objMapper = (obj) -> Tuple.create(Map.of("id", obj.id, quote("colUmn"), obj.colUmn));

        return Stream.of(
                Arguments.of(table.recordView(), identity()),
                Arguments.of(table.recordView(recMapper), objMapper),
                Arguments.of(clientTable.recordView(), identity()),
                Arguments.of(clientTable.recordView(recMapper), objMapper)
        );
    }

    @ParameterizedTest
    @MethodSource
    public <T> void testRecordViewWithQuotes(CriteriaQuerySource<T> view, Function<T, Tuple> mapper) {
        try (Cursor<T> cur = view.query(null, columnValue(quote("colUmn"), equalTo("name1")))) {
            assertThat(mapToTupleList(cur, mapper), containsInAnyOrder(
                    allOf(tupleValue("id", is(1)), tupleValue(quote("colUmn"), is("name1")))
            ));
        }
    }

    private static Stream<Arguments> testKeyViewWithQuotes() {
        Table table = CLUSTER.aliveNode().tables().table(QUOTED_TABLE_NAME);
        Table clientTable = CLIENT.tables().table(QUOTED_TABLE_NAME);

        Mapper<QuotedObjectKey> keyMapper = Mapper.of(QuotedObjectKey.class);
        Mapper<QuotedObject> valMapper = Mapper.builder(QuotedObject.class)
                .map("colUmn", quote("colUmn"))
                .build();

        Function<Entry<QuotedObjectKey, QuotedObject>, Entry<Tuple, Tuple>> kvMapper = (entry) ->
                new IgniteBiTuple<>(Tuple.create(Map.of("id", entry.getKey().id)), Tuple.create(Map.of(quote("colUmn"),
                        entry.getValue().colUmn)));

        return Stream.of(
                Arguments.of(table.keyValueView(), identity()),
                Arguments.of(table.keyValueView(keyMapper, valMapper), kvMapper),
                Arguments.of(clientTable.keyValueView(), identity()),
                Arguments.of(clientTable.keyValueView(keyMapper, valMapper), kvMapper)
        );
    }

    @ParameterizedTest
    @MethodSource
    public <T> void testKeyViewWithQuotes(CriteriaQuerySource<T> view, Function<T, Entry<Tuple, Tuple>> mapper) {
        try (Cursor<T> cur = view.query(null, columnValue(quote("colUmn"), equalTo("name1")))) {
            assertThat(mapToTupleMap(cur, mapper), allOf(
                    aMapWithSize(1),
                    hasEntry(tupleValue("id", is(1)), tupleValue(quote("colUmn"), is("name1")))
            ));
        }
    }

    private static Stream<Arguments> testSessionClosing() {
        Table table = CLUSTER.aliveNode().tables().table(TABLE_NAME);

        Transaction tx = CLUSTER.aliveNode().transactions().begin();
        tx.rollback();

        return Stream.of(
                Arguments.of(table.recordView(), tx),
                Arguments.of(table.recordView(TestObject.class), tx),
                Arguments.of(table.keyValueView(), tx),
                Arguments.of(table.keyValueView(TestObjectKey.class, TestObject.class), tx)
        );
    }

    private static <T> List<Tuple> mapToTupleList(Cursor<T> cur, Function<T, Tuple> mapper) {
        return StreamSupport.stream(spliteratorUnknownSize(cur, Spliterator.ORDERED), false)
                .map(mapper)
                .collect(toList());
    }

    private static <T, K, V> Map<K, V> mapToTupleMap(Cursor<T> cur, Function<T, Entry<K, V>> mapper) {
        return StreamSupport.stream(spliteratorUnknownSize(cur, Spliterator.ORDERED), false)
                .map(mapper)
                .collect(toMap(Entry::getKey, Entry::getValue));
    }

    static class QuotedObjectKey {
        int id;
    }

    static class QuotedObject {
        int id;
        String colUmn;
    }

    static class TestObjectKey {
        int id;
    }

    static class TestObject {
        int id;

        String name;

        double salary;

        byte[] hash;
    }
}
