#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);
}

std::string RedfishAuthorizer::GetAnycastAddress(
    const std::string& peer_role) const {
  return authz_configuration_.GetAnycastAddress(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);

  for (const auto& [service, user] : anycast_users_) {
    user->SetAnycastAddress(authz_configuration_.GetAnycastAddress(service));
  }

  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
