#include "gtest/gtest.h"
#include "db/NewDB.h"  // NewDB 的头文件
#include "leveldb/env.h"
#include "leveldb/db.h"
#include <iostream>

using namespace leveldb;

// 打开数据库的辅助函数
Status OpenDB(std::string dbName, NewDB** db) {
    Options options = Options();
    options.create_if_missing = true;
    return NewDB::Open(options, dbName, db);
}

std::string testdbname = "testdb1";

// 测试 NewDB::Put_fields 方法和二级索引的创建
TEST(TestNewDB, PutFieldsWithIndexTest) {
    // 创建 NewDB 实例
    NewDB* db;
    if (OpenDB(testdbname, &db).ok() == false) {
        std::cerr << "open db failed" << std::endl;
        abort();
    }

    // 创建索引字段
    db->CreateIndexOnField("address");

    // 定义插入的字段数据
    std::string key1 = "k_1";
    FieldArray fields1 = {
        {"name", "Customer#000000001"},
        {"address", "IVhzIApeRb"},
        {"phone", "25-989-741-2988"}
    };

    // 定义字段数组，用于获取数据
    FieldArray retrieved_fields;

    // 使用 NewDB::Put_fields 插入数据
    db->Put_fields(WriteOptions(), key1, fields1);

    // // 检查索引是否成功创建
    // EXPECT_TRUE(db->IsFieldIndexed("address")); // 检查字段是否已索引

    // 获取并验证字段数据
    db->Get_fields(ReadOptions(), key1, &retrieved_fields);
    EXPECT_EQ(retrieved_fields.size(), fields1.size());
    
    // 验证插入的每个字段
    for (size_t i = 0; i < fields1.size(); ++i) {
        EXPECT_EQ(fields1[i].first, retrieved_fields[i].first);  // 字段名
        EXPECT_EQ(fields1[i].second, retrieved_fields[i].second); // 字段值
    }

    // 插入第二条数据
    std::string key2 = "k_2";
    FieldArray fields2 = {
        {"name", "Customer#000000002"},
        {"address", "TXkjZEdIrZ"},
        {"phone", "25-123-456-7890"}
    };
    db->Put_fields(WriteOptions(), key2, fields2);

    // 获取并验证第二条数据
    FieldArray retrieved_fields2;
    db->Get_fields(ReadOptions(), key2, &retrieved_fields2);
    EXPECT_EQ(retrieved_fields2.size(), fields2.size());
    
    for (size_t i = 0; i < fields2.size(); ++i) {
        EXPECT_EQ(fields2[i].first, retrieved_fields2[i].first);  // 字段名
        EXPECT_EQ(fields2[i].second, retrieved_fields2[i].second); // 字段值
    }

    // 清理数据库
    delete db;
}

TEST(TestNewDB, DeleteDataTest) {
    // 创建 NewDB 实例
    NewDB* db;
    ASSERT_TRUE(OpenDB(testdbname, &db).ok());

    // 插入测试数据
    std::string key = "k_3";
    FieldArray fields = {
        {"name", "Customer#000000003"},
        {"address", "AddressToDelete"},
        {"phone", "25-789-123-4567"}
    };
    ASSERT_TRUE(db->Put_fields(WriteOptions(), key, fields).ok());

    // 删除数据
    ASSERT_TRUE(db->Delete(WriteOptions(), key));

    // 验证数据已被删除
    FieldArray retrieved_fields;
    Status s = db->Get_fields(ReadOptions(), key, &retrieved_fields);
    ASSERT_FALSE(s.ok()); // 数据应该不存在

    // 清理数据库
    delete db;
}

TEST(TestNewDB, QueryByIndexTest) {
    // 创建 NewDB 实例
    NewDB* db;
    ASSERT_TRUE(OpenDB(testdbname, &db).ok());

    // 创建索引字段
    db->CreateIndexOnField("address");

    // 插入测试数据
    std::string key1 = "k_4";
    FieldArray fields1 = {
        {"name", "Customer#000000004"},
        {"address", "AddressToFind"},
        {"phone", "25-987-654-3210"}
    };
    ASSERT_TRUE(db->Put_fields(WriteOptions(), key1, fields1).ok());

    // 查询索引
    Field field_to_query{"address", "AddressToFind"};
    std::vector<std::string> matching_keys = db->QueryByIndex(field_to_query);

    // 验证查询结果
    ASSERT_EQ(matching_keys.size(), 1);
    EXPECT_EQ(matching_keys[0], key1);

    // 清理数据库
    delete db;
}

TEST(TestNewDB, DeleteIndexTest) {
    // 创建 NewDB 实例
    NewDB* db;
    ASSERT_TRUE(OpenDB(testdbname, &db).ok());

    // 创建索引字段
    db->CreateIndexOnField("address");

    // 插入测试数据
    std::string key1 = "k_5";
    FieldArray fields1 = {
        {"name", "Customer#000000005"},
        {"address", "AddressToDeleteIndex"},
        {"phone", "25-123-456-7890"}
    };
    ASSERT_TRUE(db->Put_fields(WriteOptions(), key1, fields1).ok());

    // 删除索引
    ASSERT_TRUE(db->DeleteIndex("address:AddressToDeleteIndex_k_5"));

    // 尝试查询已删除的索引
    Field field_to_query{"address", "AddressToDeleteIndex"};
    std::vector<std::string> matching_keys = db->QueryByIndex(field_to_query);

    // 验证查询结果为空
    EXPECT_TRUE(matching_keys.empty());

    // 清理数据库
    delete db;
}

TEST(TestNewDB, UpdateFieldsAndQueryIndexTest) {
    // 创建 NewDB 实例
    NewDB* db;
    ASSERT_TRUE(OpenDB(testdbname, &db).ok());

    // 创建索引字段
    db->CreateIndexOnField("address");

    // 插入初始数据
    std::string key = "k_6";
    FieldArray initial_fields = {
        {"name", "Customer#000000006"},
        {"address", "InitialAddress"},
        {"phone", "25-987-654-3210"}
    };
    ASSERT_TRUE(db->Put_fields(WriteOptions(), key, initial_fields).ok());

    // 验证初始数据的索引查询
    Field query_field1{"address", "InitialAddress"};
    std::vector<std::string> matching_keys = db->QueryByIndex(query_field1);
    ASSERT_EQ(matching_keys.size(), 1);
    EXPECT_EQ(matching_keys[0], key);

    // 更新数据
    FieldArray updated_fields = {
        {"name", "Customer#000000006"},
        {"address", "UpdatedAddress"},
        {"phone", "25-987-654-3210"}
    };
    ASSERT_TRUE(db->Put_fields(WriteOptions(), key, updated_fields).ok());

    // 获取并验证字段数据
    FieldArray retrieved_fields;

    db->Get_fields(ReadOptions(), key, &retrieved_fields);
    EXPECT_EQ(retrieved_fields.size(), updated_fields.size());
    
    // 验证插入的每个字段
    for (size_t i = 0; i < updated_fields.size(); ++i) {
        EXPECT_EQ(updated_fields[i].first, retrieved_fields[i].first);  // 字段名
        EXPECT_EQ(updated_fields[i].second, retrieved_fields[i].second); // 字段值
    }

    // 验证新的 address 字段值存在于索引中
    Field query_field2{"address", "UpdatedAddress"};
    matching_keys = db->QueryByIndex(query_field2);
    ASSERT_EQ(matching_keys.size(), 1);
    EXPECT_EQ(matching_keys[0], key);

    // 验证旧的 address 字段值不再存在于索引中
    matching_keys = db->QueryByIndex(query_field1);
    ASSERT_EQ(matching_keys.size(), 0);
    EXPECT_TRUE(matching_keys.empty());


    // 清理数据库
    // db->Delete(WriteOptions(), "k_1");
    // db->Delete(WriteOptions(), "k_2");
    // db->Delete(WriteOptions(), "k_3");
    // db->Delete(WriteOptions(), "k_4");
    // db->Delete(WriteOptions(), "k_5");
    // db->Delete(WriteOptions(), "k_6");

    delete db;
}

// 主函数运行所有测试
int main(int argc, char** argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
