// 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 <gen_cpp/Exprs_types.h>
#include <gen_cpp/Types_types.h>
#include <gtest/gtest.h>

#include "common/exception.h"
#include "runtime/descriptors.h"

namespace doris {

class SlotDescriptorTest : public testing::Test {
public:
    void SetUp() override {}
    void TearDown() override {}

protected:
    // Helper method to create a basic TSlotDescriptor
    TSlotDescriptor create_basic_slot_descriptor(int slot_id = 1,
                                                 const std::string& col_name = "test_col") {
        TSlotDescriptor tdesc;
        tdesc.__set_id(slot_id);
        tdesc.__set_parent(1);
        tdesc.__set_slotType(create_string_type());
        tdesc.__set_columnPos(0);
        tdesc.__set_colName(col_name);
        tdesc.__set_col_unique_id(slot_id);
        tdesc.__set_slotIdx(0);
        tdesc.__set_isMaterialized(true);
        tdesc.__set_is_key(false);
        tdesc.__set_nullIndicatorBit(0);
        return tdesc;
    }

    // Helper method to create a TTypeDesc for string type
    TTypeDesc create_string_type() {
        TTypeDesc type_desc;
        TTypeNode type_node;
        TScalarType scalar_type;
        scalar_type.__set_type(TPrimitiveType::STRING);
        type_node.__set_type(TTypeNodeType::SCALAR);
        type_node.__set_scalar_type(scalar_type);
        type_desc.types.push_back(type_node);
        return type_desc;
    }

    // Helper method to create a TExpr with nodes
    TExpr create_virtual_column_expr(TExprNodeType::type node_type = TExprNodeType::FUNCTION_CALL) {
        TExpr expr;
        TExprNode node;
        node.__set_node_type(node_type);
        node.__set_type(create_string_type());
        expr.nodes.push_back(node);
        return expr;
    }
};

TEST_F(SlotDescriptorTest, BasicConstructor) {
    // Test basic constructor without virtual column expression
    TSlotDescriptor tdesc = create_basic_slot_descriptor();

    EXPECT_NO_THROW({
        SlotDescriptor slot_desc(tdesc);
        EXPECT_EQ(slot_desc.id(), 1);
        EXPECT_EQ(slot_desc.col_name(), "test_col");
        EXPECT_EQ(slot_desc.col_unique_id(), 1);
        EXPECT_FALSE(slot_desc.is_key());
        EXPECT_EQ(slot_desc.get_virtual_column_expr(), nullptr);
    });
}

TEST_F(SlotDescriptorTest, VirtualColumnExprValid) {
    // Test constructor with valid virtual column expression
    TSlotDescriptor tdesc = create_basic_slot_descriptor();
    TExpr virtual_expr = create_virtual_column_expr(TExprNodeType::FUNCTION_CALL);
    tdesc.__set_virtual_column_expr(virtual_expr);

    EXPECT_NO_THROW({
        SlotDescriptor slot_desc(tdesc);
        EXPECT_EQ(slot_desc.id(), 1);
        EXPECT_EQ(slot_desc.col_name(), "test_col");
        EXPECT_NE(slot_desc.get_virtual_column_expr(), nullptr);
    });
}

TEST_F(SlotDescriptorTest, VirtualColumnExprEmptyNodes) {
    // Test constructor with empty virtual column expression nodes - should throw exception
    TSlotDescriptor tdesc = create_basic_slot_descriptor(1, "virtual_col");
    TExpr virtual_expr;
    // Empty nodes list
    virtual_expr.nodes.clear();
    tdesc.__set_virtual_column_expr(virtual_expr);

    EXPECT_THROW({ SlotDescriptor slot_desc(tdesc); }, doris::Exception);

    // Test the specific exception message
    try {
        SlotDescriptor slot_desc(tdesc);
        FAIL() << "Expected doris::Exception";
    } catch (const doris::Exception& e) {
        std::string error_msg = e.what();
        EXPECT_TRUE(error_msg.find("Virtual column expr node is empty") != std::string::npos);
        EXPECT_TRUE(error_msg.find("virtual_col") != std::string::npos);
        EXPECT_TRUE(error_msg.find("col_unique_id: 1") != std::string::npos);
    }
}

TEST_F(SlotDescriptorTest, VirtualColumnExprSlotRefNode) {
    // Test constructor with SLOT_REF node type - should throw exception
    TSlotDescriptor tdesc = create_basic_slot_descriptor(2, "slot_ref_col");
    TExpr virtual_expr = create_virtual_column_expr(TExprNodeType::SLOT_REF);
    tdesc.__set_virtual_column_expr(virtual_expr);

    EXPECT_THROW({ SlotDescriptor slot_desc(tdesc); }, doris::Exception);

    // Test the specific exception message
    try {
        SlotDescriptor slot_desc(tdesc);
        FAIL() << "Expected doris::Exception";
    } catch (const doris::Exception& e) {
        std::string error_msg = e.what();
        EXPECT_TRUE(error_msg.find("Virtual column expr node is slot ref") != std::string::npos);
        EXPECT_TRUE(error_msg.find("slot_ref_col") != std::string::npos);
        EXPECT_TRUE(error_msg.find("col_unique_id: 2") != std::string::npos);
    }
}

TEST_F(SlotDescriptorTest, VirtualColumnExprVirtualSlotRefNode) {
    // Test constructor with VIRTUAL_SLOT_REF node type - should be valid
    TSlotDescriptor tdesc = create_basic_slot_descriptor();
    TExpr virtual_expr = create_virtual_column_expr(TExprNodeType::VIRTUAL_SLOT_REF);
    tdesc.__set_virtual_column_expr(virtual_expr);

    EXPECT_NO_THROW({
        SlotDescriptor slot_desc(tdesc);
        EXPECT_EQ(slot_desc.id(), 1);
        EXPECT_EQ(slot_desc.col_name(), "test_col");
        EXPECT_NE(slot_desc.get_virtual_column_expr(), nullptr);
    });
}

TEST_F(SlotDescriptorTest, OptionalFields) {
    // Test constructor with optional fields set
    TSlotDescriptor tdesc = create_basic_slot_descriptor();
    tdesc.__set_is_auto_increment(true);
    tdesc.__set_col_default_value("default_value");

    EXPECT_NO_THROW({
        SlotDescriptor slot_desc(tdesc);
        EXPECT_EQ(slot_desc.id(), 1);
        EXPECT_EQ(slot_desc.col_name(), "test_col");
    });
}

TEST_F(SlotDescriptorTest, OptionalFieldsNotSet) {
    // Test constructor with optional fields not set
    TSlotDescriptor tdesc = create_basic_slot_descriptor();
    // Don't set is_auto_increment and col_default_value

    EXPECT_NO_THROW({
        SlotDescriptor slot_desc(tdesc);
        EXPECT_EQ(slot_desc.id(), 1);
        EXPECT_EQ(slot_desc.col_name(), "test_col");
    });
}

TEST_F(SlotDescriptorTest, DebugString) {
    // Test debug string output for virtual and non-virtual columns
    TSlotDescriptor tdesc1 = create_basic_slot_descriptor(1, "normal_col");
    SlotDescriptor slot_desc1(tdesc1);
    std::string debug_str1 = slot_desc1.debug_string();
    EXPECT_TRUE(debug_str1.find("normal_col") != std::string::npos);
    EXPECT_TRUE(debug_str1.find("is_virtual=false") != std::string::npos);

    TSlotDescriptor tdesc2 = create_basic_slot_descriptor(2, "virtual_col");
    TExpr virtual_expr = create_virtual_column_expr(TExprNodeType::FUNCTION_CALL);
    tdesc2.__set_virtual_column_expr(virtual_expr);
    SlotDescriptor slot_desc2(tdesc2);
    std::string debug_str2 = slot_desc2.debug_string();
    EXPECT_TRUE(debug_str2.find("virtual_col") != std::string::npos);
    EXPECT_TRUE(debug_str2.find("is_virtual=true") != std::string::npos);
}

} // namespace doris