/**
 * 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 "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::ExtensionManager extension_manager(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
