#include "redfish_authorizer.h"

#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iterator>
#include <limits>
#include <memory>
#include <string>
#include <string_view>
#include <unordered_set>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/synchronization/mutex.h"
#include "authorizer_enums.h"
#include "nlohmann/json.hpp"
#include "nlohmann/json_fwd.hpp"
#include "config_parser.h"
#include "json_utils.h"
#include "override.h"
#include "pattern_to_entity_array.h"
#include "redfish_entity_trie.h"
#include "redfish_privileges.h"
#include "resource_uri_override.h"
#include "subordinate_override.h"

namespace milotic::authz {

using ::ecclesia::Operation;
using ::ecclesia::ResourceEntity;
using ::ecclesia::StringToOperation;
using ::ecclesia::StringToResourceEntity;

RedfishAuthorizer::RedfishAuthorizer()
    : RedfishAuthorizer(AuthorizerOptions()) {}

RedfishAuthorizer::RedfishAuthorizer(const AuthorizerOptions& options)
    : options_(options),
      authz_configuration_(nlohmann::json(), options.offline_node_entities_path,
                           options.google_machine_identity_path) {
  ResetEntityPrivilegesMappings();
  LoadRedfishEntityTrie();
  ReloadConfiguration();
}

void RedfishAuthorizer::LoadRedfishEntityTrie() {
  for (std::size_t i = 0; i < pattern_entity_pair_array.size(); ++i) {
    const auto& [pattern, entity] = pattern_entity_pair_array[i];
    redfish_entity_trie_.InsertUri(pattern, entity, i);
  }
  // Now loads non-standard URI pattern into the trie
  std::ifstream configuration_file(options_.pattern_entity_overrides_path);
  if (!configuration_file.is_open()) {
    LOG(WARNING) << "Pattern entity overrides file at '"
                 << options_.pattern_entity_overrides_path << "' is missing.";
    return;
  }
  std::string configuration = {
      std::istreambuf_iterator<char>(configuration_file),
      std::istreambuf_iterator<char>()};
  constexpr bool kAllowException = false;
  nlohmann::json configuration_json =
      nlohmann::json::parse(configuration, nullptr, kAllowException);
  if (configuration_json.is_discarded()) {
    LOG(WARNING) << "Pattern entity overrides file at '"
                 << options_.pattern_entity_overrides_path
                 << "' is not a JSON document.";
    return;
  }
  const nlohmann::json::array_t* pattern_entity_pairs =
      GetValueAsArray(configuration_json, "pattern_entity_mappings_override");
  if (pattern_entity_pairs == nullptr) {
    LOG(WARNING) << "There are no pattern entity mappings.";
    return;
  }

  for (const nlohmann::json& pattern_entity_pair : *pattern_entity_pairs) {
    const std::string* pattern =
        GetValueAsString(pattern_entity_pair, "pattern");
    const std::string* entity_str =
        GetValueAsString(pattern_entity_pair, "resource");
    if (pattern == nullptr || entity_str == nullptr) {
      LOG(WARNING) << "Pattern entity pair is invalid.";
      return;
    }
    ResourceEntity entity = StringToResourceEntity(*entity_str);
    // TODO(nanzhou): support indexing non-standard URI patterns
    redfish_entity_trie_.InsertUri(*pattern, entity,
                                   std::numeric_limits<std::size_t>::max());
  }
}

ResourceEntity RedfishAuthorizer::GetEntityTypeFromRedfishUri(
    std::string_view uri) const {
  return redfish_entity_trie_.GetEntityType(uri);
}

RedfishAuthorizer::RedfishAuthorizer(const nlohmann::json& registry_json,
                                     const nlohmann::json& configuration_json) {
  ResetEntityPrivilegesMappings();
  LoadRedfishEntityTrie();
  ReconstructPrivilegeRegistry(
      GetValueAsArray(registry_json, "Mappings"),
      GetValueAsArray(configuration_json, "oem_privilege_mappings"),
      GetValueAsJson(configuration_json, "additional_override_mappings"),
      GetValueAsArray(registry_json, "AdditionalSubtreeMappings"),
      /*platform_subtree_mappings=*/nullptr);
}

static nlohmann::json ParseJsonConfig(const std::string& configuration_path) {
  std::ifstream configuration_file(configuration_path);
  if (!configuration_file.is_open()) {
    LOG(WARNING) << "Configuration file at '" << configuration_path
                 << "' is missing.";
    return nlohmann::json();
  }
  std::string configuration = {
      std::istreambuf_iterator<char>(configuration_file),
      std::istreambuf_iterator<char>()};
  constexpr bool kAllowException = false;
  nlohmann::json configuration_json =
      nlohmann::json::parse(configuration, nullptr, kAllowException);
  if (configuration_json.is_discarded()) {
    LOG(WARNING) << "Configuration file at '" << configuration_path
                 << "' is not a JSON document.";
    return nlohmann::json();
  }
  return configuration_json;
}

nlohmann::json RedfishAuthorizer::ParseAuthConfig() const {
  return ParseJsonConfig(options_.configuration_path);
}

void RedfishAuthorizer::ParseSubscriptionLimit(
    const nlohmann::json& configuration_json) {
  const int64_t* subscription_limit =
      GetValueAsInt(configuration_json, "universal_subscription_limit");
  if (subscription_limit == nullptr) {
    LOG(WARNING) << "Subscription limit not defined in Authorization Config; a "
                    "default value 1 will be used";
    return;
  }
  if (*subscription_limit < 1) {
    LOG(WARNING) << "Subscription shouldn't be less than 1; a default value 1 "
                    "will be used";
    return;
  }
  subscription_tracker_.SetUniversalSubscriptionLimit(*subscription_limit);
}

std::string RedfishAuthorizer::FindBasePrivilegeRegistryPath(
    const nlohmann::json& configuration_json) const {
  const std::string* base_privilege_registry_str =
      GetValueAsString(configuration_json, "base_privilege_registry");
  if (base_privilege_registry_str == nullptr) {
    LOG(WARNING)
        << "Base Privilege Registry not defined in Authorization Config";
    return "";
  }

  std::string base_privilege_registry_path =
      options_.base_privileges_folder + "/" + *base_privilege_registry_str;

  std::ifstream registry_file(base_privilege_registry_path);
  if (!registry_file.is_open()) {
    LOG(WARNING) << "Base registry file at '" << base_privilege_registry_path
                 << "' is missing.";
    return "";
  }
  return base_privilege_registry_path;
}

std::string RedfishAuthorizer::GetPeerRedfishRole(
    const PeerSpiffeIdentity& peer) const {
  return authz_configuration_.GetPeerRedfishRole(peer);
}

uint64_t RedfishAuthorizer::GetSampleRateLimit(
    const std::string& peer_role) const {
  return authz_configuration_.GetSampleRateLimit(peer_role);
}

void RedfishAuthorizer::ReloadConfiguration() {
  ReloadConfiguration(options_.configuration_path);
}

void RedfishAuthorizer::ReloadConfiguration(
    const std::string& configuration_path) {
  nlohmann::json configuration_json = ParseJsonConfig(configuration_path);

  if (configuration_json.empty()) {
    return;
  }

  // Load subscription limit
  ParseSubscriptionLimit(configuration_json);

  nlohmann::json platform_configuration_json =
      ParseJsonConfig(options_.platform_configuration_path);
  const std::string* platform_name_str =
      GetValueAsString(platform_configuration_json, "name");
  if (platform_name_str != nullptr) {
    LOG(WARNING) << "Loading platform configuration '" << *platform_name_str
                 << "'" << " from " << options_.platform_configuration_path;
  }

  // Load authz config
  authz_configuration_.ReloadConfig(configuration_json,
                                    platform_configuration_json);

  std::string base_privilege_registry_path =
      FindBasePrivilegeRegistryPath(configuration_json);

  if (base_privilege_registry_path.empty()) {
    return;
  }

  ResetEntityPrivilegesMappings();

  ReconstructPrivilegeRegistry(
      base_privilege_registry_path,
      GetValueAsArray(configuration_json, "oem_privilege_mappings"),
      GetValueAsJson(configuration_json, "additional_override_mappings"),
      platform_configuration_json);
}

void RedfishAuthorizer::SetBasePrivilegesFolder(
    std::string_view base_privileges_folder) {
  options_.base_privileges_folder = base_privileges_folder;
  ReloadConfiguration();
}

void RedfishAuthorizer::SetPrivileges(
    EntityPrivilegesMappings&& new_entity_privileges_mappings,
    OverrideMappings&& new_override_mappings) {
  absl::MutexLock lock(&mutex_);
  entity_privileges_mappings_ = std::move(new_entity_privileges_mappings);
  override_mappings_ = std::move(new_override_mappings);
}

RedfishAuthorizer::EntityPrivilegesMappings
RedfishAuthorizer::DefaultEntityPrivilegesMappings() {
  return EntityPrivilegesMappings(
      static_cast<int>(ResourceEntity::kUndefined) + 1,
      std::vector<std::vector<RedfishPrivileges>>(
          static_cast<int>(Operation::kUndefined) + 1));
}

RedfishAuthorizer::OverrideMappings
RedfishAuthorizer::DefaultOverrideMappings() {
  return OverrideMappings(static_cast<int>(ResourceEntity::kUndefined) + 1);
}

void RedfishAuthorizer::ResetEntityPrivilegesMappings() {
  absl::MutexLock lock(&mutex_);
  entity_privileges_mappings_ = DefaultEntityPrivilegesMappings();
  override_mappings_ = DefaultOverrideMappings();
}

std::vector<RedfishPrivileges> RedfishAuthorizer::GetPrivilegesArrFromJsonArr(
    const nlohmann::json::array_t& operation_privilege_arr_json) const {
  std::vector<RedfishPrivileges> privileges_or_arr;
  for (const nlohmann::json& operation_privilege :
       operation_privilege_arr_json) {
    RedfishPrivileges redfish_privileges;
    const nlohmann::json::array_t* privilege_arr =
        GetValueAsArray(operation_privilege, "Privilege");
    if (privilege_arr == nullptr) {
      continue;
    }
    for (const nlohmann::json& privilege : *privilege_arr) {
      const std::string* privilege_str =
          privilege.get_ptr<const std::string*>();
      if (privilege_str == nullptr) {
        LOG(WARNING) << "The value of the privilege isn't a string.";
        LOG(WARNING) << "|value|=" << privilege.dump(2);
        continue;
      }
      redfish_privileges.InsertPrivilege(*privilege_str);
    }
    // NOTE: there won't be an empty required privilege set ever
    if (redfish_privileges.GetPrivileges().empty()) {
      continue;
    }
    privileges_or_arr.push_back(redfish_privileges);
  }
  return privileges_or_arr;
}

std::vector<std::string> RedfishAuthorizer::GetTargetsArrFromJsonArr(
    const nlohmann::json::array_t& targets_arr_json) const {
  std::vector<std::string> targets;
  for (const nlohmann::json& target : targets_arr_json) {
    const std::string* target_str = target.get_ptr<const std::string*>();
    if (target_str == nullptr) {
      continue;
    }
    targets.push_back(*target_str);
  }
  return targets;
}

absl::flat_hash_map<ecclesia::Operation, std::vector<RedfishPrivileges>>
RedfishAuthorizer::GetOperationMapFromJson(
    const nlohmann::json& override_operation_map) const {
  absl::flat_hash_map<ecclesia::Operation, std::vector<RedfishPrivileges>>
      override_operation_privileges_map;

  for (Operation operation : all_operations) {
    const nlohmann::json::array_t* override_operation_privilege_arr =
        GetValueAsArray(override_operation_map, OperationToString(operation));
    if (override_operation_privilege_arr == nullptr) {
      continue;
    }
    override_operation_privileges_map[operation] =
        GetPrivilegesArrFromJsonArr(*override_operation_privilege_arr);
  }
  return override_operation_privileges_map;
}

void RedfishAuthorizer::ReconstructPrivilegeRegistry(
    const std::string& base_registry_path,
    const nlohmann::json::array_t* oem_mappings,
    const nlohmann::json* override_mappings,
    const nlohmann::json& platform_config_json) {
  std::ifstream registry_file(base_registry_path);
  if (!registry_file.is_open()) {
    LOG(WARNING) << "Base registry file at '" << base_registry_path
                 << "' is missing.";
    return;
  }
  std::string registry = {std::istreambuf_iterator<char>(registry_file),
                          std::istreambuf_iterator<char>()};
  constexpr bool kAllowException = false;
  nlohmann::json registry_json =
      nlohmann::json::parse(registry, nullptr, kAllowException);
  if (registry_json.is_discarded()) {
    LOG(WARNING) << "Base registry file at '" << base_registry_path
                 << "' is not a JSON document.";
    return;
  }
  const nlohmann::json::array_t* mappings =
      GetValueAsArray(registry_json, "Mappings");
  const nlohmann::json::array_t* additional_subtree_mappings =
      GetValueAsArray(registry_json, "AdditionalSubtreeMappings");
  const nlohmann::json::array_t* platform_subtree_mappings =
      GetValueAsArray(platform_config_json, "AdditionalSubtreeMappings");
  ReconstructPrivilegeRegistry(mappings, oem_mappings, override_mappings,
                               additional_subtree_mappings,
                               platform_subtree_mappings);
}

void RedfishAuthorizer::ReconstructPrivilegeRegistry(
    const nlohmann::json::array_t* registry_mappings,
    const nlohmann::json::array_t* oem_mappings,
    const nlohmann::json* override_mappings,
    const nlohmann::json::array_t* additional_subtree_mappings,
    const nlohmann::json::array_t* platform_subtree_mappings) {
  if (registry_mappings == nullptr) {
    return;
  }
  EntityPrivilegesMappings new_entity_privileges_mappings =
      DefaultEntityPrivilegesMappings();
  OverrideMappings new_override_mappings = DefaultOverrideMappings();

  for (const nlohmann::json& mapping : *registry_mappings) {
    const std::string* entity_str = GetValueAsString(mapping, "Entity");
    const nlohmann::json* operation_map =
        GetValueAsJson(mapping, "OperationMap");
    if (operation_map == nullptr || entity_str == nullptr) {
      continue;
    }
    ResourceEntity entity = StringToResourceEntity(*entity_str);
    if (entity == ResourceEntity::kUndefined) {
      continue;
    }

    for (Operation operation : all_operations) {
      const nlohmann::json::array_t* operation_privilege_arr =
          GetValueAsArray(*operation_map, OperationToString(operation));
      if (operation_privilege_arr == nullptr) {
        continue;
      }

      new_entity_privileges_mappings[static_cast<int>(entity)][static_cast<int>(
          operation)] = GetPrivilegesArrFromJsonArr(*operation_privilege_arr);
    }

    // Apply overrides if applicable
    ApplySubordinateOverridesToEntity(
        GetValueAsArray(mapping, "SubordinateOverrides"), entity,
        new_override_mappings);
    ApplyResourceOverridesToEntity(
        GetValueAsArray(mapping, "ResourceURIOverrides"), entity,
        new_override_mappings);
  }

  if (oem_mappings != nullptr) {
    ApplyOemMappings(*oem_mappings, new_entity_privileges_mappings);
  }

  if (override_mappings != nullptr) {
    ApplyOverrideMappings(*override_mappings, new_override_mappings);
  }

  std::vector<SubtreePrivilegeMapping> additional_subtree_mappings_vector;
  if (additional_subtree_mappings != nullptr) {
    ParseAdditionalSubtreeMappings(additional_subtree_mappings_vector,
                                   *additional_subtree_mappings);
  }
  if (platform_subtree_mappings != nullptr) {
    ParseAdditionalSubtreeMappings(additional_subtree_mappings_vector,
                                   *platform_subtree_mappings);
  }

  redfish_entity_trie_.ReplaceSubtreePrivilegeMappings(
      std::move(additional_subtree_mappings_vector));

  SetPrivileges(std::move(new_entity_privileges_mappings),
                std::move(new_override_mappings));
}

void RedfishAuthorizer::ApplySubordinateOverrides(
    const nlohmann::json::array_t* subordinate_overrides,
    OverrideMappings& new_override_mappings) {
  if (subordinate_overrides == nullptr) {
    return;
  }
  for (const nlohmann::json& subordinate_override : *subordinate_overrides) {
    const std::string* entity_str =
        GetValueAsString(subordinate_override, "entity");
    const nlohmann::json::array_t* targets_json =
        GetValueAsArray(subordinate_override, "targets");
    const nlohmann::json* override_operation_map =
        GetValueAsJson(subordinate_override, "operation_map");

    if (entity_str == nullptr || targets_json == nullptr ||
        targets_json->empty() || override_operation_map == nullptr) {
      LOG(WARNING) << "Override is setup incorrectly";
      LOG(WARNING) << "|json|=" << subordinate_override.dump(2);
      continue;
    }

    ResourceEntity entity = StringToResourceEntity(*entity_str);
    if (entity == ResourceEntity::kUndefined) {
      LOG(WARNING) << "|entity| is unsupported; |entity|=" << *entity_str;
      continue;
    }

    std::vector<std::string> targets = GetTargetsArrFromJsonArr(*targets_json);

    if (targets.empty()) {
      continue;
    }

    new_override_mappings[static_cast<int>(entity)].push_back(
        std::make_shared<SubordinateOverride>(
            std::move(targets),
            GetOperationMapFromJson(*override_operation_map),
            redfish_entity_trie_));
  }
}

void RedfishAuthorizer::ApplySubordinateOverridesToEntity(
    const nlohmann::json::array_t* subordinate_overrides, ResourceEntity entity,
    OverrideMappings& new_override_mappings) {
  if (subordinate_overrides == nullptr) {
    return;
  }

  for (const nlohmann::json& subordinate_override : *subordinate_overrides) {
    const nlohmann::json::array_t* targets_json =
        GetValueAsArray(subordinate_override, "Targets");
    const nlohmann::json* override_operation_map =
        GetValueAsJson(subordinate_override, "OperationMap");

    if (targets_json == nullptr || override_operation_map == nullptr) {
      continue;
    }

    std::vector<std::string> targets = GetTargetsArrFromJsonArr(*targets_json);

    if (targets.empty()) {
      continue;
    }

    new_override_mappings[static_cast<int>(entity)].push_back(
        std::make_shared<SubordinateOverride>(
            std::move(targets),
            GetOperationMapFromJson(*override_operation_map),
            redfish_entity_trie_));
  }
}

void RedfishAuthorizer::ApplyResourceOverrides(
    const nlohmann::json::array_t* resource_overrides,
    OverrideMappings& new_override_mappings) {
  if (resource_overrides == nullptr) {
    return;
  }
  for (const nlohmann::json& resource_override : *resource_overrides) {
    const std::string* entity_str =
        GetValueAsString(resource_override, "entity");
    const nlohmann::json::array_t* targets_json =
        GetValueAsArray(resource_override, "targets");
    const nlohmann::json* override_operation_map =
        GetValueAsJson(resource_override, "operation_map");

    if (entity_str == nullptr || targets_json == nullptr ||
        targets_json->empty() || override_operation_map == nullptr) {
      LOG(WARNING) << "Override is setup incorrectly";
      LOG(WARNING) << "|json|=" << resource_override.dump(2);
      continue;
    }

    ResourceEntity entity = StringToResourceEntity(*entity_str);
    if (entity == ResourceEntity::kUndefined) {
      LOG(WARNING) << "|entity| is unsupported; |entity|=" << *entity_str;
      continue;
    }

    std::vector<std::string> targets = GetTargetsArrFromJsonArr(*targets_json);

    if (targets.empty()) {
      continue;
    }

    new_override_mappings[static_cast<int>(entity)].push_back(
        std::make_shared<ResourceUriOverride>(
            std::move(targets),
            GetOperationMapFromJson(*override_operation_map)));
  }
}

void RedfishAuthorizer::ApplyResourceOverridesToEntity(
    const nlohmann::json::array_t* resource_overrides, ResourceEntity entity,
    OverrideMappings& new_override_mappings) {
  if (resource_overrides == nullptr) {
    return;
  }

  for (const nlohmann::json& resource_override : *resource_overrides) {
    const nlohmann::json::array_t* targets_json =
        GetValueAsArray(resource_override, "Targets");
    const nlohmann::json* override_operation_map =
        GetValueAsJson(resource_override, "OperationMap");

    if (targets_json == nullptr || override_operation_map == nullptr) {
      continue;
    }

    std::vector<std::string> targets = GetTargetsArrFromJsonArr(*targets_json);

    if (targets.empty()) {
      continue;
    }

    new_override_mappings[static_cast<int>(entity)].push_back(
        std::make_shared<ResourceUriOverride>(
            std::move(targets),
            GetOperationMapFromJson(*override_operation_map)));
  }
}

void RedfishAuthorizer::ApplyOverrideMappings(
    const nlohmann::json& override_mappings_json,
    OverrideMappings& new_override_mappings) {
  ApplySubordinateOverrides(
      GetValueAsArray(override_mappings_json, "subordinate_overrides"),
      new_override_mappings);
  ApplyResourceOverrides(
      GetValueAsArray(override_mappings_json, "resource_overrides"),
      new_override_mappings);
}

void RedfishAuthorizer::ApplyOemMappings(
    const nlohmann::json::array_t& oem_mappings,
    EntityPrivilegesMappings& entity_privileges_mappings) {
  for (const nlohmann::json& oem_mapping : oem_mappings) {
    const std::string* oem_privilege =
        GetValueAsString(oem_mapping, "oem_privilege");
    if (oem_privilege == nullptr) {
      continue;
    }
    RedfishPrivileges new_privileges({*oem_privilege});
    const nlohmann::json::array_t* resource_operations =
        GetValueAsArray(oem_mapping, "resource_operations");
    if (resource_operations == nullptr) {
      continue;
    }
    for (const nlohmann::json& resource_operation : *resource_operations) {
      const std::string* resource_entity_str =
          GetValueAsString(resource_operation, "resource_entity");
      if (resource_entity_str == nullptr) {
        continue;
      }
      ResourceEntity entity = StringToResourceEntity(*resource_entity_str);
      if (entity == ResourceEntity::kUndefined) {
        LOG(WARNING) << "|resource_entity| is unsupported; |resource_entity|="
                     << *resource_entity_str;
        continue;
      }
      const nlohmann::json::array_t* operations =
          GetValueAsArray(resource_operation, "operations");
      if (operations == nullptr) {
        continue;
      }
      for (const nlohmann::json& operation_json : *operations) {
        const std::string* operation_str =
            operation_json.get_ptr<const std::string*>();
        if (operation_str == nullptr) {
          LOG(WARNING) << "The value of the operation isn't a string.";
          LOG(WARNING) << "|value|=" << operation_json;
          continue;
        }
        Operation operation = StringToOperation(*operation_str);
        if (operation == Operation::kUndefined) {
          LOG(WARNING) << "|operation| is unsupported; |operation|="
                       << *operation_str;
          continue;
        }
        AppendPrivilege(new_privileges, entity, operation,
                        entity_privileges_mappings);
      }
    }
  }
}

void RedfishAuthorizer::ParseAdditionalSubtreeMappings(
    std::vector<SubtreePrivilegeMapping>& additional_subtree_mappings,
    const nlohmann::json& additional_subtree_mappings_json) {
  for (const nlohmann::json& subtree_mapping :
       additional_subtree_mappings_json) {
    const std::string* subtree_prefix =
        GetValueAsString(subtree_mapping, "SubtreePrefix");
    const nlohmann::json* operation_map_json =
        GetValueAsJson(subtree_mapping, "OperationMap");
    if (subtree_prefix == nullptr || operation_map_json == nullptr) {
      continue;
    }
    for (const auto& [operation, privileges] :
         GetOperationMapFromJson(*operation_map_json)) {
      for (const auto& privilege : privileges) {
        additional_subtree_mappings.push_back(
            SubtreePrivilegeMapping{.url = *subtree_prefix,
                                    .operation = operation,
                                    .privileges = privilege});
      }
    }
  }
}

void RedfishAuthorizer::AppendPrivilege(
    const RedfishPrivileges& privileges, ResourceEntity resource_entity,
    Operation operation, EntityPrivilegesMappings& entity_privileges_mappings) {
  entity_privileges_mappings[static_cast<int>(resource_entity)]
                            [static_cast<int>(operation)]
                                .push_back(privileges);
}

std::vector<RedfishPrivileges> RedfishAuthorizer::GetRequiredPrivileges(
    ResourceEntity resource_entity, Operation operation) const {
  absl::MutexLock lock(&mutex_);
  return entity_privileges_mappings_[static_cast<int>(resource_entity)]
                                    [static_cast<int>(operation)];
}

std::vector<std::shared_ptr<Override>> RedfishAuthorizer::GetOverrides(
    ResourceEntity resource_entity) const {
  absl::MutexLock lock(&mutex_);
  return override_mappings_[static_cast<int>(resource_entity)];
}

absl::Status RedfishAuthorizer::RecordNewSubscription(
    const PeerSpiffeIdentity& peer) {
  return subscription_tracker_.RecordNewSubscription(peer);
}

absl::Status RedfishAuthorizer::RecordNewUnsubscription(
    const PeerSpiffeIdentity& peer) {
  return subscription_tracker_.RecordNewUnsubscription(peer);
}

bool RedfishAuthorizer::IsPeerAuthorized(
    ResourceEntity entity, Operation operation,
    const RedfishPrivileges& peer_privileges) const {
  if (entity == ResourceEntity::kUndefined ||
      operation == Operation::kUndefined) {
    return false;
  }

  std::vector<RedfishPrivileges> required_privilege_sets =
      GetRequiredPrivileges(entity, operation);

  if (required_privilege_sets.empty()) {
    LOG(WARNING) << "No required privileges found for "
                 << ResourceEntityToString(entity) << " and operation "
                 << OperationToString(operation)
                 << ". This most likely means that you are using an outdated "
                    "redfish authz policy.";
  }

  for (const RedfishPrivileges& privileges : required_privilege_sets) {
    // NOTE: there won't be an empty required privilege set ever; otherwise,
    // we skip this required privilege set.
    if (privileges.GetPrivileges().empty()) {
      LOG(WARNING)
          << "Precondition failed: required privilege set will never be "
             "empty; check the base privilege registry for "
          << ResourceEntityToString(entity) << " and operation "
          << OperationToString(operation);
      continue;
    }
    if (peer_privileges.IsSupersetOf(privileges)) {
      return true;
    }
  }
  return false;
}

bool RedfishAuthorizer::IsPeerAuthorized(
    std::string_view uri, Operation operation,
    const RedfishPrivileges& peer_privileges) const {
  ResourceEntity entity = GetEntityTypeFromRedfishUri(uri);
  if (entity == ResourceEntity::kUndefined) {
    LOG(WARNING) << "Can't map |uri| to Redfish resource; |uri|=" << uri;
    return false;
  }
  if (operation == Operation::kUndefined) {
    LOG(WARNING) << "|operation| is undefined";
    return false;
  }

  // Check Overrides
  for (const std::shared_ptr<Override>& override : GetOverrides(entity)) {
    // If the override is applicable, then peer must be authorized through
    // override
    if (override->IsApplicable(uri, operation)) {
      return override->IsPeerAuthorized(uri, operation, peer_privileges);
    }
  }

  // Check Additional Subtree Mappings
  for (const auto& privileges :
       redfish_entity_trie_.GetAdditionalSubtreePrivileges(uri, operation)) {
    // NOTE: there won't be an empty required privilege set ever; otherwise,
    // we skip this required privilege set.
    if (privileges.GetPrivileges().empty()) {
      LOG(WARNING)
          << "Precondition failed: required privilege set will never be "
             "empty; check the additional subtree mappings for "
          << uri << " and operation " << OperationToString(operation);
      continue;
    }
    if (peer_privileges.IsSupersetOf(privileges)) {
      return true;
    }
  }

  return IsPeerAuthorized(entity, operation, peer_privileges);
}

nlohmann::json::array_t RedfishAuthorizer::RedfishPrivilegeRegistryMappings()
    const {
  nlohmann::json::array_t privilege_registry_mappings;

  for (size_t i = 0; i < static_cast<size_t>(ResourceEntity::kUndefined); ++i) {
    nlohmann::json::object_t entity_privilege_mappings;
    ResourceEntity entity = static_cast<ResourceEntity>(i);
    entity_privilege_mappings["Entity"] = ResourceEntityToString(entity);

    // Get OperationMap
    entity_privilege_mappings["OperationMap"] = nlohmann::json::object_t();
    for (size_t j = 0; j < static_cast<size_t>(Operation::kUndefined); ++j) {
      nlohmann::json::array_t operation_privileges;
      Operation operation = static_cast<Operation>(j);
      std::vector<RedfishPrivileges> privilege_set =
          GetRequiredPrivileges(entity, operation);
      for (const RedfishPrivileges& privileges : privilege_set) {
        operation_privileges.push_back(privileges.ToJson());
      }
      entity_privilege_mappings["OperationMap"][OperationToString(operation)] =
          operation_privileges;
    }

    // Get Overrides
    std::vector<std::shared_ptr<Override>> overrides = GetOverrides(entity);
    nlohmann::json::array_t subordinate_overrides_json =
        nlohmann::json::array_t();
    nlohmann::json::array_t resource_overrides_json = nlohmann::json::array_t();
    for (const std::shared_ptr<Override>& override : overrides) {
      if (override->GetOverrideType() == Override::Type::kSubordinateOverride) {
        subordinate_overrides_json.push_back(override->ToJson());
        continue;
      }
      resource_overrides_json.push_back(override->ToJson());
    }

    if (!subordinate_overrides_json.empty()) {
      entity_privilege_mappings["SubordinateOverrides"] =
          subordinate_overrides_json;
    }
    if (!resource_overrides_json.empty()) {
      entity_privilege_mappings["ResourceURIOverrides"] =
          resource_overrides_json;
    }

    privilege_registry_mappings.push_back(entity_privilege_mappings);
  }

  return privilege_registry_mappings;
}

nlohmann::json::object_t RedfishAuthorizer::GetRedfishPrivilegeRegistry()
    const {
  nlohmann::json::object_t privilege_registry;

  privilege_registry["@odata.id"] = "/redfish/v1/AccountService/PrivilegeMap";
  privilege_registry["@odata.type"] =
      "#PrivilegeRegistry.v1_1_4.PrivilegeRegistry";
  privilege_registry["Id"] = "Redfish_1.3.1_PrivilegeRegistry";
  privilege_registry["Name"] = "Privilege Mapping array collection";
  privilege_registry["PrivilegesUsed"] =
      authz_configuration_.GetDefaultRedfishPrivileges();
  privilege_registry["OEMPrivilegesUsed"] =
      authz_configuration_.GetOemPrivileges();
  privilege_registry["Mappings"] = RedfishPrivilegeRegistryMappings();

  return privilege_registry;
}

}  // namespace milotic::authz
