#ifndef THIRD_PARTY_MILOTIC_INTERNAL_CC_AUTHZ_BMCWEB_AUTHORIZER_SINGLETON_H_
#define THIRD_PARTY_MILOTIC_INTERNAL_CC_AUTHZ_BMCWEB_AUTHORIZER_SINGLETON_H_

#include <cstddef>
#include <cstdint>
#include <map>
#include <string>
#include <string_view>
#include <unordered_set>
#include <utility>
#include <vector>

#include "tlbmc/anycast_user.h"
#include "absl/base/thread_annotations.h"
#include "absl/synchronization/mutex.h"
#include "boost/beast/http/verb.hpp"  // NOLINT
#include "authorizer_enums.h"
#include "redfish_v1.pb.h"
#include <nlohmann/json.hpp>
#include "config_parser.h"
#include "redfish_authorizer.h"
#include "redfish_authorizer_interface.h"
#include "g3/grpc_headers.h"
#include "zatar/certificate_metadata.h"

namespace milotic::authz {

// Performs dynamic authorization based on configuration files.
// It encapsulates all states and operations that're needed for BMC
// authorization.
// This class is thread-safe.
class BmcWebAuthorizerSingleton {
 public:
  struct RequestState {
    bool with_trust_bundle = true;
    bool peer_authenticated = false;
    std::unordered_set<std::string> peer_privileges;
  };

  virtual ~BmcWebAuthorizerSingleton() = default;

  // Note: the first call will initialize the function local instance. All
  // future calls won't change the state of the singleton.
  // Typical usage:
  //  // Initialize with arguments
  // BmcWebAuthorizerSingleton::Initialize(...);
  //  // Reference without arguments
  // BmcWebAuthorizerSingleton::GetInstance().CheckTarget(...);
  static BmcWebAuthorizerSingleton& Initialize(const AuthorizerOptions& options,
                                               std::string_view oauth_key_path);
  static BmcWebAuthorizerSingleton& GetInstance();

  // Checks if the peer's target matches with the BMC.
  // Shall be called in every RPC.
  grpc::Status CheckTarget(
      const grpc::AuthContext& context,
      const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata,
      const ::redfish::v1::Request& request) const;

  // Authorizes peer via its identity and the status of the request.
  // The identity of the peer can be derived from peer's X.509 SAN, or from
  //  OAuth Token.
  // Returns OK status if the request is authorized. Otherwise returns
  // corresponding error.
  grpc::Status Authorize(std::string_view uri, boost::beast::http::verb verb,
                         const RequestState& request_state) const;

  // Processes the OAuth workflow and gets peer's privileges
  // - decodes the token
  // - verifies the signature of the token
  // - verifies the peer X.509 certificate matches the subject
  // - extract peer's privileges
  grpc::Status GetPrivilegesViaOAuth(
      const grpc::AuthContext& context, const std::string& token,
      std::unordered_set<std::string>& peer_privileges) const;

  // Looks up the peer's privileges by its MTls identity and the authorization
  // configuration
  grpc::Status GetPrivilegesViaMTls(
      const grpc::AuthContext& context,
      std::unordered_set<std::string>& peer_privileges) const;

  // Reloads the authorization configuration and all credentials (GMI, OAuth
  // key, etc).
  void ReloadConfiguration();

  // Records a new subscription for the peer and returns if it is allowed.
  grpc::Status RecordNewSubscription(const PeerSpiffeIdentity& peer);
  // Records a new unsubscription for the peer.
  grpc::Status RecordNewUnsubscription(const PeerSpiffeIdentity& peer);

  static grpc::Status GetPeerIdentityFromAuthContext(
      const grpc::AuthContext& context, PeerSpiffeIdentity& peer_identity);

  // Returns the peer role from the auth context.
  // On error, peer_role will be empty.
  grpc::Status GetPeerRoleFromAuthContext(const grpc::AuthContext& context,
                                          std::string& peer_role) const;

  // Returns the sample rate limit for the peer role.
  uint64_t GetSampleRateLimit(const std::string& peer_role) const;

  // Returns feed client target address for the peer role.
  std::string GetAnycastAddress(const std::string& peer_role) const;

  // Returns the underlying Redfish authorizer through its nlohmann-free
  // decision-API interface.
  const RedfishAuthorizerInterface& GetRedfishAuthorizer() const {
    return redfish_authorizer_;
  }

  // Reloads the redfish authorizer with the given configuration path.
  void ReloadRedfishAuthorizer(const std::string& configuration_path);

  // Reloads the redfish authorizer with the current configuration path.
  void ReloadRedfishAuthorizer();

  void RegisterAnycastUser(
      const std::string& service,
      platforms_syshealth::collection::feed::AnycastUser* user);

  void DeregisterAnycastUser(const std::string& service);

  static ecclesia::Operation BoostVerbToOperation(
      boost::beast::http::verb verb);

  ecclesia::ResourceEntity GetEntityTypeFromRedfishUri(
      std::string_view uri) const;

  size_t GetNodeIndexInPatternArray(std::string_view uri) const;

  // Get current Redfish Privilege Registry
  nlohmann::json GetRedfishPrivilegeRegistry() const;

  bool IsBasePrivilegeRegistryFound() const;

  void SetBasePrivilegesFolder(std::string_view base_privileges_folder);

  // Reset GMI path, used by unit test only.
  void ReloadGmiPaths(std::string_view gmi_path);

  BmcWebAuthorizerSingleton(const AuthorizerOptions& options,
                            std::string_view oauth_key_path);

  nlohmann::json GetConfig() const;

  nlohmann::json GetPrivilegeRegistry() const;

 protected:
  std::string ReadPrimaryFqdnFromGmi() const;
  std::string ReadOauthKeyFromFile() const;
  std::vector<std::string> ReadDomainNameFromOfflineNodeEntity(
      std::string_view primary_fqdn) const;

  virtual grpc::Status AuthorizeWithoutTrustBundle(
      std::string_view uri, boost::beast::http::verb verb) const;

  virtual grpc::Status RecoveryAuthorizeForBloom(
      std::string_view uri, boost::beast::http::verb verb) const;

  virtual grpc::Status AuthorizeWithTrustBundle(
      std::string_view uri, boost::beast::http::verb verb,
      const RequestState& request_state) const;

  std::string GetPrimaryFqdn() const {
    absl::MutexLock lock(mutex_);
    return primary_fqdn_;
  }
  std::string GetOauthKey() const {
    absl::MutexLock lock(mutex_);
    return oauth_key_;
  }
  std::vector<std::string> GetInterfaceFqdns() const {
    absl::MutexLock lock(mutex_);
    return interface_fqdns_;
  }
  void SetPrimaryFqdn(std::string_view fqdn) {
    absl::MutexLock lock(mutex_);
    primary_fqdn_ = fqdn;
  }
  void SetOauthKey(std::string_view oauth_key) {
    absl::MutexLock lock(mutex_);
    oauth_key_ = oauth_key;
  }
  void SetInterfaceFqdns(std::vector<std::string>&& fqdns) {
    absl::MutexLock lock(mutex_);
    interface_fqdns_ = std::move(fqdns);
  }

  bool tlbmc_trust_bundle_install_module_is_enabled_;

 private:
  mutable absl::Mutex mutex_;

  std::string gmi_path_;
  std::string oauth_key_path_;
  std::string offline_node_entity_path_;

  // |primary_fqdn_| is read from GMI file at |gmi_path_|; empty string means an
  // error happened, e.g., missing or corrupted GMI file
  std::string primary_fqdn_ ABSL_GUARDED_BY(mutex_);

  // |interface_fqdns_| is read from offline node entity file; including all
  // interfaces' domain name
  std::vector<std::string> interface_fqdns_ ABSL_GUARDED_BY(mutex_);

  // |oauth_key_| is read from key file at |oauth_key_path_|; empty string means
  // an error happened, e.g., missing or corrupted GMI file
  std::string oauth_key_ ABSL_GUARDED_BY(mutex_);

  RedfishAuthorizer redfish_authorizer_;
  ::milotic::redfish::CertificateMetadataParser metadata_parser_;
};
}  // namespace milotic::authz

#endif  // THIRD_PARTY_MILOTIC_INTERNAL_CC_AUTHZ_BMCWEB_AUTHORIZER_SINGLETON_H_
