// 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 <cstdint>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <boost/optional/optional.hpp>
#include <glog/logging.h>

#include "kudu/tablet/metadata.pb.h"
#include "kudu/tablet/tablet.pb.h"  // IWYU pragma: keep
#include "kudu/util/status.h"

namespace kudu {
namespace cluster_summary {

// The result of health check on a tablet.
// Also used to indicate the health of a table, since the health of a table is
// the health of its least healthy tablet.
enum class HealthCheckResult {
  // The tablet is healthy.
  HEALTHY,

  // The tablet has on-going tablet copies.
  RECOVERING,

  // The tablet has fewer replicas than its table's replication factor and
  // has no on-going tablet copies.
  UNDER_REPLICATED,

  // The tablet is missing a majority of its replicas and is unavailable for
  // writes. If a majority cannot be brought back online, then the tablet
  // requires manual intervention to recover.
  UNAVAILABLE,

  // There was a discrepancy among the tablets' consensus configs and the master's.
  CONSENSUS_MISMATCH,
};

const char* HealthCheckResultToString(HealthCheckResult cr);

// Possible types of consensus configs.
enum class ConsensusConfigType {
  // A config reported by the master.
  MASTER,
  // A config that has been committed.
  COMMITTED,
  // A config that has not yet been committed.
  PENDING,
};

// Representation of a consensus state.
struct ConsensusState {
  ConsensusState() = default;
  ConsensusState(ConsensusConfigType type,
                        boost::optional<int64_t> term,
                        boost::optional<int64_t> opid_index,
                        boost::optional<std::string> leader_uuid,
                        const std::vector<std::string>& voters,
                        const std::vector<std::string>& non_voters)
    : type(type),
      term(std::move(term)),
      opid_index(std::move(opid_index)),
      leader_uuid(std::move(leader_uuid)),
      voter_uuids(voters.cbegin(), voters.cend()),
      non_voter_uuids(non_voters.cbegin(), non_voters.cend()) {
   // A consensus state must have a term unless it's one sourced from the master.
   CHECK(type == ConsensusConfigType::MASTER || term);
  }

  // Two ConsensusState structs match if they have the same
  // leader_uuid, the same set of peers, and one of the following holds:
  // - at least one of them is of type MASTER
  // - they are configs of the same type and they have the same term
  bool Matches(const ConsensusState &other) const {
    bool same_leader_and_peers =
        leader_uuid == other.leader_uuid &&
        voter_uuids == other.voter_uuids &&
        non_voter_uuids == other.non_voter_uuids;
    if (type == ConsensusConfigType::MASTER ||
        other.type == ConsensusConfigType::MASTER) {
      return same_leader_and_peers;
    }
    return type == other.type && term == other.term && same_leader_and_peers;
  }

  ConsensusConfigType type;
  boost::optional<int64_t> term;
  boost::optional<int64_t> opid_index;
  boost::optional<std::string> leader_uuid;
  std::set<std::string> voter_uuids;
  std::set<std::string> non_voter_uuids;
};

// Represents the health of a server.
enum class ServerHealth {
  // The server is healthy.
  HEALTHY,

  // The server rejected attempts to communicate as unauthorized.
  UNAUTHORIZED,

  // The server can't be contacted.
  UNAVAILABLE,

  // The server reported an unexpected UUID.
  WRONG_SERVER_UUID,
};

// Return a string representation of 'sh'.
const char* ServerHealthToString(ServerHealth sh);

// Quiescing-related info.
struct QuiescingInfo {
  bool is_quiescing;
  int num_leaders;
  int num_active_scanners;
};

// A summary of a server health check.
struct ServerHealthSummary {
  std::string uuid;
  std::string address;
  std::string ts_location;
  boost::optional<std::string> version;
  boost::optional<QuiescingInfo> quiescing_info;
  ServerHealth health = ServerHealth::HEALTHY;
  Status status = Status::OK();
};

// A summary of the state of a table.
struct TableSummary {
  std::string id;
  std::string name;
  int replication_factor = 0;
  int healthy_tablets = 0;
  int recovering_tablets = 0;
  int underreplicated_tablets = 0;
  int consensus_mismatch_tablets = 0;
  int unavailable_tablets = 0;

  int TotalTablets() const {
    return healthy_tablets + recovering_tablets + underreplicated_tablets +
        consensus_mismatch_tablets + unavailable_tablets;
  }

  int UnhealthyTablets() const {
    return TotalTablets() - healthy_tablets;
  }

  // Summarize the table's status with a HealthCheckResult.
  // A table's status is determined by the health of the least healthy tablet.
  HealthCheckResult TableStatus() const {
    if (unavailable_tablets > 0) {
      return HealthCheckResult::UNAVAILABLE;
    }
    if (consensus_mismatch_tablets > 0) {
      return HealthCheckResult::CONSENSUS_MISMATCH;
    }
    if (underreplicated_tablets > 0) {
      return HealthCheckResult::UNDER_REPLICATED;
    }
    if (recovering_tablets > 0) {
      return HealthCheckResult::RECOVERING;
    }
    return HealthCheckResult::HEALTHY;
  }
};

// Types of Kudu servers.
enum class ServerType {
  MASTER,
  TABLET_SERVER,
};

// Return a string representation of 'type'.
const char* ServerTypeToString(ServerType type);

// A summary of the state of a tablet replica.
struct ReplicaSummary {
  std::string ts_uuid;
  boost::optional<std::string> ts_address;
  bool ts_healthy = false;
  bool is_leader = false;
  bool is_voter = false;
  tablet::TabletStatePB state = tablet::UNKNOWN;
  boost::optional<tablet::TabletStatusPB> status_pb;
  boost::optional<ConsensusState> consensus_state;
};

// A summary of the state of a tablet.
struct TabletSummary {
  std::string id;
  std::string table_id;
  std::string table_name;
  HealthCheckResult result;
  std::string status;
  ConsensusState master_cstate;
  std::vector<ReplicaSummary> replicas;
};

typedef std::map<std::string, ConsensusState> ConsensusStateMap;

// Container for information of cluster status.
struct ClusterStatus {

  // Health summaries for master and tablet servers.
  std::vector<ServerHealthSummary> master_summaries;
  std::vector<ServerHealthSummary> tserver_summaries;

  // Information about the master consensus configuration.
  std::vector<std::string> master_uuids;
  bool master_consensus_conflict = false;
  ConsensusStateMap master_consensus_state_map;

  // Detailed information about each table and tablet.
  // Tablet information includes consensus state.
  std::vector<TabletSummary> tablet_summaries;
  std::vector<TableSummary> table_summaries;
  std::vector<TableSummary> system_table_summaries;
};

} // namespace cluster_summary
} // namespace kudu
