#include "config_parser.h"

#include <algorithm>
#include <array>
#include <cstddef>
#include <fstream>
#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "gmi/machine_identity.pb.h"
#include "one/node_entities_api.pb.h"
#include "one/offline_node_entities.pb.h"
#include "one/resolved_entities.pb.h"
#include "one/public_offline_node_entities.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "nlohmann/json.hpp"
#include "nlohmann/json_fwd.hpp"
#include "json_utils.h"
#include "authorized_entity.pb.h"
#include "zatar/certificate_metadata.h"

namespace milotic::authz {

using ::milotic::redfish::CertificateMetadataParser;
using ::production_msv::node_entities::ReadOfflineNodeEntityInformation;
using ::production_msv::node_entities_proto::OfflineNodeEntityInformation;
using ::security_prodid::GoogleMachineIdentityProto;
using EntityTagIdentity = AuthzConfiguration::EntityTagIdentity;

AuthzConfiguration::AuthzConfiguration(
    const nlohmann::json& config, absl::string_view offline_node_entities_path,
    absl::string_view gmi_path)
    : offline_node_entities_path_(offline_node_entities_path),
      gmi_path_(gmi_path) {
  ReloadConfig(config);
};

std::optional<AuthzConfiguration::SpiffeIdentityMatcher>
AuthzConfiguration::CreateIdentityMatcherFromPeerSpiffeIdentity(
    const PeerSpiffeIdentity& peer) {
  AuthzConfiguration::SpiffeIdentityMatcher matcher;
  matcher.fqdn = peer.fqdn;

  const std::string spiffe_id = absl::AsciiStrToLower(peer.spiffe_id);
  // As per SPIFFE specification, SPIFFE schema and trust domain are case
  // insensitive.
  // https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE-ID.md#24-spiffe-id-parsing
  constexpr std::string_view kSpiffeSchema = "spiffe://";
  if (!absl::StartsWithIgnoreCase(spiffe_id, kSpiffeSchema)) {
    return std::nullopt;
  }

  std::size_t path_start = spiffe_id.find_first_of('/', kSpiffeSchema.size());
  if (path_start == std::string_view::npos) {
    return std::nullopt;
  }

  matcher.spiffe_id_matcher.path = spiffe_id.substr(path_start);

  const std::string trust_domain = absl::AsciiStrToLower(spiffe_id.substr(
      kSpiffeSchema.size(), path_start - kSpiffeSchema.size()));

  // Trust domain consists of (issuing-role).(context).(realm).(suffix)
  // See go/zatar-prod-certificates for details.
  std::vector<std::string_view> trust_domain_pieces =
      absl::StrSplit(trust_domain, '.');

  // There should be at least 4 elements in this array for a property trust
  // domain
  if (trust_domain_pieces.size() < 4) {
    return std::nullopt;
  }

  matcher.spiffe_id_matcher.issuer = trust_domain_pieces[0];
  matcher.spiffe_id_matcher.ca_context = trust_domain_pieces[1];
  matcher.spiffe_id_matcher.realm = trust_domain_pieces[2];

  matcher.spiffe_id_matcher.trust_domain_suffix =
      absl::StrCat(".", absl::StrJoin(trust_domain_pieces.begin() + 3,
                                      trust_domain_pieces.end(), "."));

  return matcher;
}

std::optional<AuthzConfiguration::SpiffeIdentityMatcher>
AuthzConfiguration::ParseSpiffeIdentityMatcher(const nlohmann::json& config) {
  const nlohmann::json* spiffe_id_matcher =
      GetValueAsJson(config, "spiffe_id_matcher");
  if (spiffe_id_matcher == nullptr) {
    return std::nullopt;
  }
  const std::string* trust_domain_suffix =
      GetValueAsString(*spiffe_id_matcher, "trust_domain_suffix");
  if (trust_domain_suffix == nullptr) {
    LOG(WARNING) << "Warning: trust_domain_suffix isn't a string; "
                 << "|spiffe_id_matcher|=" << spiffe_id_matcher->dump(2);
    return std::nullopt;
  }

  AuthzConfiguration::SpiffeIdentityMatcher matcher;
  matcher.spiffe_id_matcher.trust_domain_suffix =
      absl::AsciiStrToLower(*trust_domain_suffix);

  const std::string* path = GetValueAsString(*spiffe_id_matcher, "path");
  if (path == nullptr) {
    return std::nullopt;
  }
  matcher.spiffe_id_matcher.path = absl::AsciiStrToLower(*path);

  const std::string* ca_context =
      GetValueAsString(*spiffe_id_matcher, "ca_context");
  if (ca_context == nullptr) {
    return std::nullopt;
  }
  matcher.spiffe_id_matcher.ca_context = absl::AsciiStrToLower(*ca_context);

  const std::string* issuer = GetValueAsString(*spiffe_id_matcher, "issuer");
  if (issuer != nullptr) {
    matcher.spiffe_id_matcher.issuer = absl::AsciiStrToLower(*issuer);
  }

  // If realm_check is enabled, get current realm from GMI
  const bool* realm_check = GetValueAsBool(*spiffe_id_matcher, "realm_check");
  if (realm_check != nullptr && *realm_check) {
    matcher.spiffe_id_matcher.realm = GetNodeRealm();
  }

  const std::string* fqdn = GetValueAsString(config, "fqdn");
  // Non-string value
  if (fqdn == nullptr && config.find("fqdn") != config.end()) {
    return std::nullopt;
  }

  if (fqdn != nullptr) {
    matcher.fqdn = *fqdn;
  }

  return matcher;
}

bool AuthzConfiguration::IsResourceOwnerExisting(
    const ResourceOwner& resource_owner) const {
  absl::MutexLock lock(&mutex_);
  return std::binary_search(resource_owners_.begin(), resource_owners_.end(),
                            resource_owner);
}

bool AuthzConfiguration::IsPeerResourceOwner(
    const PeerSpiffeIdentity& peer) const {
  std::optional<SpiffeIdentityMatcher> peer_matcher =
      CreateIdentityMatcherFromPeerSpiffeIdentity(peer);

  if (peer_matcher == std::nullopt) {
    LOG(WARNING) << "Peer spiffe id" << peer.spiffe_id << "is malformed";
    return false;
  }
  ResourceOwner peer_to_resource_owner{.identity_matcher = *peer_matcher};

  return IsResourceOwnerExisting(peer_to_resource_owner);
}

absl::StatusOr<std::string> AuthzConfiguration::GetRedfishRoleOfSpiffeMatcher(
    const SpiffeUser& spiffe_user) const {
  absl::MutexLock lock(&mutex_);

  auto it =
      std::lower_bound(spiffe_users_.begin(), spiffe_users_.end(), spiffe_user);
  // Comparing equality
  if (it == spiffe_users_.end() || *it != spiffe_user) {
    return absl::NotFoundError(
        absl::StrCat("No user with matching spiffe; spiffe_user is ",
                     spiffe_user.identity_matcher.DebugString()));
  }

  return it->redfish_role;
}

std::unordered_set<std::string> AuthzConfiguration::GetPeerRedfishPrivileges(
    const PeerSpiffeIdentity& peer) const {
  std::optional<SpiffeIdentityMatcher> peer_matcher =
      CreateIdentityMatcherFromPeerSpiffeIdentity(peer);

  if (peer_matcher == std::nullopt) {
    LOG(WARNING) << "Peer spiffe id" << peer.spiffe_id << "is malformed";
    return {"NoAuth"};
  }

  SpiffeUser peer_to_spiffe_user{.identity_matcher = *peer_matcher,
                                 .redfish_role = ""};

  absl::StatusOr<std::string> role =
      GetRedfishRoleOfSpiffeMatcher(peer_to_spiffe_user);

  if (!role.ok()) {
    LOG(WARNING) << role.status();
    return {"NoAuth"};
  }

  return GetRedfishPrivileges(*role);
}

std::unordered_set<std::string> AuthzConfiguration::GetPeerRedfishPrivileges(
    const PeerLoasIdentity& peer) const {
  std::optional<std::string> role = GetRoleByUsername(peer.username);
  if (role) {
    return GetRedfishPrivileges(*role);
  }
  role = GetRoleByGroup(peer.username);
  if (role) {
    return GetRedfishPrivileges(*role);
  }
  return {"NoAuth"};
}

absl::string_view AuthzConfiguration::GetCertNodeOwner(
    absl::string_view node_owner) const {
  if (IsHwopsState()) {
    return kHwopsRole;
  }
  return node_owner;
}

std::vector<AuthzConfiguration::SpiffeIdentityMatcher>
AuthzConfiguration::ParseSpiffeIdentityMatchersUsingOne(
    const nlohmann::json& config) const {
  const std::string* entity = GetValueAsString(config, "entity");
  if (entity == nullptr) {
    return {};
  }

  AuthorizedEntity entity_enum;
  if (!AuthorizedEntity_Parse(*entity, &entity_enum)) {
    LOG(WARNING) << "Warning: entity " << *entity
                 << " is not a valid AuthorizedEntity";
    return {};
  };
  std::vector<AuthzConfiguration::SpiffeIdentityMatcher> matchers;

  for (const std::string& entity_tag :
       GetAllEntityTagsFromAuthorizedEntity(entity_enum)) {
    AuthzConfiguration::SpiffeIdentityMatcher matcher;
    absl::StatusOr<AuthzConfiguration::EntityTagIdentity> entity_tag_identity =
        GetEntityTagIdentity(entity_tag);
    if (!entity_tag_identity.ok()) {
      continue;
    }
    matcher.fqdn =
        absl::StrCat(entity_tag_identity->hostname, ".prod.google.com");

    matcher.spiffe_id_matcher.trust_domain_suffix = ".prod.google.com";
    matcher.spiffe_id_matcher.ca_context =
        CertificateMetadataParser::kCaContextNode;

    matcher.spiffe_id_matcher.path =
        absl::StrCat("/role/", GetCertNodeOwner(entity_tag_identity->owner));

    matchers.push_back(std::move(matcher));
  }

  return matchers;
}

void AuthzConfiguration::ReloadResourceOwners(const nlohmann::json& config) {
  if (config.is_discarded()) {
    return;
  }
  const nlohmann::json::array_t* resource_owners =
      GetValueAsArray(config, "resource_owners");
  if (resource_owners == nullptr) {
    return;
  }
  std::vector<ResourceOwner> new_resource_owners;
  for (const nlohmann::json& resource_owner : *resource_owners) {
    // If the spiffe matcher is explicitly defined, parse it.
    if (resource_owner.contains("spiffe_id_matcher")) {
      ResourceOwner owner;
      std::optional<SpiffeIdentityMatcher> matcher =
          ParseSpiffeIdentityMatcher(resource_owner);
      if (matcher) {
        owner.identity_matcher = *matcher;
        new_resource_owners.push_back(std::move(owner));
      }
      continue;
    }
    // Otherwise continue with entity based parsing
    std::vector<SpiffeIdentityMatcher> matchers =
        ParseSpiffeIdentityMatchersUsingOne(resource_owner);
    for (const SpiffeIdentityMatcher& matcher : matchers) {
      ResourceOwner owner;
      owner.identity_matcher = matcher;
      new_resource_owners.push_back(std::move(owner));
    }
  }

  std::sort(new_resource_owners.begin(), new_resource_owners.end());

  absl::MutexLock lock(&mutex_);
  resource_owners_ = std::move(new_resource_owners);
}

void AuthzConfiguration::ReloadRedfishUsers(const nlohmann::json& config) {
  if (config.is_discarded()) {
    return;
  }
  const nlohmann::json::array_t* exchange_mappings =
      GetValueAsArray(config, "exchange_mappings");
  if (exchange_mappings == nullptr) {
    return;
  }
  std::vector<SpiffeUser> new_spiffe_users;
  std::unordered_map<std::string, std::string> new_username_to_role;
  std::unordered_map<std::string, std::string> new_group_to_role;
  for (const nlohmann::json& exchange_mapping : *exchange_mappings) {
    const std::string* redfish_role =
        GetValueAsString(exchange_mapping, "redfish_role");
    if (redfish_role == nullptr) {
      continue;
    }
    // If peer is explicitly defined, then create exchange mapping with peer.
    if (exchange_mapping.contains("peer")) {
      const nlohmann::json* peer = GetValueAsJson(exchange_mapping, "peer");
      if (peer == nullptr) {
        continue;
      }
      // If it is username based, parse the username and continue
      const std::string* username = GetValueAsString(*peer, "username");
      if (username != nullptr) {
        new_username_to_role[*username] = *redfish_role;
        continue;
      }
      // If it is group based, parse the group and continue
      const std::string* group = GetValueAsString(*peer, "group");
      if (group != nullptr) {
        new_group_to_role[*group] = *redfish_role;
        continue;
      }
      // Otherwise, it is spiffe based
      SpiffeUser user;
      std::optional<SpiffeIdentityMatcher> matcher =
          ParseSpiffeIdentityMatcher(*peer);
      if (!matcher) {
        continue;
      }
      user.identity_matcher = *matcher;
      user.redfish_role = *redfish_role;
      new_spiffe_users.push_back(std::move(user));
      continue;
    }

    // Otherwise, continue with entity based parsing
    std::vector<SpiffeIdentityMatcher> matchers =
        ParseSpiffeIdentityMatchersUsingOne(exchange_mapping);
    for (const SpiffeIdentityMatcher& matcher : matchers) {
      SpiffeUser user;
      user.identity_matcher = matcher;
      user.redfish_role = *redfish_role;
      // TODO(edwarddl): This is n^2. We can make it linear with refactoring of
      // vector into hashmap. Do profiling and benchmarking to see if this would
      // lead to better performance.

      // Update the redfish_role of the matcher if
      //  the user already exists.
      auto it =
          std::find(new_spiffe_users.begin(), new_spiffe_users.end(), user);
      if (it != new_spiffe_users.end()) {
        it->redfish_role = *redfish_role;
        continue;
      }

      // Add the user to the list if they aren't there
      new_spiffe_users.push_back(std::move(user));
    }
  }

  std::sort(new_spiffe_users.begin(), new_spiffe_users.end());

  absl::MutexLock lock(&mutex_);
  spiffe_users_ = std::move(new_spiffe_users);
  username_to_role_ = std::move(new_username_to_role);
  group_to_role_ = std::move(new_group_to_role);
}

void AuthzConfiguration::ReloadRoleToPrivileges(const nlohmann::json& config) {
  if (config.is_discarded()) {
    return;
  }
  const nlohmann::json::array_t* role_privileges =
      GetValueAsArray(config, "role_privileges_mappings");
  if (role_privileges == nullptr) {
    return;
  }
  std::unordered_map<std::string, std::unordered_set<std::string>>
      new_role_to_privileges;
  for (const nlohmann::json& role_privilege : *role_privileges) {
    const std::string* role = GetValueAsString(role_privilege, "redfish_role");
    if (role == nullptr) {
      continue;
    }
    const nlohmann::json* privileges =
        GetValueAsJson(role_privilege, "privileges");
    if (privileges == nullptr) {
      continue;
    }
    std::unordered_set<std::string> privileges_set;
    const nlohmann::json::array_t* base_privileges =
        GetValueAsArray(*privileges, "base_privileges");
    if (base_privileges != nullptr) {
      for (const nlohmann::json& privilege : *base_privileges) {
        const std::string* privilege_str =
            privilege.get_ptr<const std::string*>();
        if (privilege_str == nullptr) {
          continue;
        }
        privileges_set.insert(*privilege_str);
      }
    }
    const nlohmann::json::array_t* oem_privileges =
        GetValueAsArray(*privileges, "oem_privileges");
    if (oem_privileges != nullptr) {
      for (const nlohmann::json& privilege : *oem_privileges) {
        const std::string* privilege_str =
            privilege.get_ptr<const std::string*>();
        if (privilege_str == nullptr) {
          continue;
        }
        privileges_set.insert(*privilege_str);
      }
    }

    privileges_set.insert("NoAuth");
    new_role_to_privileges[*role] = std::move(privileges_set);
  }

  absl::MutexLock lock(&mutex_);
  role_to_privileges_ = std::move(new_role_to_privileges);
}

void AuthzConfiguration::ReloadOfflineNodeEntities() {
  if (offline_node_entities_path_.empty()) {
    return;
  }

  absl::StatusOr<OfflineNodeEntityInformation> parsed_offline_node_entities =
      ReadOfflineNodeEntityInformation(offline_node_entities_path_);

  if (!parsed_offline_node_entities.ok()) {
    LOG(WARNING) << "Could not read offline node entities information from "
                 << offline_node_entities_path_ << ": "
                 << parsed_offline_node_entities.status().message();
    return;
  }

  absl::MutexLock lock(&mutex_);
  offline_node_entities_ = std::move(*parsed_offline_node_entities);
}

void AuthzConfiguration::ReloadGmi() {
  if (gmi_path_.empty()) {
    return;
  }

  std::ifstream gmi_file(gmi_path_);
  if (!gmi_file.is_open()) {
    LOG(ERROR) << "GMI file at '" << gmi_path_ << "' is missing.";
    return;
  }
  GoogleMachineIdentityProto gmi;
  if (!gmi.ParseFromIstream(&gmi_file)) {
    LOG(ERROR) << "GMI parsing failed at '" << gmi_path_ << "'";
    return;
  }

  absl::MutexLock lock(&mutex_);
  gmi_ = std::move(gmi);
}

void AuthzConfiguration::ReloadConfig(const nlohmann::json& config) {
  if (config.is_discarded()) {
    LOG(WARNING) << "Warning: config isn't a valid JSON";
    return;
  }

  ReloadGmi();
  ReloadOfflineNodeEntities();
  ReloadResourceOwners(config);
  ReloadRedfishUsers(config);
  ReloadRoleToPrivileges(config);
}

std::unordered_set<std::string> AuthzConfiguration::GetOemPrivileges() const {
  std::unordered_set<std::string> privileges;

  absl::MutexLock lock(&mutex_);
  for (const auto& [role, privilege_set] : role_to_privileges_) {
    for (const std::string& privilege : privilege_set) {
      // If the privilege is not a default redfish privilege, it is OEM.
      if (!std::binary_search(kDefaultRedfishPrivileges.begin(),
                              kDefaultRedfishPrivileges.end(), privilege)) {
        privileges.insert(privilege);
      }
    }
  }

  return privileges;
}

absl::StatusOr<EntityTagIdentity> AuthzConfiguration::GetEntityTagIdentity(
    absl::string_view entity_tag) const {
  absl::MutexLock lock(&mutex_);
  auto it =
      offline_node_entities_.resolved_config().entities().find(entity_tag);
  if (it == offline_node_entities_.resolved_config().entities().end()) {
    return absl::NotFoundError("Entity Tag Not Found");
  }
  return EntityTagIdentity{.hostname = it->second.hostname(),
                           .owner = it->second.owner()};
}

std::string AuthzConfiguration::GetMachineManagerEntityTag() const {
  absl::MutexLock lock(&mutex_);
  return offline_node_entities_.resolved_config()
      .ecclesia_machine_manager_entity();
}

std::vector<std::string> AuthzConfiguration::GetAllComputeNodeEntityTags()
    const {
  std::vector<std::string> entity_tags;
  absl::MutexLock lock(&mutex_);
  for (const auto& [entity_tag, entity] :
       offline_node_entities_.resolved_config().entities()) {
    if (entity.node_type_info().is_compute()) {
      entity_tags.push_back(entity_tag);
    }
  }

  return entity_tags;
}

std::vector<std::string> AuthzConfiguration::GetEntityTagsFromRedfishSystemId(
    absl::string_view system_id) const {
  std::vector<std::string> entity_tags;
  absl::MutexLock lock(&mutex_);
  for (const auto& [entity_tag, entity] :
       offline_node_entities_.resolved_config().entities()) {
    if (entity.redfish_system_id() == system_id) {
      entity_tags.push_back(entity_tag);
    }
  }

  return entity_tags;
}

std::vector<std::string>
AuthzConfiguration::GetAllEntityTagsFromAuthorizedEntity(
    AuthorizedEntity entity) const {
  switch (entity) {
    case AuthorizedEntity::ComputeNode:
      return GetAllComputeNodeEntityTags();
    case AuthorizedEntity::ComputeNode1:
      return GetEntityTagsFromRedfishSystemId("system1");
    case AuthorizedEntity::ComputeNode2:
      return GetEntityTagsFromRedfishSystemId("system2");
    case AuthorizedEntity::EcclesiaMachineManagerEntity:
      return {GetMachineManagerEntityTag()};
    case AuthorizedEntity::Undefined:
      return {};
    case AuthorizedEntity_INT_MIN_SENTINEL_DO_NOT_USE_:
    case AuthorizedEntity_INT_MAX_SENTINEL_DO_NOT_USE_:
      return {};
  }
  return {};
}

bool AuthzConfiguration::IsHwopsState() const {
  absl::MutexLock lock(&mutex_);
  if (gmi_.has_in_hwops_state()) {
    return gmi_.in_hwops_state();
  }
  return false;
}

std::string AuthzConfiguration::GetNodeRealm() const {
  absl::MutexLock lock(&mutex_);
  // GMI only supports 1 realm
  if (gmi_.security_realms_size() != 1) {
    LOG(ERROR) << "Machine GMI's realm is broken. All realm specific Borg jobs "
                  "will be denied.";
    return "";
  }
  return gmi_.security_realms(0);
}

}  // namespace milotic::authz
