#include "redfish_devpath_injector.hpp"

#include <fstream>
#include <memory>
#include <sstream>
#include <string>
#include <string_view>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "boost/beast/http/status.hpp"  // NOLINT
#include "boost/beast/http/verb.hpp"  // NOLINT
#include "g3/macros.h"
#include "redfish_to_uhm_mapping.pb.h"
#include "redfish_to_uhm_mapping_value.hpp"
#include "http_request.hpp"

#include <nlohmann/json.hpp>
#include "topology_config.pb.h"
#include "tlbmc/redfish/data/stable_id.h"
#include "stable_id.pb.h"
#include "google/protobuf/text_format.h"

namespace devpath_plugin {

namespace {

absl::StatusOr<std::string> ReadFileToString(std::string_view path) {
  std::ifstream input(std::string{path});
  if (!input.is_open()) {
    return absl::NotFoundError(
        absl::StrCat("Failed to open RedfishToUhmMapping file at: ", path));
  }
  std::stringstream buffer;
  buffer << input.rdbuf();
  return buffer.str();
}

}  // namespace

absl::StatusOr<std::unique_ptr<RedfishDevpathInjector>>
RedfishDevpathInjector::Create(std::string_view mapping_config_path) {
  ECCLESIA_ASSIGN_OR_RETURN(std::string config_content,
                            ReadFileToString(mapping_config_path));

  RedfishToUhmMappingConfig config;
  if (!google::protobuf::TextFormat::ParseFromString(config_content, &config)) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Failed to parse RedfishToUhmMappingConfig textproto from: ",
        mapping_config_path));
  }

  // new keyword required to access private constructor
  std::unique_ptr<RedfishDevpathInjector> injector(
      new RedfishDevpathInjector());
  for (const RedfishToUhmMapping& mapping : config.redfish_to_uhm_mapping()) {
    std::shared_ptr<RedfishToUhmMappingValue> value =
        std::make_shared<RedfishToUhmMappingValue>();
    value->uhm_monitored_component_key = mapping.uhm_monitored_component_key();
    value->redfish_expose_config = mapping.redfish_expose_config();

    injector->trie_.Insert(mapping.key(), value);
  }

  return injector;
}


void RedfishDevpathInjector::Inject(
    const crow::Request& req,
    crow::Response& res) const {
  // No-op if response is not successful.
  if (res.result() != boost::beast::http::status::ok) {
    return;
  }
  // Only modify GET requests.
  if (req.method() != boost::beast::http::verb::get) {
    return;
  }

  Key lookup_key;
  lookup_key.set_redfish_url_pattern(std::string(req.url().path()));

  std::shared_ptr<const RedfishToUhmMappingValue> value =
      trie_.GetMappingFromUrl(lookup_key);
  if (value == nullptr) {
    return;
  }

  std::string_view barepath = value->uhm_monitored_component_key.barepath();
  const RedfishExposeConfig& expose_config = value->redfish_expose_config;

  milotic_tlbmc::LocationContext location_context;
  location_context.set_devpath(std::string(barepath));
  if (!expose_config.embedded_location_context().empty()) {
    location_context.add_logical_identifiers(
        expose_config.embedded_location_context());
  }
  milotic_tlbmc::StableId stable_id = milotic_tlbmc::GetStableId(
      location_context, /*root_chassis_location_code=*/"");
  if (!expose_config.service_label_override().empty()) {
    stable_id.set_service_label(expose_config.service_label_override());
  }
  if (!expose_config.part_location_context_override().empty()) {
    stable_id.set_part_location_context(
        expose_config.part_location_context_override());
  }

  std::string_view location_key =
      expose_config.use_physical_location() ? "PhysicalLocation" : "Location";
  nlohmann::json& location_json = res.jsonValue[location_key];

  location_json["PartLocation"]["ServiceLabel"] = stable_id.service_label();
  if (!expose_config.location_type().empty()) {
    location_json["PartLocation"]["LocationType"] =
        expose_config.location_type();
  }

  if (expose_config.set_plc_as_placeholder()) {
    location_json["PartLocationContext"] = "PlaceHolderAndShouldNotBeUsed";
  } else if (stable_id.has_part_location_context() &&
             !stable_id.part_location_context().empty()) {
    location_json["PartLocationContext"] = stable_id.part_location_context();
  } else {
    location_json.erase("PartLocationContext");
  }

  if (expose_config.expose_oem_google_devpath()) {
    location_json["Oem"]["Google"]["Devpath"] = barepath;
  }

  if (stable_id.has_embedded_location_context() &&
      !stable_id.embedded_location_context().empty()) {
    location_json["Oem"]["Google"]["EmbeddedLocationContext"] =
        stable_id.embedded_location_context();
  }
}

}  // namespace devpath_plugin
