/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "FlowConfigEncryptor.h"

#include "Defaults.h"
#include "Utils.h"
#include "core/FlowConfiguration.h"
#include "core/ProcessGroup.h"
#include "core/RepositoryFactory.h"
#include "core/extension/ExtensionManager.h"
#include "core/flow/AdaptiveConfiguration.h"
#include "core/repository/VolatileContentRepository.h"
#include "utils/Id.h"
#include "utils/file/FileSystem.h"

namespace minifi = org::apache::nifi::minifi;

namespace {
enum class ComponentType {
  Processor,
  ControllerService,
  ParameterContext
};

struct SensitiveItem {
  ComponentType component_type;
  minifi::utils::Identifier component_id;
  std::string component_name;
  std::string item_name;
  std::string item_display_name;
  std::string item_value;
};

}  // namespace

namespace magic_enum::customize {
template<>
constexpr customize_t enum_name<ComponentType>(ComponentType type) noexcept {
  switch (type) {
    case ComponentType::Processor: return "Processor";
    case ComponentType::ControllerService: return "Controller service";
    case ComponentType::ParameterContext: return "Parameter context";
  }
  return invalid_tag;
}
}  // namespace magic_enum::customize

namespace {
std::vector<SensitiveItem> listSensitiveItems(const minifi::core::ProcessGroup &process_group,
    const std::unordered_map<std::string, gsl::not_null<std::unique_ptr<minifi::core::ParameterContext>>>& parameter_contexts) {
  std::vector<SensitiveItem> sensitive_items;

  for (const auto& [parameter_context_name, parameter_context] : parameter_contexts) {
    for (const auto& [parameter_name, parameter] : parameter_context->getParameters()) {
      if (parameter.sensitive) {
        sensitive_items.push_back(SensitiveItem{
            .component_type = ComponentType::ParameterContext,
            .component_id = parameter_context->getUUID(),
            .component_name = parameter_context_name,
            .item_name = parameter_name,
            .item_display_name = parameter_name,
            .item_value = parameter.value});
      }
    }
  }

  std::vector<minifi::core::Processor *> processors;
  process_group.getAllProcessors(processors);
  for (const auto* processor : processors) {
    gsl_Expects(processor);
    for (const auto& [_, property] : processor->getSupportedProperties()) {
      if (property.isSensitive()) {
        sensitive_items.push_back(SensitiveItem{
            .component_type = ComponentType::Processor,
            .component_id = processor->getUUID(),
            .component_name = processor->getName(),
            .item_name = property.getName(),
            .item_display_name = property.getDisplayName(),
            .item_value = std::string{property.getValue().value_or("")}});
      }
    }
  }

  std::unordered_set<minifi::utils::Identifier> processed_controller_services;
  for (const auto* controller_service_node : process_group.getAllControllerServices()) {
    gsl_Expects(controller_service_node);
    const auto* controller_service = controller_service_node->getControllerServiceImplementation();
    gsl_Expects(controller_service);
    if (processed_controller_services.contains(controller_service->getUUID())) {
      continue;
    }
    processed_controller_services.insert(controller_service->getUUID());
    for (const auto& [_, property] : controller_service->getSupportedProperties()) {
      if (property.isSensitive()) {
        sensitive_items.push_back(SensitiveItem{
            .component_type = ComponentType::ControllerService,
            .component_id = controller_service->getUUID(),
            .component_name = controller_service->getName(),
            .item_name = property.getName(),
            .item_display_name = property.getDisplayName(),
            .item_value = std::string{property.getValue().value_or("")}});
      }
    }
  }

  return sensitive_items;
}

std::unordered_map<minifi::utils::Identifier, minifi::core::flow::Overrides> createOverridesInteractively(const std::vector<SensitiveItem>& sensitive_items) {
  std::unordered_map<minifi::utils::Identifier, minifi::core::flow::Overrides> overrides;
  std::cout << '\n';
  for (const auto& sensitive_item : sensitive_items) {
    std::cout << magic_enum::enum_name(sensitive_item.component_type) << " " << sensitive_item.component_name << " (" << sensitive_item.component_id.to_string() << ") "
              << "has sensitive property or parameter " << sensitive_item.item_display_name << "\n    enter a new value or press Enter to keep the current value unchanged: ";
    std::cout.flush();
    std::string new_value;
    std::getline(std::cin, new_value);
    if (!new_value.empty()) {
      overrides[sensitive_item.component_id].add(sensitive_item.item_name, new_value);
    }
  }
  return overrides;
}

std::unordered_map<minifi::utils::Identifier, minifi::core::flow::Overrides> createOverridesForSingleItem(
    const std::vector<SensitiveItem>& sensitive_items, const std::string& component_id, const std::string& item_name, const std::string& item_value) {
  const auto sensitive_item_it = std::ranges::find_if(sensitive_items, [&](const auto& sensitive_item) {
    return sensitive_item.component_id.to_string().view() == component_id && (sensitive_item.item_name == item_name || sensitive_item.item_display_name == item_name);
  });
  if (sensitive_item_it == sensitive_items.end()) {
    std::cout << "No sensitive property or parameter found with this component ID and name.\n";
    return {};
  }
  return {{sensitive_item_it->component_id, minifi::core::flow::Overrides{}.add(sensitive_item_it->item_name, item_value)}};
}

std::unordered_map<minifi::utils::Identifier, minifi::core::flow::Overrides> createOverridesForReEncryption(const std::vector<SensitiveItem>& sensitive_items) {
  std::unordered_map<minifi::utils::Identifier, minifi::core::flow::Overrides> overrides;
  for (const auto& sensitive_item : sensitive_items) {
    overrides[sensitive_item.component_id].addOptional(sensitive_item.item_name, sensitive_item.item_value);
  }
  return overrides;
}

}  // namespace

namespace org::apache::nifi::minifi::encrypt_config::flow_config_encryptor {

EncryptionRequest::EncryptionRequest(EncryptionType type) : type{type} {
  gsl_Expects(type == EncryptionType::Interactive || type == EncryptionType::ReEncrypt);
}

EncryptionRequest::EncryptionRequest(std::string_view component_id, std::string_view item_name, std::string_view item_value)
    : type{EncryptionType::SingleProperty},
      component_id{component_id},
      item_name{item_name},
      item_value{item_value} {}

void encryptSensitiveValuesInFlowConfig(const EncryptionKeys& keys, const std::filesystem::path& minifi_home, const std::filesystem::path& flow_config_path, const EncryptionRequest& request) {
  const bool is_re_encrypting = keys.old_key.has_value();
  if (is_re_encrypting && request.type != EncryptionType::ReEncrypt) {
    throw std::runtime_error("Error: found .old key; please run --re-encrypt and then remove the .old key");
  }
  if (!is_re_encrypting && request.type == EncryptionType::ReEncrypt) {
    throw std::runtime_error("Error: cannot re-encrypt without an .old key!");
  }

  const auto configure = std::make_shared<ConfigureImpl>();
  configure->loadConfigureFile(minifi_home / DEFAULT_NIFI_PROPERTIES_FILE);

  bool encrypt_whole_flow_config_file = (configure->get(Configure::nifi_flow_configuration_encrypt) | utils::andThen(utils::string::toBool)).value_or(false);
  auto whole_file_encryptor = encrypt_whole_flow_config_file ? utils::crypto::EncryptionProvider::create(minifi_home) : std::nullopt;
  auto filesystem = std::make_shared<utils::file::FileSystem>(encrypt_whole_flow_config_file, whole_file_encryptor);

  auto sensitive_values_decryptor = is_re_encrypting ?
      utils::crypto::EncryptionProvider{utils::crypto::XSalsa20Cipher{*keys.old_key}} :
      utils::crypto::EncryptionProvider{utils::crypto::XSalsa20Cipher{keys.encryption_key}};

  core::extension::ExtensionManagerImpl::get().initialize(configure);

  core::flow::AdaptiveConfiguration adaptive_configuration{core::ConfigurationContext{
      .flow_file_repo = nullptr,
      .content_repo = nullptr,
      .configuration = configure,
      .path = flow_config_path,
      .filesystem = filesystem,
      .sensitive_values_encryptor = sensitive_values_decryptor
  }};

  const auto flow_config_content = filesystem->read(flow_config_path);
  if (!flow_config_content) {
    throw std::runtime_error(utils::string::join_pack("Could not read the flow configuration file \"", flow_config_path.string(), "\""));
  }

  const auto process_group = adaptive_configuration.getRootFromPayload(*flow_config_content);
  gsl_Expects(process_group);
  const auto sensitive_items = listSensitiveItems(*process_group, adaptive_configuration.getParameterContexts());

  const auto overrides = [&]() -> std::unordered_map<utils::Identifier, core::flow::Overrides> {
    switch (request.type) {
      case EncryptionType::Interactive: return createOverridesInteractively(sensitive_items);
      case EncryptionType::SingleProperty: return createOverridesForSingleItem(sensitive_items, request.component_id, request.item_name, request.item_value);
      case EncryptionType::ReEncrypt: return createOverridesForReEncryption(sensitive_items);
    }
    return {};
  }();

  if (overrides.empty()) {
    std::cout << "Nothing to do, exiting.\n";
    return;
  }

  if (is_re_encrypting) {
    adaptive_configuration.setSensitivePropertiesEncryptor(utils::crypto::EncryptionProvider{utils::crypto::XSalsa20Cipher{keys.encryption_key}});
  }

  std::string flow_config_str = adaptive_configuration.serializeWithOverrides(*process_group, overrides);
  adaptive_configuration.persist(flow_config_str);
}

}  // namespace org::apache::nifi::minifi::encrypt_config::flow_config_encryptor
