// 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 <brpc/controller.h>
#include <brpc/server.h>
#include <foundationdb/fdb_c_options.g.h>
#include <foundationdb/fdb_c_types.h>
#include <gen_cpp/cloud.pb.h>
#include <gtest/gtest.h>

#include <chrono>
#include <cstdint>
#include <cstdlib>
#include <iostream>
#include <memory>

#include "common/bvars.h"
#include "common/config.h"
#include "common/logging.h"
#include "cpp/sync_point.h"
#include "meta-service/meta_service.h"
#include "meta-store/txn_kv.h"

using namespace doris;

static std::unique_ptr<cloud::MetaServiceProxy> create_meta_service() {
    std::shared_ptr<cloud::TxnKv> txn_kv = std::make_unique<cloud::FdbTxnKv>();
    [&]() { ASSERT_EQ(txn_kv->init(), 0); }();

    auto rate_limiter = std::make_shared<cloud::RateLimiter>();
    auto rc_mgr = std::make_shared<cloud::ResourceManager>(txn_kv);
    [&]() { ASSERT_EQ(rc_mgr->init(), 0); }();
    auto snapshot_manager = std::make_shared<cloud::SnapshotManager>(txn_kv);

    auto meta_service_impl = std::make_unique<cloud::MetaServiceImpl>(txn_kv, rc_mgr, rate_limiter,
                                                                      snapshot_manager);
    return std::make_unique<cloud::MetaServiceProxy>(std::move(meta_service_impl));
}

static std::unique_ptr<cloud::MetaServiceProxy> meta_service;

int main(int argc, char** argv) {
    const std::string conf_file = "doris_cloud.conf";
    if (!cloud::config::init(conf_file.c_str(), true)) {
        std::cerr << "failed to init config file, conf=" << conf_file << std::endl;
        return -1;
    }

    if (!cloud::init_glog("fdb_injection_test")) {
        std::cerr << "failed to init glog" << std::endl;
        return -1;
    }

    ::testing::InitGoogleTest(&argc, argv);

    cloud::config::enable_txn_store_retry = true;
    cloud::config::txn_store_retry_times = 100;
    cloud::config::txn_store_retry_base_intervals_ms = 1;
    cloud::config::fdb_cluster_file_path = "fdb.cluster";
    cloud::config::write_schema_kv = true;
    cloud::config::enable_check_instance_id = false;
    cloud::config::enable_loopback_address_for_ms = true;

    auto sp = SyncPoint::get_instance();
    sp->enable_processing();
    sp->set_call_back("encrypt_ak_sk:get_encryption_key", [](auto&& args) {
        auto* ret = try_any_cast<int*>(args[0]);
        *ret = 0;
        auto* key = try_any_cast<std::string*>(args[1]);
        *key = "test";
        auto* key_id = try_any_cast<int64_t*>(args[2]);
        *key_id = 1;
    });
    sp->set_call_back("decrypt_ak_sk:get_encryption_key", [](auto&& args) {
        auto* key = try_any_cast<std::string*>(args[0]);
        *key = "test";
        auto* ret = try_any_cast<int*>(args[1]);
        *ret = 0;
    });
    sp->set_call_back("MetaServiceProxy::call_impl_duration_ms",
                      [](auto&& args) { *try_any_cast<uint64_t*>(args[0]) = 0; });
    sp->set_call_back("put_schema_kv:schema_key_exists_return",
                      [](auto&& args) { *try_any_cast<bool*>(args.back()) = true; });
    sp->set_call_back("resource_manager::set_safe_drop_time",
                      [](auto&& args) { *try_any_cast<int64_t*>(args[0]) = -1; });

    meta_service = create_meta_service();

    int ret = RUN_ALL_TESTS();
    if (ret != 0) {
        std::cerr << "run first round of tests failed" << std::endl;
        return ret;
    }

    std::vector<std::string> sync_points {
            "transaction:init:create_transaction_err",
            "transaction:commit:get_err",
            "transaction:get:get_err",
            "transaction:get_range:get_err",
            "transaction:get_read_version:get_err",
            "range_get_iterator:init:get_keyvalue_array_err",
    };

    // See
    // 1. https://apple.github.io/foundationdb/api-error-codes.html#developer-guide-error-codes
    // 2. FDB source code: flow/include/flow/error_definitions.h
    std::vector<fdb_error_t> retryable_not_committed {
            // future version
            1009,
            // process_behind
            1037,
            // database locked
            1038,
            // commit_proxy_memory_limit_exceeded
            1042,
            // batch_transaction_throttled
            1051,
            // grv_proxy_memory_limit_exceeded
            1078,
            // tag_throttled
            1213,
            // proxy_tag_throttled
            1223,
    };

    for (auto err : retryable_not_committed) {
        if (!fdb_error_predicate(FDB_ERROR_PREDICATE_RETRYABLE_NOT_COMMITTED, err)) {
            LOG_WARNING("skip unknown err").tag("err", err).tag("msg", fdb_get_error(err));
            continue;
        }
        for (auto&& name : sync_points) {
            for (auto&& clear_name : sync_points) {
                sp->clear_call_back(clear_name);
            }

            auto count = std::make_shared<std::atomic<uint64_t>>(0);
            auto inject_at = std::make_shared<std::atomic<uint64_t>>(0);
            sp->set_call_back(name, [=](auto&& args) mutable {
                size_t n = count->fetch_add(1);
                if (n == *inject_at) {
                    *try_any_cast<fdb_error_t*>(args[0]) = err;
                }
            });
            sp->set_call_back("MetaServiceProxy::call_impl:1", [=](auto&&) {
                // For each RPC invoking, inject every fdb txn kv call.
                count->store(0);
                inject_at->store(0);
            });
            sp->set_call_back("MetaServiceProxy::call_impl:2", [=](auto&&) {
                count->store(0);
                inject_at->fetch_add(1);
            });

            ret = RUN_ALL_TESTS();
            if (ret != 0) {
                std::cerr << "run test failed, sync_point=" << name << ", err=" << err
                          << ", msg=" << fdb_get_error(err) << std::endl;
                return ret;
            }
        }
    }

    meta_service.reset();

    return 0;
}

namespace doris::cloud {

using Status = MetaServiceResponseStatus;

static std::string cloud_unique_id(const std::string& instance_id) {
    // degraded format
    return fmt::format("1:{}:unique_id", instance_id);
}

static int create_instance(MetaService* service, const std::string& instance_id) {
    CreateInstanceRequest req;
    CreateInstanceResponse resp;
    req.set_instance_id(instance_id);
    req.set_user_id("user_id");
    req.set_name(fmt::format("instance-{}", instance_id));
    req.set_sse_enabled(false);

    auto* obj_info = req.mutable_obj_info();
    obj_info->set_ak("access-key");
    obj_info->set_sk("secret-key");
    obj_info->set_bucket("cloud-test-bucket");
    obj_info->set_prefix("cloud-test");
    obj_info->set_endpoint("endpoint");
    obj_info->set_external_endpoint("endpoint");
    obj_info->set_region("region");
    obj_info->set_provider(ObjectStoreInfoPB_Provider_COS);

    brpc::Controller ctrl;
    service->create_instance(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("create instance")
                .tag("instance_id", instance_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        return -1;
    }

    auto code = resp.status().code();
    if (code != cloud::MetaServiceCode::OK && code != cloud::MetaServiceCode::ALREADY_EXISTED) {
        LOG_ERROR("create instance")
                .tag("instance_id", instance_id)
                .tag("code", code)
                .tag("msg", resp.status().msg());
        return -1;
    }

    return 0;
}

static int remove_instance(MetaService* service, const std::string& instance_id) {
    AlterInstanceRequest req;
    AlterInstanceResponse resp;
    req.set_instance_id(instance_id);
    req.set_op(AlterInstanceRequest_Operation_DROP);

    brpc::Controller ctrl;
    service->alter_instance(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("alter_instance")
                .tag("instance_id", instance_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        return -1;
    }

    auto code = resp.status().code();
    if (code != cloud::MetaServiceCode::OK) {
        LOG_ERROR("create instance")
                .tag("instance_id", instance_id)
                .tag("code", code)
                .tag("msg", resp.status().msg());
        return -1;
    }

    return 0;
}

static int add_cluster(MetaService* service, const std::string& instance_id) {
    bool retry = false;
    while (true) {
        brpc::Controller ctrl;
        cloud::AlterClusterRequest req;
        cloud::AlterClusterResponse resp;

        req.set_instance_id(instance_id);
        req.set_op(cloud::AlterClusterRequest_Operation::AlterClusterRequest_Operation_ADD_CLUSTER);
        auto* cluster = req.mutable_cluster();
        auto name = fmt::format("instance_{}_cluster", instance_id);
        cluster->set_cluster_id(name);
        cluster->set_cluster_name(name);
        cluster->set_type(cloud::ClusterPB_Type::ClusterPB_Type_SQL);
        cluster->set_desc("cluster description");
        auto* node = cluster->add_nodes();
        node->set_ip("0.0.0.0");
        node->set_node_type(cloud::NodeInfoPB_NodeType::NodeInfoPB_NodeType_FE_MASTER);
        node->set_cloud_unique_id(cloud_unique_id(instance_id));
        node->set_edit_log_port(123);
        node->set_heartbeat_port(456);
        node->set_name("default_node");

        service->alter_cluster(&ctrl, &req, &resp, nullptr);
        if (ctrl.Failed()) {
            LOG_ERROR("alter cluster")
                    .tag("instance_id", instance_id)
                    .tag("code", ctrl.ErrorCode())
                    .tag("msg", ctrl.ErrorText());
            return -1;
        }

        auto code = resp.status().code();
        if (code == cloud::MetaServiceCode::OK) {
            return 0;
        } else if (code == cloud::MetaServiceCode::ALREADY_EXISTED) {
            if (!retry) {
                retry = true;
                req.set_op(cloud::AlterClusterRequest_Operation::
                                   AlterClusterRequest_Operation_DROP_CLUSTER);
                ctrl.Reset();
                service->alter_cluster(&ctrl, &req, &resp, nullptr);
            }
            return 0;
        } else {
            LOG_ERROR("add default cluster")
                    .tag("instance_id", instance_id)
                    .tag("code", code)
                    .tag("msg", resp.status().msg());
            return -1;
        }
    }
}

static int drop_cluster(MetaService* service, const std::string& instance_id) {
    AlterClusterRequest req;
    AlterClusterResponse resp;
    req.set_instance_id(instance_id);
    req.set_op(AlterClusterRequest_Operation_DROP_CLUSTER);
    auto cluster = req.mutable_cluster();
    cluster->set_cluster_id(fmt::format("instance_{}_cluster", instance_id));

    brpc::Controller ctrl;
    service->alter_cluster(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("drop cluster")
                .tag("instance_id", instance_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        return -1;
    }
    if (resp.status().code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("drop cluster")
                .tag("instance_id", instance_id)
                .tag("code", resp.status().code())
                .tag("msg", resp.status().msg());
        return -1;
    }
    return 0;
}

static doris::TabletMetaCloudPB add_tablet(int64_t table_id, int64_t index_id, int64_t partition_id,
                                           int64_t tablet_id) {
    doris::TabletMetaCloudPB tablet;
    tablet.set_table_id(table_id);
    tablet.set_index_id(index_id);
    tablet.set_partition_id(partition_id);
    tablet.set_tablet_id(tablet_id);
    auto schema = tablet.mutable_schema();
    schema->set_schema_version(1);
    auto first_rowset = tablet.add_rs_metas();
    first_rowset->set_rowset_id(0); // required
    first_rowset->set_rowset_id_v2(std::to_string(1));
    first_rowset->set_start_version(0);
    first_rowset->set_end_version(1);
    first_rowset->mutable_tablet_schema()->CopyFrom(*schema);
    return tablet;
}

static int create_tablet(MetaService* meta_service, const std::string& instance_id, int64_t db_id,
                         int64_t table_id, int64_t index_id, int64_t partition_id,
                         int64_t tablet_id) {
    if (tablet_id < 0) {
        LOG_ERROR("invalid tablet id").tag("id", tablet_id);
        return -1;
    }

    brpc::Controller ctrl;
    cloud::CreateTabletsRequest req;
    cloud::CreateTabletsResponse resp;
    req.set_cloud_unique_id(cloud_unique_id(instance_id));
    req.set_db_id(db_id);
    req.add_tablet_metas()->CopyFrom(add_tablet(table_id, index_id, partition_id, tablet_id));
    meta_service->create_tablets(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("create_tablets")
                .tag("instance_id", instance_id)
                .tag("tablet_id", tablet_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        return -1;
    }
    if (resp.status().code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("create tablet")
                .tag("instance_id", instance_id)
                .tag("tablet_id", tablet_id)
                .tag("code", resp.status().code())
                .tag("msg", resp.status().msg());
        return -1;
    }
    return 0;
}

static Status begin_txn(MetaService* service, const std::string& instance_id, std::string label,
                        int64_t db_id, const std::vector<uint64_t>& tablet_ids, int64_t* txn_id) {
    brpc::Controller ctrl;
    cloud::BeginTxnRequest req;
    cloud::BeginTxnResponse resp;
    req.set_cloud_unique_id(cloud_unique_id(instance_id));
    auto* txn_info = req.mutable_txn_info();
    txn_info->set_label(label);
    txn_info->set_db_id(db_id);
    txn_info->mutable_table_ids()->Add(tablet_ids.begin(), tablet_ids.end());
    txn_info->set_timeout_ms(1000 * 60 * 60);

    service->begin_txn(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("begin_txn")
                .tag("instance_id", instance_id)
                .tag("table_ids", fmt::format("{}", fmt::join(tablet_ids, ",")))
                .tag("label", label)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        Status status;
        status.set_code(MetaServiceCode::UNDEFINED_ERR);
        status.set_msg(ctrl.ErrorText());
        return status;
    }

    *txn_id = resp.txn_id();
    return resp.status();
}

static Status commit_txn(MetaService* service, const std::string& instance_id, int64_t txn_id,
                         int64_t db_id) {
    brpc::Controller ctrl;
    cloud::CommitTxnRequest req;
    cloud::CommitTxnResponse resp;
    req.set_cloud_unique_id(cloud_unique_id(instance_id));
    req.set_db_id(db_id);
    req.set_txn_id(txn_id);

    service->commit_txn(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("commit_txn")
                .tag("instance_id", instance_id)
                .tag("txn_id", txn_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        Status status;
        status.set_code(MetaServiceCode::UNDEFINED_ERR);
        status.set_msg(ctrl.ErrorText());
        return status;
    }

    return resp.status();
}

static doris::RowsetMetaCloudPB create_rowset(int64_t tablet_id, std::string rowset_id,
                                              int64_t txn_id, int64_t index_id,
                                              int64_t partition_id, int64_t version = -1,
                                              int num_rows = 100) {
    doris::RowsetMetaCloudPB rowset;
    rowset.set_rowset_id(0); // required
    rowset.set_rowset_id_v2(rowset_id);
    rowset.set_index_id(index_id);
    rowset.set_partition_id(partition_id);
    rowset.set_tablet_id(tablet_id);
    rowset.set_txn_id(txn_id);
    if (version >= 0) {
        rowset.set_start_version(version);
        rowset.set_end_version(version);
    }
    rowset.set_num_segments(1);
    rowset.set_num_rows(num_rows);
    rowset.set_data_disk_size(num_rows * 100);
    rowset.set_txn_expiration(10000);
    rowset.set_schema_version(1);

    // auto* schema = rowset.mutable_tablet_schema();
    // schema->set_schema_version(1);
    // schema->set_disable_auto_compaction(true);

    auto* bound = rowset.add_segments_key_bounds();
    bound->set_min_key("min_key");
    bound->set_max_key("max_key");

    return rowset;
}

static Status prepare_rowset(MetaService* service, const std::string& instance_id, int64_t txn_id,
                             int64_t tablet_id, std::string rowset_id, int64_t index_id,
                             int64_t partition_id) {
    brpc::Controller ctrl;
    cloud::CreateRowsetRequest req;
    cloud::CreateRowsetResponse resp;
    req.set_cloud_unique_id(cloud_unique_id(instance_id));
    req.mutable_rowset_meta()->CopyFrom(
            create_rowset(tablet_id, rowset_id, txn_id, index_id, partition_id));

    service->prepare_rowset(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("prepare_rowset")
                .tag("instance_id", instance_id)
                .tag("txn_id", txn_id)
                .tag("tablet_id", tablet_id)
                .tag("rowset_id", rowset_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        Status status;
        status.set_code(MetaServiceCode::UNDEFINED_ERR);
        status.set_msg(ctrl.ErrorText());
        return status;
    }
    return resp.status();
}

static Status commit_rowset(MetaService* service, const std::string& instance_id, int64_t txn_id,
                            int64_t tablet_id, std::string rowset_id, int64_t index_id,
                            int64_t partition_id) {
    brpc::Controller ctrl;
    cloud::CreateRowsetRequest req;
    cloud::CreateRowsetResponse resp;
    req.set_cloud_unique_id(cloud_unique_id(instance_id));
    req.mutable_rowset_meta()->CopyFrom(
            create_rowset(tablet_id, rowset_id, txn_id, index_id, partition_id));
    LOG_INFO("send commit rowset request");

    service->commit_rowset(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("commit_rowset")
                .tag("instance_id", instance_id)
                .tag("txn_id", txn_id)
                .tag("tablet_id", tablet_id)
                .tag("rowset_id", rowset_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());

        Status status;
        status.set_code(MetaServiceCode::UNDEFINED_ERR);
        status.set_msg(ctrl.ErrorText());
        return status;
    }
    return resp.status();
}

static Status insert_rowset(MetaService* service, const std::string& instance_id, int64_t txn_id,
                            int64_t tablet_id, std::string rowset_id, int64_t index_id,
                            int64_t partition_id) {
    auto status = prepare_rowset(service, instance_id, txn_id, tablet_id, rowset_id, index_id,
                                 partition_id);
    if (status.code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("prepare_rowset")
                .tag("instance_id", instance_id)
                .tag("txn_id", txn_id)
                .tag("tablet_id", tablet_id)
                .tag("rowset_id", rowset_id)
                .tag("code", status.code())
                .tag("msg", status.msg());
        if (status.code() != cloud::MetaServiceCode::ALREADY_EXISTED) {
            return status;
        }
    }

    LOG_INFO("prepare rowset").tag("code", status.code()).tag("msg", status.msg());
    status = commit_rowset(service, instance_id, txn_id, tablet_id, rowset_id, index_id,
                           partition_id);
    if (status.code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("commit_rowset")
                .tag("instance_id", instance_id)
                .tag("txn_id", txn_id)
                .tag("tablet_id", tablet_id)
                .tag("rowset_id", rowset_id)
                .tag("code", status.code())
                .tag("msg", status.msg());
        return status;
    }

    return Status();
}

static Status copy_into(MetaService* service, const std::string& instance_id, std::string label,
                        int64_t db_id, int64_t index_id, int64_t partition_id,
                        const std::vector<uint64_t>& tablet_ids) {
    int64_t txn_id = 0;
    auto status = begin_txn(service, instance_id, label, db_id, tablet_ids, &txn_id);
    if (status.code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("begin_txn")
                .tag("instance_id", instance_id)
                .tag("label", label)
                .tag("code", status.code())
                .tag("msg", status.msg());
        return status;
    }

    for (uint64_t tablet_id : tablet_ids) {
        auto rowset_id = fmt::format("rowset_{}_{}", label, tablet_id);
        status = insert_rowset(service, instance_id, txn_id, tablet_id, rowset_id, index_id,
                               partition_id);
        if (status.code() != cloud::MetaServiceCode::OK) {
            return status;
        }
    }

    status = commit_txn(service, instance_id, txn_id, db_id);
    if (status.code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("commit_txn")
                .tag("instance_id", instance_id)
                .tag("label", label)
                .tag("code", status.code())
                .tag("msg", status.msg());
        return status;
    }

    return Status();
}

static Status get_read_version(MetaService* service, const std::string& instance_id,
                               int64_t* version) {
    brpc::Controller ctrl;
    cloud::GetCurrentMaxTxnRequest req;
    cloud::GetCurrentMaxTxnResponse resp;
    req.set_cloud_unique_id(cloud_unique_id(instance_id));
    service->get_current_max_txn_id(&ctrl, &req, &resp, nullptr);

    if (ctrl.Failed()) {
        LOG_ERROR("get read version")
                .tag("instance_id", instance_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        Status status;
        status.set_code(MetaServiceCode::UNDEFINED_ERR);
        status.set_msg(ctrl.ErrorText());
        return status;
    }

    auto status = resp.status();
    if (status.code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("get read version")
                .tag("instance_id", instance_id)
                .tag("code", status.code())
                .tag("msg", status.msg());
        return status;
    }

    *version = resp.current_max_txn_id();

    return Status();
}

static Status get_version(MetaService* service, const std::string& instance_id, int64_t db_id,
                          int64_t partition_id, int64_t table_id, int64_t* version) {
    brpc::Controller ctrl;
    cloud::GetVersionRequest req;
    cloud::GetVersionResponse resp;
    req.set_cloud_unique_id(cloud_unique_id(instance_id));
    req.set_db_id(db_id);
    req.set_partition_id(partition_id);
    req.set_table_id(table_id);

    service->get_version(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("get version")
                .tag("instance_id", instance_id)
                .tag("db_id", db_id)
                .tag("partition_id", partition_id)
                .tag("table_id", table_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        Status status;
        status.set_code(MetaServiceCode::UNDEFINED_ERR);
        status.set_msg(ctrl.ErrorText());
        return status;
    }

    auto status = resp.status();
    if (status.code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("get version")
                .tag("instance_id", instance_id)
                .tag("db_id", db_id)
                .tag("partition_id", partition_id)
                .tag("table_id", table_id)
                .tag("code", status.code())
                .tag("msg", status.msg());
        return status;
    }

    *version = resp.version();

    return Status();
}

static Status get_tablet_meta(MetaService* service, const std::string& instance_id,
                              int64_t tablet_id) {
    brpc::Controller ctrl;
    cloud::GetTabletRequest req;
    cloud::GetTabletResponse resp;
    req.set_cloud_unique_id(cloud_unique_id(instance_id));
    req.set_tablet_id(tablet_id);
    service->get_tablet(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("get_tablet")
                .tag("instance_id", instance_id)
                .tag("tablet_id", tablet_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        Status status;
        status.set_code(MetaServiceCode::UNDEFINED_ERR);
        status.set_msg(ctrl.ErrorText());
        return status;
    }

    auto status = resp.status();
    if (status.code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("get_tablet")
                .tag("instance_id", instance_id)
                .tag("tablet_id", tablet_id)
                .tag("code", status.code())
                .tag("msg", status.msg());
        return status;
    }

    return Status();
}

static Status get_tablet_stats(MetaService* service, const std::string& instance_id,
                               int64_t tablet_id, cloud::TabletStatsPB* stats) {
    brpc::Controller ctrl;
    cloud::GetTabletStatsRequest req;
    cloud::GetTabletStatsResponse resp;
    req.set_cloud_unique_id(cloud_unique_id(instance_id));
    auto* tablet_idx = req.mutable_tablet_idx()->Add();
    tablet_idx->set_tablet_id(tablet_id);
    service->get_tablet_stats(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("get tablet stats")
                .tag("instance_id", instance_id)
                .tag("tablet_id", tablet_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        Status status;
        status.set_code(MetaServiceCode::UNDEFINED_ERR);
        status.set_msg(ctrl.ErrorText());
        return status;
    }

    auto status = resp.status();
    if (status.code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("get_tablet_stats")
                .tag("instance_id", instance_id)
                .tag("tablet_id", tablet_id)
                .tag("code", status.code())
                .tag("msg", status.msg());
        return status;
    }

    stats->CopyFrom(resp.tablet_stats().at(0));

    return Status();
}

static Status get_rowset_meta(MetaService* service, const std::string& instance_id,
                              int64_t tablet_id, int64_t version,
                              const cloud::TabletStatsPB& stats) {
    brpc::Controller ctrl;
    cloud::GetRowsetRequest req;
    cloud::GetRowsetResponse resp;
    req.set_cloud_unique_id(cloud_unique_id(instance_id));
    req.mutable_idx()->set_tablet_id(tablet_id);
    req.set_start_version(0);
    req.set_end_version(version);
    req.set_base_compaction_cnt(stats.base_compaction_cnt());
    req.set_cumulative_compaction_cnt(stats.cumulative_compaction_cnt());
    req.set_cumulative_point(stats.cumulative_point());
    service->get_rowset(&ctrl, &req, &resp, nullptr);
    if (ctrl.Failed()) {
        LOG_ERROR("get_rowset")
                .tag("instance_id", instance_id)
                .tag("tablet_id", tablet_id)
                .tag("code", ctrl.ErrorCode())
                .tag("msg", ctrl.ErrorText());
        Status status;
        status.set_code(MetaServiceCode::UNDEFINED_ERR);
        status.set_msg(ctrl.ErrorText());
        return status;
    }

    auto status = resp.status();
    if (status.code() != cloud::MetaServiceCode::OK) {
        LOG_ERROR("get_rowset")
                .tag("instance_id", instance_id)
                .tag("tablet_id", tablet_id)
                .tag("code", status.code())
                .tag("msg", status.msg());
        return status;
    }

    return Status();
}

TEST(FdbInjectionTest, AllInOne) {
    auto now = std::chrono::high_resolution_clock::now();
    auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch());
    std::string instance_id = fmt::format("fdb_injection_test_{}", ns.count());
    int ret = create_instance(meta_service.get(), instance_id);
    ASSERT_EQ(ret, 0);

    ret = add_cluster(meta_service.get(), instance_id);
    ASSERT_EQ(ret, 0);

    int64_t db_id = 1;
    int64_t table_id = 1;
    int64_t index_id = 1;
    int64_t partition_id = 1;
    std::vector<uint64_t> tablet_ids;
    for (int64_t tablet_id = 1; tablet_id <= 10; ++tablet_id) {
        ret = create_tablet(meta_service.get(), instance_id, db_id, table_id, index_id,
                            partition_id, tablet_id);
        ASSERT_EQ(ret, 0) << tablet_id;
        tablet_ids.push_back(tablet_id);
    }

    // Run copy into.
    std::string label = fmt::format("{}-label", instance_id);
    auto status = copy_into(meta_service.get(), instance_id, label, db_id, index_id, partition_id,
                            tablet_ids);
    ASSERT_EQ(status.code(), MetaServiceCode::OK) << status.msg();

    // Get version
    int64_t version = 0;
    status = get_version(meta_service.get(), instance_id, db_id, partition_id, table_id, &version);
    ASSERT_EQ(status.code(), MetaServiceCode::OK) << status.msg();

    // Get tablet meta & stats
    TabletStatsPB stats;
    status = get_tablet_stats(meta_service.get(), instance_id, tablet_ids.back(), &stats);
    ASSERT_EQ(status.code(), MetaServiceCode::OK) << status.msg();

    status = get_tablet_meta(meta_service.get(), instance_id, tablet_ids.back());
    ASSERT_EQ(status.code(), MetaServiceCode::OK) << status.msg();

    // Get rowset metas.
    status = get_rowset_meta(meta_service.get(), instance_id, tablet_ids.back(), version, stats);
    ASSERT_EQ(status.code(), MetaServiceCode::OK) << status.msg();

    int64_t max_txn_id = 0;
    status = get_read_version(meta_service.get(), instance_id, &max_txn_id);
    ASSERT_EQ(status.code(), MetaServiceCode::OK) << status.msg();
    ASSERT_GE(max_txn_id, version);

    ret = drop_cluster(meta_service.get(), instance_id);
    ASSERT_EQ(ret, 0);

    ret = remove_instance(meta_service.get(), instance_id);
    ASSERT_EQ(ret, 0);
}

} // namespace doris::cloud
