#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 "override_json.h"
#include "pattern_to_entity_array.h"
#include "redfish_entity_trie.h"
#include "redfish_privileges.h"
#include "redfish_privileges_json.h"
#include "resource_uri_override.h"
#include "subordinate_override.h"
#include <redfish_authorization/private_pattern_to_entity_array.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);
  }
  for (std::size_t i = 0; i < private_pattern_entity_pair_array.size(); ++i) {
    const auto& [pattern, entity] = private_pattern_entity_pair_array[i];
    redfish_entity_trie_.InsertUri(pattern, entity,
                                   pattern_entity_pair_array.size() + 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);

  absl::MutexLock lock(mutex_);
  privilege_registry_json_ = std::move(registry_json);
}

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(RedfishPrivilegesToJson(privileges));
      }
      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(OverrideToJson(*override));
        continue;
      }
      resource_overrides_json.push_back(OverrideToJson(*override));
    }

    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
