// 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.

#include "runtime/runtime_predicate.h"

#include <gtest/gtest.h>

#include <array>

#include "core/data_type/data_type_factory.hpp"
#include "core/data_type/data_type_number.h"
#include "core/field.h"
#include "exec/pipeline/thrift_builder.h"
#include "exprs/expr_zonemap_filter.h"
#include "exprs/vexpr_context.h"
#include "exprs/vtopn_pred.h"
#include "runtime/descriptors.h"
#include "runtime/query_context.h"
#include "testutil/mock/mock_runtime_state.h"

namespace doris {
namespace {

constexpr TPlanNodeId SOURCE_NODE_ID = 10;
constexpr TPlanNodeId TARGET_NODE_ID = 20;
constexpr SlotId SLOT_ID = 0;

TTopnFilterDesc create_topn_filter_desc(PrimitiveType type = TYPE_INT, bool is_asc = true,
                                        bool nulls_first = false) {
    auto target_expr = TRuntimeFilterDescBuilder::get_default_expr();
    target_expr.nodes[0].__set_type(create_type_desc(type));

    TTopnFilterDesc desc;
    desc.__set_source_node_id(SOURCE_NODE_ID);
    desc.__set_is_asc(is_asc);
    desc.__set_null_first(nulls_first);
    desc.__set_target_node_id_to_target_expr({{TARGET_NODE_ID, target_expr}});
    return desc;
}

SlotDescriptor create_int_slot_descriptor() {
    SlotDescriptor slot_desc;
    slot_desc._id = SLOT_ID;
    slot_desc._col_name = "k1";
    slot_desc._type = DataTypeFactory::instance().create_data_type(PrimitiveType::TYPE_INT, false);
    return slot_desc;
}

VExprContextSPtr create_prepared_topn_expr(MockRuntimeState* state, const DataTypePtr& data_type,
                                           const Field& top_value = Field(), bool is_asc = true,
                                           bool nulls_first = false) {
    DORIS_CHECK(state != nullptr);
    DORIS_CHECK(data_type != nullptr);
    auto desc = create_topn_filter_desc(data_type->get_primitive_type(), is_asc, nulls_first);
    state->get_query_ctx()->init_runtime_predicates({desc});
    auto& predicate = state->get_query_ctx()->get_runtime_predicate(SOURCE_NODE_ID);
    predicate.set_detected_source();
    DORIS_CHECK(predicate.init_target(TARGET_NODE_ID, {}, -1).ok());
    if (!top_value.is_null()) {
        DORIS_CHECK(predicate.update(top_value).ok());
    }

    TExprNode node;
    node.__set_type(create_type_desc(PrimitiveType::TYPE_BOOLEAN));
    node.__set_is_nullable(data_type->is_nullable());
    auto expr = VTopNPred::create_shared(node, SOURCE_NODE_ID, nullptr);
    expr->add_child(VSlotRef::create_shared(SLOT_ID, 0, -1, data_type, "topn_column"));
    auto context = VExprContext::create_shared(std::move(expr));
    DORIS_CHECK(context->prepare(state, RowDescriptor()).ok());
    DORIS_CHECK(context->open(state).ok());
    return context;
}

} // namespace

TEST(RuntimePredicateTest, init_target_creates_column_predicate_for_valid_column_id) {
    RuntimePredicate predicate(create_topn_filter_desc());
    predicate.set_detected_source();

    auto slot_desc = create_int_slot_descriptor();
    phmap::flat_hash_map<int, SlotDescriptor*> slot_id_to_slot_desc;
    slot_id_to_slot_desc[SLOT_ID] = &slot_desc;

    ASSERT_TRUE(predicate.init_target(TARGET_NODE_ID, slot_id_to_slot_desc, 0).ok());

    EXPECT_TRUE(predicate.enable());
    EXPECT_EQ("k1", predicate.get_col_name(TARGET_NODE_ID));
    EXPECT_NE(nullptr, predicate.get_predicate(TARGET_NODE_ID));
}

TEST(RuntimePredicateTest, init_target_without_column_predicate_still_enables_runtime_filter) {
    RuntimePredicate predicate(create_topn_filter_desc());
    predicate.set_detected_source();

    phmap::flat_hash_map<int, SlotDescriptor*> slot_id_to_slot_desc;
    ASSERT_TRUE(predicate.init_target(TARGET_NODE_ID, slot_id_to_slot_desc, -1).ok());

    EXPECT_TRUE(predicate.enable());
    EXPECT_EQ(nullptr, predicate.get_predicate(TARGET_NODE_ID));

    auto top_value = Field::create_field<TYPE_INT>(10);
    ASSERT_TRUE(predicate.update(top_value).ok());
    EXPECT_TRUE(predicate.has_value());
    EXPECT_EQ(top_value, predicate.get_value());
}

TEST(RuntimePredicateTest, TopNPredicateFiltersRawFixedValuesUsingCurrentBound) {
    MockRuntimeState state;
    const auto type = std::make_shared<DataTypeInt32>();
    auto context = create_prepared_topn_expr(&state, type, Field::create_field<TYPE_INT>(3));
    const std::array<int32_t, 4> values {1, 3, 4, 2};
    IColumn::Filter matches(values.size(), 1);

    ASSERT_TRUE(context->root()->can_execute_on_raw_fixed_values(type, 0));
    ASSERT_TRUE(context->root()
                        ->execute_on_raw_fixed_values(
                                reinterpret_cast<const uint8_t*>(values.data()), values.size(),
                                sizeof(int32_t), type, 0, matches.data())
                        .ok());
    EXPECT_EQ(matches, (IColumn::Filter {1, 1, 0, 1}));
    context->close();
}

TEST(RuntimePredicateTest, TopNPredicateEvaluatesDictionaryValuesUsingCurrentBound) {
    MockRuntimeState state;
    const auto type = std::make_shared<DataTypeInt32>();
    auto context = create_prepared_topn_expr(&state, type, Field::create_field<TYPE_INT>(3));
    DictionaryEvalContext dictionary_ctx;
    dictionary_ctx.slots.emplace(0, DictionaryEvalContext::SlotDictionary {
                                            .data_type = type,
                                            .values = {Field::create_field<TYPE_INT>(4),
                                                       Field::create_field<TYPE_INT>(5)}});

    ASSERT_TRUE(context->root()->can_evaluate_dictionary_filter());
    EXPECT_EQ(context->root()->evaluate_dictionary_filter(dictionary_ctx),
              ZoneMapFilterResult::kNoMatch);
    dictionary_ctx.slots.at(0).values.push_back(Field::create_field<TYPE_INT>(2));
    EXPECT_EQ(context->root()->evaluate_dictionary_filter(dictionary_ctx),
              ZoneMapFilterResult::kMayMatch);
    context->close();
}

TEST(RuntimePredicateTest, TopNPredicateFiltersRawBinaryValuesUsingCurrentBound) {
    MockRuntimeState state;
    const auto type = DataTypeFactory::instance().create_data_type(TYPE_STRING, false);
    auto context =
            create_prepared_topn_expr(&state, type, Field::create_field<TYPE_STRING>("middle"));
    const std::array<StringRef, 3> values {StringRef("alpha"), StringRef("middle"),
                                           StringRef("zulu")};
    IColumn::Filter matches(values.size(), 1);

    ASSERT_TRUE(context->root()->can_execute_on_raw_binary_values(type, 0));
    ASSERT_TRUE(context->root()
                        ->execute_on_raw_binary_values(values.data(), values.size(), type, 0,
                                                       matches.data())
                        .ok());
    EXPECT_EQ(matches, (IColumn::Filter {1, 1, 0}));
    context->close();
}

TEST(RuntimePredicateTest, TopNPredicateFiltersRawVarbinaryAndDictionaryValues) {
    MockRuntimeState state;
    const auto type = DataTypeFactory::instance().create_data_type(TYPE_VARBINARY, false);
    auto context = create_prepared_topn_expr(
            &state, type, Field::create_field<TYPE_VARBINARY>(StringView("middle")));
    const std::array<StringRef, 3> values {StringRef("alpha"), StringRef("middle"),
                                           StringRef("zulu")};
    IColumn::Filter matches(values.size(), 1);

    ASSERT_TRUE(context->root()
                        ->execute_on_raw_binary_values(values.data(), values.size(), type, 0,
                                                       matches.data())
                        .ok());
    EXPECT_EQ(matches, (IColumn::Filter {1, 1, 0}));

    DictionaryEvalContext dictionary_ctx;
    dictionary_ctx.slots.emplace(
            0, DictionaryEvalContext::SlotDictionary {
                       .data_type = type,
                       .values = {Field::create_field<TYPE_VARBINARY>(StringView("zulu"))}});
    EXPECT_EQ(context->root()->evaluate_dictionary_filter(dictionary_ctx),
              ZoneMapFilterResult::kNoMatch);
    dictionary_ctx.slots.at(0).values.push_back(
            Field::create_field<TYPE_VARBINARY>(StringView("alpha")));
    EXPECT_EQ(context->root()->evaluate_dictionary_filter(dictionary_ctx),
              ZoneMapFilterResult::kMayMatch);
    context->close();
}

TEST(RuntimePredicateTest, TopNPredicateKeepsDirectCapabilityBeforeFirstBound) {
    MockRuntimeState state;
    const auto type = std::make_shared<DataTypeInt32>();
    auto context = create_prepared_topn_expr(&state, type);
    const std::array<int32_t, 2> values {1, 4};
    IColumn::Filter matches(values.size(), 1);

    ASSERT_TRUE(context->root()->can_execute_on_raw_fixed_values(type, 0));
    EXPECT_TRUE(context->root()->raw_predicate_result_for_null());
    ASSERT_TRUE(context->root()
                        ->execute_on_raw_fixed_values(
                                reinterpret_cast<const uint8_t*>(values.data()), values.size(),
                                sizeof(int32_t), type, 0, matches.data())
                        .ok());
    EXPECT_EQ(matches, (IColumn::Filter {1, 1}));

    auto& predicate = state.get_query_ctx()->get_runtime_predicate(SOURCE_NODE_ID);
    ASSERT_TRUE(predicate.update(Field::create_field<TYPE_INT>(2)).ok());
    EXPECT_FALSE(context->root()->raw_predicate_result_for_null());
    ASSERT_TRUE(context->root()
                        ->execute_on_raw_fixed_values(
                                reinterpret_cast<const uint8_t*>(values.data()), values.size(),
                                sizeof(int32_t), type, 0, matches.data())
                        .ok());
    EXPECT_EQ(matches, (IColumn::Filter {1, 0}));
    context->close();
}

TEST(RuntimePredicateTest, TopNPredicateAdvertisesDirectCapabilityForEverySupportedType) {
    struct TypeSpec {
        PrimitiveType type;
        int precision = 0;
        int scale = 0;
        bool binary = false;
    };
    const std::array<TypeSpec, 23> supported_types {{
            {TYPE_BOOLEAN},
            {TYPE_TINYINT},
            {TYPE_SMALLINT},
            {TYPE_INT},
            {TYPE_BIGINT},
            {TYPE_LARGEINT},
            {TYPE_DATE},
            {TYPE_DATETIME},
            {TYPE_DATEV2},
            {TYPE_DATETIMEV2},
            {TYPE_TIMESTAMPTZ},
            {TYPE_TIMEV2},
            {TYPE_DECIMAL32, 9, 2},
            {TYPE_DECIMAL64, 18, 2},
            {TYPE_DECIMALV2, 27, 9},
            {TYPE_DECIMAL128I, 38, 2},
            {TYPE_DECIMAL256, 76, 2},
            {TYPE_IPV4},
            {TYPE_IPV6},
            {TYPE_CHAR, 0, 0, true},
            {TYPE_STRING, 0, 0, true},
            {TYPE_VARCHAR, 0, 0, true},
            {TYPE_VARBINARY, 0, 0, true},
    }};

    for (const auto& spec : supported_types) {
        SCOPED_TRACE(type_to_string(spec.type));
        MockRuntimeState state;
        const auto data_type = DataTypeFactory::instance().create_data_type(
                spec.type, false, spec.precision, spec.scale);
        auto context = create_prepared_topn_expr(&state, data_type);
        if (spec.binary) {
            EXPECT_TRUE(context->root()->can_execute_on_raw_binary_values(data_type, 0));
        } else {
            EXPECT_TRUE(context->root()->can_execute_on_raw_fixed_values(data_type, 0));
        }
        EXPECT_TRUE(context->root()->can_evaluate_dictionary_filter());
        context->close();
    }
}

TEST(RuntimePredicateTest, DescTopNPredicateFiltersRawValuesUsingCurrentBound) {
    MockRuntimeState state;
    const auto type = std::make_shared<DataTypeInt32>();
    auto context = create_prepared_topn_expr(&state, type, Field::create_field<TYPE_INT>(3), false);
    const std::array<int32_t, 3> values {1, 3, 4};
    IColumn::Filter matches(values.size(), 1);

    ASSERT_TRUE(context->root()
                        ->execute_on_raw_fixed_values(
                                reinterpret_cast<const uint8_t*>(values.data()), values.size(),
                                sizeof(int32_t), type, 0, matches.data())
                        .ok());
    EXPECT_EQ(matches, (IColumn::Filter {0, 1, 1}));
    context->close();
}

TEST(RuntimePredicateTest, NullableNullsFirstTopNSupportsRawNullSemantics) {
    MockRuntimeState state;
    const auto type = make_nullable(std::make_shared<DataTypeInt32>());
    auto context =
            create_prepared_topn_expr(&state, type, Field::create_field<TYPE_INT>(3), true, true);

    EXPECT_TRUE(context->root()->can_execute_on_raw_fixed_values(type, 0));
    EXPECT_TRUE(context->root()->raw_predicate_result_for_null());
    EXPECT_FALSE(context->root()->can_evaluate_dictionary_filter());
    context->close();
}

TEST(RuntimePredicateTest, TopNPredicateNormalizesConstNullableComparisonResult) {
    constexpr size_t rows = 3;
    const auto type = make_nullable(std::make_shared<DataTypeInt32>());

    for (const bool nulls_first : {false, true}) {
        SCOPED_TRACE(nulls_first ? "NULLS FIRST" : "NULLS LAST");
        MockRuntimeState state;
        auto context = create_prepared_topn_expr(&state, type, Field::create_field<TYPE_INT>(3),
                                                 true, nulls_first);

        Block block;
        block.insert(
                {ColumnNullable::create(ColumnInt32::create(rows, 0), ColumnUInt8::create(rows, 1)),
                 type, "topn_column"});

        ColumnPtr result_column;
        auto status = context->root()->execute_column(context.get(), &block, nullptr, block.rows(),
                                                      result_column);
        ASSERT_TRUE(status.ok()) << status;
        ASSERT_TRUE(is_column_const(*result_column));
        EXPECT_FALSE(result_column->is_null_at(0));
        EXPECT_EQ(result_column->get_bool(0), nulls_first);

        int result_column_id = -1;
        status = context->execute(&block, &result_column_id);
        ASSERT_TRUE(status.ok()) << status;
        const auto& strict_result = block.get_by_position(result_column_id);
        ASSERT_TRUE(is_column_const(*strict_result.column));
        EXPECT_NE(nullptr, check_and_get_column_with_const<ColumnNullable>(*strict_result.column));
        EXPECT_FALSE(strict_result.column->is_null_at(0));
        EXPECT_EQ(strict_result.column->get_bool(0), nulls_first);

        IColumn::Filter filter(rows, 1);
        bool can_filter_all = false;
        status = context->execute_filter(&block, filter.data(), rows, false, &can_filter_all);
        ASSERT_TRUE(status.ok()) << status;
        EXPECT_EQ(filter, IColumn::Filter(rows, nulls_first));
        EXPECT_EQ(can_filter_all, !nulls_first);
        context->close();
    }
}

} // namespace doris
