// 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 "exprs/vtopn_pred.h"

#include <cstring>

#include "exprs/expr_zonemap_filter.h"
#include "util/simd/parquet_kernels.h"

namespace doris {

namespace {

using simd::RawComparisonOp;

size_t topn_raw_value_size(PrimitiveType type) {
    switch (type) {
#define RETURN_TOPN_RAW_SIZE(TYPE) \
    case TYPE:                     \
        return sizeof(typename PrimitiveTypeTraits<TYPE>::CppType)
        RETURN_TOPN_RAW_SIZE(TYPE_BOOLEAN);
        RETURN_TOPN_RAW_SIZE(TYPE_TINYINT);
        RETURN_TOPN_RAW_SIZE(TYPE_SMALLINT);
        RETURN_TOPN_RAW_SIZE(TYPE_INT);
        RETURN_TOPN_RAW_SIZE(TYPE_BIGINT);
        RETURN_TOPN_RAW_SIZE(TYPE_LARGEINT);
        RETURN_TOPN_RAW_SIZE(TYPE_FLOAT);
        RETURN_TOPN_RAW_SIZE(TYPE_DOUBLE);
        RETURN_TOPN_RAW_SIZE(TYPE_DATE);
        RETURN_TOPN_RAW_SIZE(TYPE_DATETIME);
        RETURN_TOPN_RAW_SIZE(TYPE_DATEV2);
        RETURN_TOPN_RAW_SIZE(TYPE_DATETIMEV2);
        RETURN_TOPN_RAW_SIZE(TYPE_TIMESTAMPTZ);
        // Master no longer defines a C++ carrier for legacy TYPE_TIME; Parquet time values use
        // TYPE_TIMEV2, so advertising the deprecated tag would make direct filtering unusable.
        RETURN_TOPN_RAW_SIZE(TYPE_TIMEV2);
        RETURN_TOPN_RAW_SIZE(TYPE_DECIMAL32);
        RETURN_TOPN_RAW_SIZE(TYPE_DECIMAL64);
        RETURN_TOPN_RAW_SIZE(TYPE_DECIMALV2);
        RETURN_TOPN_RAW_SIZE(TYPE_DECIMAL128I);
        RETURN_TOPN_RAW_SIZE(TYPE_DECIMAL256);
        RETURN_TOPN_RAW_SIZE(TYPE_IPV4);
        RETURN_TOPN_RAW_SIZE(TYPE_IPV6);
#undef RETURN_TOPN_RAW_SIZE
    default:
        return 0;
    }
}

bool topn_binary_type(PrimitiveType type) {
    return is_string_type(type) || type == TYPE_VARBINARY;
}

template <typename T, PrimitiveType PT>
void execute_topn_raw_comparison(const uint8_t* values, size_t num_values, const Field& bound,
                                 RawComparisonOp op, uint8_t* matches) {
    simd::raw_compare(values, num_values, bound.get<PT>(), op, matches);
}

template <typename T>
bool topn_raw_scalar_matches(const T& value, const T& bound, RawComparisonOp op) {
    return op == RawComparisonOp::LE ? value <= bound : value >= bound;
}

template <PrimitiveType PT>
void execute_topn_raw_scalar(const uint8_t* values, size_t num_values, const Field& bound,
                             RawComparisonOp op, uint8_t* matches) {
    using T = typename PrimitiveTypeTraits<PT>::CppType;
    const T& typed_bound = bound.get<PT>();
    for (size_t row = 0; row < num_values; ++row) {
        T value;
        std::memcpy(&value, values + row * sizeof(T), sizeof(T));
        matches[row] &= topn_raw_scalar_matches(value, typed_bound, op) ? 1 : 0;
    }
}

bool topn_string_matches(int comparison, RawComparisonOp op) {
    return op == RawComparisonOp::LE ? comparison <= 0 : comparison >= 0;
}

} // namespace

bool VTopNPred::can_execute_on_raw_fixed_values(const DataTypePtr& data_type, int column_id) const {
    if (_predicate == nullptr || data_type == nullptr || _children.size() != 1) {
        return false;
    }
    const auto slot = std::dynamic_pointer_cast<VSlotRef>(_children[0]);
    if (slot == nullptr || slot->column_id() != column_id || slot->data_type() == nullptr) {
        return false;
    }
    const auto raw_type = remove_nullable(data_type);
    return remove_nullable(slot->data_type())->equals(*raw_type) &&
           topn_raw_value_size(raw_type->get_primitive_type()) != 0;
}

Status VTopNPred::execute_on_raw_fixed_values(const uint8_t* values, size_t num_values,
                                              size_t value_width, const DataTypePtr& data_type,
                                              int column_id, uint8_t* matches) const {
    if (!can_execute_on_raw_fixed_values(data_type, column_id)) {
        return Status::NotSupported("TopN predicate cannot evaluate raw fixed-width values");
    }
    DORIS_CHECK(values != nullptr || num_values == 0);
    DORIS_CHECK(matches != nullptr || num_values == 0);
    const auto primitive_type = remove_nullable(data_type)->get_primitive_type();
    const size_t expected_width = topn_raw_value_size(primitive_type);
    if (value_width != expected_width) {
        return Status::Corruption("Raw TopN width {} does not match expected {}", value_width,
                                  expected_width);
    }

    // The bound is mutable and may arrive after reader initialization. Snapshot it once per batch
    // so every row observes one monotonic TopN frontier without invalidating cached capability.
    const Field bound = _predicate->get_value();
    if (bound.is_null()) {
        return Status::OK();
    }
    if (!expr_zonemap::field_types_compatible(bound.get_type(), primitive_type)) {
        return Status::InternalError("TopN bound type {} does not match raw value type {}",
                                     type_to_string(bound.get_type()),
                                     type_to_string(primitive_type));
    }
    const auto op = _predicate->is_asc() ? RawComparisonOp::LE : RawComparisonOp::GE;
    switch (primitive_type) {
    case TYPE_INT:
        execute_topn_raw_comparison<int32_t, TYPE_INT>(values, num_values, bound, op, matches);
        break;
    case TYPE_BIGINT:
        execute_topn_raw_comparison<int64_t, TYPE_BIGINT>(values, num_values, bound, op, matches);
        break;
    case TYPE_FLOAT:
        execute_topn_raw_comparison<float, TYPE_FLOAT>(values, num_values, bound, op, matches);
        break;
    case TYPE_DOUBLE:
        execute_topn_raw_comparison<double, TYPE_DOUBLE>(values, num_values, bound, op, matches);
        break;
#define EXECUTE_TOPN_RAW_SCALAR(TYPE)                                          \
    case TYPE:                                                                 \
        execute_topn_raw_scalar<TYPE>(values, num_values, bound, op, matches); \
        break
        EXECUTE_TOPN_RAW_SCALAR(TYPE_BOOLEAN);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_TINYINT);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_SMALLINT);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_LARGEINT);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DATE);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DATETIME);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DATEV2);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DATETIMEV2);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_TIMESTAMPTZ);
        // Keep dispatch aligned with topn_raw_value_size(): legacy TYPE_TIME has no master carrier.
        EXECUTE_TOPN_RAW_SCALAR(TYPE_TIMEV2);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DECIMAL32);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DECIMAL64);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DECIMALV2);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DECIMAL128I);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_DECIMAL256);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_IPV4);
        EXECUTE_TOPN_RAW_SCALAR(TYPE_IPV6);
#undef EXECUTE_TOPN_RAW_SCALAR
    default:
        return Status::NotSupported("TopN raw fixed-width type {} is unsupported",
                                    type_to_string(primitive_type));
    }
    return Status::OK();
}

bool VTopNPred::can_execute_on_raw_binary_values(const DataTypePtr& data_type,
                                                 int column_id) const {
    if (_predicate == nullptr || data_type == nullptr || _children.size() != 1) {
        return false;
    }
    const auto raw_type = remove_nullable(data_type);
    const auto raw_primitive_type = raw_type->get_primitive_type();
    if (!topn_binary_type(raw_primitive_type)) {
        return false;
    }
    const auto slot = std::dynamic_pointer_cast<VSlotRef>(_children[0]);
    if (slot == nullptr || slot->column_id() != column_id || slot->data_type() == nullptr) {
        return false;
    }
    const auto slot_primitive_type = remove_nullable(slot->data_type())->get_primitive_type();
    return (is_string_type(raw_primitive_type) && is_string_type(slot_primitive_type)) ||
           (raw_primitive_type == TYPE_VARBINARY && slot_primitive_type == TYPE_VARBINARY);
}

Status VTopNPred::execute_on_raw_binary_values(const StringRef* values, size_t num_values,
                                               const DataTypePtr& data_type, int column_id,
                                               uint8_t* matches) const {
    if (!can_execute_on_raw_binary_values(data_type, column_id)) {
        return Status::NotSupported("TopN predicate cannot evaluate raw binary values");
    }
    DORIS_CHECK(values != nullptr || num_values == 0);
    DORIS_CHECK(matches != nullptr || num_values == 0);
    const Field bound = _predicate->get_value();
    if (bound.is_null()) {
        return Status::OK();
    }
    const auto primitive_type = remove_nullable(data_type)->get_primitive_type();
    StringRef bound_ref;
    if (is_string_type(primitive_type) && is_string_type(bound.get_type())) {
        const auto& value = bound.get<TYPE_STRING>();
        bound_ref = StringRef(value.data(), value.size());
    } else if (primitive_type == TYPE_VARBINARY && bound.get_type() == TYPE_VARBINARY) {
        bound_ref = bound.get<TYPE_VARBINARY>().to_string_ref();
    } else {
        return Status::InternalError("TopN bound type {} does not match raw binary type {}",
                                     type_to_string(bound.get_type()),
                                     type_to_string(primitive_type));
    }
    const auto op = _predicate->is_asc() ? RawComparisonOp::LE : RawComparisonOp::GE;
    for (size_t row = 0; row < num_values; ++row) {
        matches[row] &= topn_string_matches(values[row].compare(bound_ref), op) ? 1 : 0;
    }
    return Status::OK();
}

bool VTopNPred::can_evaluate_dictionary_filter() const {
    if (_predicate == nullptr || _predicate->nulls_first() || _children.size() != 1) {
        return false;
    }
    const auto slot = std::dynamic_pointer_cast<VSlotRef>(_children[0]);
    if (slot == nullptr || slot->data_type() == nullptr) {
        return false;
    }
    const auto primitive_type = remove_nullable(slot->data_type())->get_primitive_type();
    return topn_raw_value_size(primitive_type) != 0 || topn_binary_type(primitive_type);
}

ZoneMapFilterResult VTopNPred::evaluate_dictionary_filter(const DictionaryEvalContext& ctx) const {
    if (!can_evaluate_dictionary_filter()) {
        return ZoneMapFilterResult::kUnsupported;
    }
    const auto slot = std::dynamic_pointer_cast<VSlotRef>(_children[0]);
    DORIS_CHECK(slot != nullptr);
    const auto* dictionary = ctx.slot(slot->column_id());
    if (dictionary == nullptr ||
        !expr_zonemap::data_types_compatible(dictionary->data_type, slot->data_type())) {
        return ZoneMapFilterResult::kUnsupported;
    }
    const Field bound = _predicate->get_value();
    if (bound.is_null()) {
        return ZoneMapFilterResult::kMayMatch;
    }
    const auto primitive_type = remove_nullable(dictionary->data_type)->get_primitive_type();
    if (!expr_zonemap::field_types_compatible(bound.get_type(), primitive_type)) {
        return ZoneMapFilterResult::kUnsupported;
    }
    for (const Field& value : dictionary->values) {
        if (value.is_null()) {
            continue;
        }
        if (!expr_zonemap::field_types_compatible(value.get_type(), primitive_type)) {
            return ZoneMapFilterResult::kUnsupported;
        }
        if ((_predicate->is_asc() && value <= bound) || (!_predicate->is_asc() && value >= bound)) {
            return ZoneMapFilterResult::kMayMatch;
        }
    }
    return ZoneMapFilterResult::kNoMatch;
}

} // namespace doris
