/**
 * 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 "AgentDocs.h"

#include <algorithm>
#include <iostream>
#include <ranges>
#include <string>
#include <utility>
#include <vector>

#include "TableFormatter.h"
#include "agent/agent_docs.h"
#include "core/Core.h"
#include "core/Relationship.h"
#include "minifi-cpp/agent/agent_version.h"
#include "minifi-cpp/core/PropertyValidator.h"
#include "range/v3/algorithm/lexicographical_compare.hpp"
#include "range/v3/range/conversion.hpp"
#include "range/v3/view/join.hpp"
#include "range/v3/view/transform.hpp"
#include "utils/StringUtils.h"
#include "utils/file/FileUtils.h"

namespace {

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

std::string formatName(std::string_view name_view, bool is_required) {
  std::string name{name_view};
  if (is_required) { return "**" + name + "**"; }
  return name;
}

std::string formatAllowedValues(const minifi::core::Property& property) {
  if (property.getValidator().getEquivalentNifiStandardValidatorName() ==
      minifi::core::StandardPropertyValidators::BOOLEAN_VALIDATOR.getEquivalentNifiStandardValidatorName()) {
    return "true<br/>false";
  }
  const auto allowed_values = property.getAllowedValues();
  return allowed_values | ranges::views::join(std::string_view{"<br/>"}) | ranges::to<std::string>();
}

std::string formatDescription(std::string_view description_view, bool is_sensitive = false, bool supports_expression_language = false) {
  std::string description{description_view};
  minifi::utils::string::replaceAll(description, "\n", "<br/>");
  if (is_sensitive) { description += "<br/>**Sensitive Property: true**"; }
  if (supports_expression_language) { description += "<br/>**Supports Expression Language: true**"; }
  return description;
}

std::string formatDescription(const minifi::core::Property& property) {
  return formatDescription(property.getDescription(), property.isSensitive(), property.supportsExpressionLanguage());
}

std::string formatDescription(const minifi::core::DynamicProperty& dynamic_property) {
  return formatDescription(dynamic_property.description, false, dynamic_property.supports_expression_language);
}

std::string formatListOfRelationships(std::span<const minifi::core::Relationship> relationships) {
  return minifi::utils::string::join(", ", relationships, [](const auto& relationship) { return relationship.getName(); });
}

inline constexpr std::string_view APACHE_LICENSE = R"license(<!--
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.
-->)license";

void writeHeader(std::ostream& docs, const std::vector<std::pair<std::string, minifi::ClassDescription>>& class_descriptions) {
  docs << APACHE_LICENSE;

  docs << "\n\n## Table of Contents\n\n";
  for (const auto& [name, documentation] : class_descriptions) {
    docs << "- [" << name << "](#" << name << ")\n";
  }
}

void writeName(std::ostream& docs, std::string_view name) {
  docs << "\n\n## " << name;
}

void writeDescription(std::ostream& docs, const minifi::ClassDescription& documentation) {
  docs << "\n\n### Description\n\n";
  docs << documentation.description_;
}

void writeProperties(std::ostream& docs, const minifi::ClassDescription& documentation) {
  docs << "\n\n### Properties";
  docs << "\n\nIn the list below, the names of required properties appear in bold. Any other properties (not in bold) are considered optional. "
       << "The table also indicates any default values, and whether a property supports the NiFi Expression Language.";
  minifi::docs::Table properties{{"Name", "Default Value", "Allowable Values", "Description"}};
  for (const auto& property : documentation.class_properties_) {
    properties.addRow({formatName(property.getName(), property.getRequired()),
        property.getDefaultValue().value_or(""),
        formatAllowedValues(property),
        formatDescription(property)});
  }
  docs << "\n\n" << properties.toString();
}

void writeDynamicProperties(std::ostream& docs, const minifi::ClassDescription& documentation) {
  if (documentation.dynamic_properties_.empty()) { return; }

  docs << "\n### Dynamic Properties\n\n";
  minifi::docs::Table dynamic_properties{{"Name", "Value", "Description"}};
  for (const auto& dynamic_property : documentation.dynamic_properties_) {
    dynamic_properties.addRow({formatName(dynamic_property.name, false), std::string(dynamic_property.value), formatDescription(dynamic_property)});
  }
  docs << dynamic_properties.toString();
}

void writeRelationships(std::ostream& docs, const minifi::ClassDescription& documentation) {
  docs << "\n### Relationships\n\n";
  minifi::docs::Table relationships{{"Name", "Description"}};
  for (const auto& rel : documentation.class_relationships_) {
    relationships.addRow({rel.getName(), formatDescription(rel.getDescription())});
  }
  docs << relationships.toString();
}

void writeOutputAttributes(std::ostream& docs, const minifi::ClassDescription& documentation) {
  if (documentation.output_attributes_.empty()) { return; }

  docs << "\n### Output Attributes";
  minifi::docs::Table output_attributes{{"Attribute", "Relationship", "Description"}};
  for (const auto& output_attribute : documentation.output_attributes_) {
    output_attributes.addRow({std::string(output_attribute.name),
        formatListOfRelationships(output_attribute.relationships),
        formatDescription(output_attribute.description)});
  }
  docs << "\n\n" << output_attributes.toString();
}

std::string extractClassName(const std::string& full_class_name) {
  return minifi::utils::string::split(full_class_name, ".").back();
}

void writeProcessor(std::ostream& os, const std::string_view name, const minifi::ClassDescription& documentation) {
  writeName(os, name);
  writeDescription(os, documentation);
  writeProperties(os, documentation);
  writeDynamicProperties(os, documentation);
  writeRelationships(os, documentation);
  writeOutputAttributes(os, documentation);
}

void writeControllerService(std::ostream& os, const std::string_view name, const minifi::ClassDescription& documentation) {
  writeName(os, name);
  writeDescription(os, documentation);
  writeProperties(os, documentation);
}

void writeParameterProvider(std::ostream& os, const std::string_view name, const minifi::ClassDescription& documentation) {
  writeName(os, name);
  writeDescription(os, documentation);
  writeProperties(os, documentation);
}

class MonolithDocumentation {
 public:
  explicit MonolithDocumentation() {
    for (const auto& [bundle_id, components] : minifi::ClassDescriptionRegistry::getClassDescriptions()) {
      addComponents(components);
    }
    sort();
  }

  void write(const std::filesystem::path& docs_dir) {
    std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
    std::ofstream processors_md(docs_dir / "PROCESSORS.md");
    std::ofstream parameter_providers_md(docs_dir / "PARAMETER_PROVIDERS.md");
    gsl_Assert(controllers_md && processors_md && parameter_providers_md);

    writeControllers(controllers_md);
    writeProcessors(processors_md);
    writeParameterProviders(parameter_providers_md);
  }

 private:
  void addComponents(const minifi::Components& components) {
    for (const auto& controller_service_description : components.controller_services) {
      controller_services.emplace_back(extractClassName(controller_service_description.full_name_), controller_service_description);
    }
    for (const auto& processor_description : components.processors) {
      processors.emplace_back(extractClassName(processor_description.full_name_), processor_description);
    }
    for (const auto& parameter_provider_description : components.parameter_providers) {
      parameter_providers.emplace_back(extractClassName(parameter_provider_description.full_name_), parameter_provider_description);
    }
  }

  void sort() {
    auto lower_case_first = [](const auto& kv) { return minifi::utils::string::toLower(kv.first); };
    std::ranges::sort(controller_services, std::less(), lower_case_first);
    std::ranges::sort(processors, std::less(), lower_case_first);
    std::ranges::sort(parameter_providers, std::less(), lower_case_first);
  }

  void writeControllers(std::ostream& os) {
    writeHeader(os, controller_services);
    for (const auto& [name, documentation] : controller_services) {
      writeControllerService(os, name, documentation);
    }
  }

  void writeProcessors(std::ostream& os) {
    writeHeader(os, processors);
    for (const auto& [name, documentation] : processors) {
      writeProcessor(os, name, documentation);
    }
  }

  void writeParameterProviders(std::ostream& os) {
    writeHeader(os, parameter_providers);
    for (const auto& [name, documentation] : parameter_providers) {
      writeParameterProvider(os, name, documentation);
    }
  }

  std::vector<std::pair<std::string, minifi::ClassDescription>> controller_services;
  std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
  std::vector<std::pair<std::string, minifi::ClassDescription>> parameter_providers;
};

class ModularDocumentation {
 public:
  static void write(const std::filesystem::path& docs_dir) {
    for (auto [bundle_id, components] : minifi::ClassDescriptionRegistry::getClassDescriptions()) {
      if (components.empty()) { continue; }
      sortComponents(components);
      writeModule(docs_dir, bundle_id.name, components);
    }
  }

 private:
  static void sortComponents(minifi::Components& components) {
    auto lower_case_short_name = [](const auto& b) { return minifi::utils::string::toLower(b.short_name_); };
    std::ranges::sort(components.processors, {}, lower_case_short_name);
    std::ranges::sort(components.controller_services, {}, lower_case_short_name);
    std::ranges::sort(components.parameter_providers, {}, lower_case_short_name);
  }

  static void writeComponentParts(std::ostream& os, const std::vector<minifi::ClassDescription>& class_descriptions, const std::string_view h3) {
    if (!class_descriptions.empty()) {
      os << fmt::format("### {}\n\n", h3);
      for (const auto& class_description : class_descriptions) {
        const auto name = extractClassName(class_description.full_name_);
        os << "- [" << name << "](#" << name << ")\n";
      }
    }
  }

  static void writeToC(std::ostream& os, const minifi::Components& components) {
    os << "\n\n## Table of Contents\n\n";
    writeComponentParts(os, components.processors, "Processors");
    writeComponentParts(os, components.controller_services, "Controller Services");
    writeComponentParts(os, components.parameter_providers, "Parameter Providers");
  }

  static void writeModule(const std::filesystem::path& docs_dir, const std::string_view module_name, const minifi::Components& components) {
    const auto dir_creation_result = minifi::utils::file::create_dir(docs_dir / "modules");
    gsl_Assert(dir_creation_result == 0);
    std::ofstream os(docs_dir / "modules" / (std::string(module_name) + ".md"));
    gsl_Assert(os);
    os << APACHE_LICENSE;

    writeToC(os, components);

    for (const auto& processor : components.processors) {
      writeProcessor(os, extractClassName(processor.full_name_), processor);
    }

    for (const auto& controller_service : components.controller_services) {
      writeControllerService(os, extractClassName(controller_service.full_name_), controller_service);
    }

    for (const auto& parameter_provider_description : components.parameter_providers) {
      writeParameterProvider(os, extractClassName(parameter_provider_description.full_name_), parameter_provider_description);
    }
  }
};
}  // namespace

namespace org::apache::nifi::minifi::docs {

void AgentDocs::generate(const std::filesystem::path& docs_dir) {
  MonolithDocumentation monolith_docs;
  monolith_docs.write(docs_dir);

  ModularDocumentation::write(docs_dir);
}

}  // namespace org::apache::nifi::minifi::docs
