// 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.
#pragma once

#include <memory>
#include <string>
#include <unordered_set>
#include <vector>

#include "kudu/client/shared_ptr.h" // IWYU pragma: keep
#include "kudu/integration-tests/cluster_itest_util.h"
#include "kudu/integration-tests/mini_cluster_fs_inspector.h"
#include "kudu/mini-cluster/external_mini_cluster.h"
#include "kudu/tserver/tablet_server-test-base.h"
#include "kudu/util/random.h"
#include "kudu/util/status.h"

namespace kudu {

class MonoDelta;

namespace client {
class KuduClient;
class KuduTable;
} // namespace client

namespace tserver {

// A base for tablet server integration tests.
class TabletServerIntegrationTestBase : public TabletServerTestBase {
 public:
  TabletServerIntegrationTestBase();

  void SetUp() override;

  void AddExtraFlags(const std::string& flags_str,
                     std::vector<std::string>* flags);

  void CreateCluster(const std::string& data_root_path,
                     std::vector<std::string> non_default_ts_flags = {},
                     std::vector<std::string> non_default_master_flags = {},
                     cluster::LocationInfo location_info = {});

  // Creates TSServerDetails instance for each TabletServer and stores them
  // in 'tablet_servers_'.
  void CreateTSProxies();

  // Waits that all replicas for a all tablets of 'table_id' table are online
  // and creates the tablet_replicas_ map.
  void WaitForReplicasAndUpdateLocations(const std::string& table_id = kTableId);

  // Returns the last committed leader of the consensus configuration. Tries to get it from master
  // but then actually tries to the get the committed consensus configuration to make sure.
  itest::TServerDetails* GetLeaderReplicaOrNull(const std::string& tablet_id);

  // For the last committed consensus configuration, return the last committed
  // leader of the consensus configuration and its followers.
  Status GetTabletLeaderAndFollowers(const std::string& tablet_id,
                                     itest::TServerDetails** leader,
                                     std::vector<itest::TServerDetails*>* followers);

  Status GetLeaderReplicaWithRetries(const std::string& tablet_id,
                                     itest::TServerDetails** leader,
                                     int max_attempts = 100);

  Status GetTabletLeaderUUIDFromMaster(const std::string& tablet_id,
                                       std::string* leader_uuid);

  itest::TServerDetails* GetReplicaWithUuidOrNull(const std::string& tablet_id,
                                                  const std::string& uuid);

  // Wait for tablet servers to start up.
  void WaitForTabletServers();

  // Wait for tablet servers to start and all replicas are available for all
  // the test table's tablets.
  void WaitForTSAndReplicas(const std::string& table_id = kTableId);

  // Removes a set of servers from the replicas_ list.
  // Handy for controlling who to validate against after killing servers.
  void PruneFromReplicas(const std::unordered_set<std::string>& uuids);

  void GetOnlyLiveFollowerReplicas(const std::string& tablet_id,
                                   std::vector<itest::TServerDetails*>* followers);

  Status ShutdownServerWithUUID(const std::string& uuid);

  Status RestartServerWithUUID(const std::string& uuid);

  // Since we're fault-tolerant we might mask when a tablet server is
  // dead. This returns Status::IllegalState() if fewer than 'num_tablet_servers'
  // are alive.
  Status CheckTabletServersAreAlive(int num_tablet_servers);

  void TearDown() override;

  void CreateClient(client::sp::shared_ptr<client::KuduClient>* client);

  // Create a table with a single tablet, with 'num_replicas'.
  void CreateTable(const std::string& table_id = kTableId);

  // Starts an external cluster with a single tablet and a number of replicas
  // equal to 'FLAGS_num_replicas'. The caller can pass 'ts_flags' and
  // 'master_flags' to specify non-default flags to pass to the tablet servers
  // and masters respectively. For location-aware tests scenarios, location
  // mapping rules can be passed using the 'location_info' parameter.
  void BuildAndStart(std::vector<std::string> ts_flags = {},
                     std::vector<std::string> master_flags = {},
                     cluster::LocationInfo location_info = {},
                     bool create_table = true);

  void AssertAllReplicasAgree(int expected_result_count);

  // Check for and restart any TS that have crashed.
  // Returns the number of servers restarted.
  int RestartAnyCrashedTabletServers();

  // Assert that no tablet servers have crashed.
  // Tablet servers that have been manually Shutdown() are allowed.
  void AssertNoTabletServersCrashed();

  // Find the tablet leader replica and wait for at least one operation
  // committed in current term. This is useful when finding a leader replica
  // to commence a Raft configuration change. Otherwise, any Raft configuration
  // change attempt ends up with error:
  // 'Illegal state: Leader has not yet committed an operation in its own term'.
  Status WaitForLeaderWithCommittedOp(const std::string& tablet_id,
                                      const MonoDelta& timeout,
                                      itest::TServerDetails** leader);

  // Get UUIDs of tablet servers that have a replica of the tablet identified
  // by the 'tablet_id' parameter. The result is sorted in ascending order.
  std::vector<std::string> GetServersWithReplica(const std::string& tablet_id) const;

  // Get UUIDs of tablet servers that do not have replicas of the tablet
  // identified by the 'tablet_id' parameter. The result is sorted in ascending order.
  std::vector<std::string> GetServersWithoutReplica(const std::string& tablet_id) const;

 protected:
  std::unique_ptr<cluster::ExternalMiniCluster> cluster_;
  std::unique_ptr<itest::MiniClusterFsInspector> inspect_;

  // Maps server uuid to TServerDetails
  itest::TabletServerMap tablet_servers_;
  // Maps tablet to all replicas.
  itest::TabletReplicaMap tablet_replicas_;

  client::sp::shared_ptr<client::KuduClient> client_;
  client::sp::shared_ptr<client::KuduTable> table_;
  std::string tablet_id_;

  ThreadSafeRandom random_;
};

}  // namespace tserver
}  // namespace kudu
