#include "log_services.hpp"

#include <systemd/sd-bus.h>
#include <systemd/sd-journal.h>
#include <tinyxml2.h>
#include <unistd.h>

#include <algorithm>
#include <array>
#include <cerrno>
#include <charconv>
#include <chrono>  // NOLINT
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <filesystem>  // NOLINT
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iostream>
#include <iterator>
#include <memory>
#include <optional>
#include <span>  // NOLINT
#include <sstream>
#include <string>
#include <string_view>
#include <system_error>  // NOLINT
#include <tuple>
#include <unordered_map>
#include <utility>
#include <variant>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "boost/algorithm/string/case_conv.hpp"  // NOLINT
#include "boost/algorithm/string/classification.hpp"  // NOLINT
#include "boost/algorithm/string/replace.hpp"  // NOLINT
#include "boost/algorithm/string/split.hpp"  // NOLINT
#include "boost/beast/core/detail/base64.hpp"  // NOLINT
#include "boost/beast/http/verb.hpp"  // NOLINT
#include "boost/container/flat_map.hpp"  // NOLINT
#include "boost/system/linux_error.hpp"  // NOLINT
#include "bmcweb_config.h"
#include "app.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "utility.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "http_utility.hpp"
#include "human_sort.hpp"
#include "str_utility.hpp"
#include "error_messages.hpp"
#include "generated/enums/log_entry.hpp"
#include "gzfile.hpp"
#include "query.hpp"
#include "registries.hpp"
#include "registries/privilege_registry.hpp"
#include "task_messages.hpp"
#include "dbus_utils.hpp"
#include "json_utils.hpp"
#include "system_utils.hpp"
#include "time_utils.hpp"
#include "external_storer.hpp"  // NOLINT(misc-include-cleaner)
#include "health.hpp"
#include "redfish_util.hpp"
#include "task.hpp"
#include <nlohmann/json.hpp>
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/message.hpp"
#include "sdbusplus/message/native_types.hpp"
#include "sdbusplus/unpack_properties.hpp"  // NOLINT

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp"  // NOLINT
#endif

namespace redfish {
#ifdef BMCWEB_ENABLE_RASMANAGER_EVENT_LOG
constexpr char const* rasManagerObject = "com.intel.RAS";
constexpr char const* rasManagerPath = "/com/intel/ras/logs";
#endif

#ifdef BMCWEB_ENABLE_ILIAD_EVENT_LOG
constexpr char const* iliadObject = "xyz.openbmc_project.IliadManager";
constexpr char const* iliadPath =
    "/xyz/openbmc_project/iliad_event/0/CPER/entry/";
#endif

constexpr char const* crashdumpObject =
    bmcwebEnableAmd ? "com.amd.crashdump" : "com.intel.crashdump";
constexpr char const* crashdumpPath =
    bmcwebEnableAmd ? "/com/amd/crashdump" : "/com/intel/crashdump";
constexpr char const* crashdumpInterface =
    bmcwebEnableAmd ? "com.amd.crashdump" : "com.intel.crashdump";
constexpr char const* deleteAllInterface =
    "xyz.openbmc_project.Collection.DeleteAll";
constexpr char const* crashdumpOnDemandInterface =
    bmcwebEnableAmd ? "com.amd.crashdump.OnDemand"
                    : "com.intel.crashdump.OnDemand";
constexpr char const* crashdumpTelemetryInterface =
    bmcwebEnableAmd ? "com.amd.crashdump.Telemetry"
                    : "com.intel.crashdump.Telemetry";
constexpr char const* pprFileInterface =
    "xyz.openbmc_project.PostPackageRepair.PprData";
constexpr std::string_view kPrimaryCrashdumpPrefix =
    bmcwebEnableAmd ? "amd_" : "intel_";
constexpr std::string_view kDumpManagerCrashdumpPrefix = "dumpmanager_";
constexpr std::string_view kSystemAgnosticDumpEntryPathPrefix =
    "/xyz/openbmc_project/dump/faultlog/entry/";
constexpr std::string_view kFaultLogTypePrefix =
    "xyz.openbmc_project.Common.FaultLogType.FaultLogTypes.";

constexpr std::array<std::string_view, 1> systemInterfaces{
    {"xyz.openbmc_project.Inventory.Item.System"}};

constexpr char const* pprFileObject = "xyz.openbmc_project.PostPackageRepair";
constexpr char const* pprFilePath = "/xyz/openbmc_project/PostPackageRepair";
constexpr char const* defaultLogPrefix = "log";
constexpr uint64_t kMaxRuntimePPRCount = 8;
constexpr uint64_t kPPRTypeBoottimeMask = 0x8000;
constexpr uint16_t kBtSetToHardMask = 0x01;
constexpr uint16_t kRtToBtMask = 0x02;

enum class DumpCreationProgress : std::uint8_t {
  DUMP_CREATE_SUCCESS,
  DUMP_CREATE_FAILED,
  DUMP_CREATE_INPROGRESS
};

std::string dumpTypeToString(DumpType dumpType) {
  return std::string(dumpTypeStrings[static_cast<size_t>(dumpType)]);
}

inline std::string bootTimeDataTypeToString(const BootTimeDataType dataType) {
  return std::string(bootTimeDataTypeString[static_cast<size_t>(dataType)]);
}

inline static int getJournalMetadata(sd_journal* journal,
                                     std::string_view field,
                                     std::string_view& contents) {
  const char* data = nullptr;
  size_t length = 0;
  int ret = 0;
  // Get the metadata from the requested field of the journal entry
  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
  const void** dataVoid = reinterpret_cast<const void**>(&data);

  ret = sd_journal_get_data(journal, field.data(), dataVoid, &length);
  if (ret < 0) {
    return ret;
  }
  contents = std::string_view(data, length);
  // Only use the content after the "=" character.
  contents.remove_prefix(std::min(contents.find('=') + 1, contents.size()));
  return ret;
}

inline static int getJournalMetadataToInt64(sd_journal* journal,
                                            std::string_view field,
                                            int64_t& contents) {
  int ret = 0;
  std::string_view metadata;
  // Get the metadata from the requested field of the journal entry
  ret = getJournalMetadata(journal, field, metadata);
  if (ret < 0) {
    return ret;
  }

  bool parsed = absl::SimpleAtoi(metadata, &contents);

  if (!parsed) {
    BMCWEB_LOG_ERROR
        << "getJournalMetadata: Failed to parse metadata(severity): "
        << metadata;
    return -EINVAL;
  }

  return ret;
}

inline static bool getEntryTimestamp(sd_journal* journal,
                                     std::string& entryTimestamp) {
  int ret = 0;
  uint64_t timestamp = 0;
  ret = sd_journal_get_realtime_usec(journal, &timestamp);
  if (ret < 0) {
    BMCWEB_LOG_ERROR << "Failed to read entry timestamp: " << strerror(-ret);
    return false;
  }
  entryTimestamp = redfish::time_utils::getDateTimeUintUs(timestamp);
  return true;
}

inline static bool getUniqueEntryID(sd_journal* journal, std::string& entryID,
                                    const bool firstEntry = true) {
  int ret = 0;
  static uint64_t prevTs = 0;
  static int index = 0;
  if (firstEntry) {
    prevTs = 0;
  }

  // Get the entry timestamp
  uint64_t curTs = 0;
  ret = sd_journal_get_realtime_usec(journal, &curTs);
  if (ret < 0) {
    BMCWEB_LOG_ERROR << "Failed to read entry timestamp: " << strerror(-ret);
    return false;
  }
  // If the timestamp isn't unique, increment the index
  if (curTs == prevTs) {
    index++;
  } else {
    // Otherwise, reset it
    index = 0;
  }
  // Save the timestamp
  prevTs = curTs;

  entryID = std::to_string(curTs);
  if (index > 0) {
    entryID += "_" + std::to_string(index);
  }
  return true;
}

inline static bool getTimestampFromID(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& entryID, uint64_t& timestamp, uint64_t& index) {
  if (entryID.empty()) {
    return false;
  }
  // Convert the unique ID back to a timestamp to find the entry
  std::string_view tsStr(entryID);

  auto underscorePos = tsStr.find('_');
  if (underscorePos != std::string_view::npos) {
    // Timestamp has an index
    tsStr.remove_suffix(tsStr.size() - underscorePos);
    std::string_view indexStr(entryID);
    indexStr.remove_prefix(underscorePos + 1);
    auto [ptr, ec] = std::from_chars(indexStr.data(),
                                     indexStr.data() + indexStr.size(), index);
    if (ec != std::errc()) {
      messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
      return false;
    }
  }
  // Timestamp has no index
  auto [ptr, ec] =
      std::from_chars(tsStr.data(), tsStr.data() + tsStr.size(), timestamp);
  if (ec != std::errc()) {
    messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
    return false;
  }
  return true;
}

inline log_entry::OriginatorTypes mapDbusOriginatorTypeToRedfish(
    const std::string& originatorType) {
  if (originatorType ==
      "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client") {
    return log_entry::OriginatorTypes::Client;
  }
  if (originatorType ==
      "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Internal") {
    return log_entry::OriginatorTypes::Internal;
  }
  if (originatorType ==
      "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes."
      "SupportingService") {
    return log_entry::OriginatorTypes::SupportingService;
  }
  return log_entry::OriginatorTypes::Invalid;
}

inline void parseDumpEntryFromDbusObject(
    const dbus::utility::ManagedObjectType::value_type& object,
    std::string& dumpStatus, uint64_t& size, uint64_t& timestampUs,
    std::string& originatorId, log_entry::OriginatorTypes& originatorType,
    std::string& entryType, std::string& primaryLogId,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  for (const auto& interfaceMap : object.second) {
    if (interfaceMap.first == "xyz.openbmc_project.Common.Progress") {
      for (const auto& propertyMap : interfaceMap.second) {
        if (propertyMap.first == "Status") {
          const auto* status = std::get_if<std::string>(&propertyMap.second);
          if (status == nullptr) {
            messages::internalError(asyncResp->res);
            break;
          }
          dumpStatus = *status;
        }
      }
    } else if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry") {
      for (const auto& propertyMap : interfaceMap.second) {
        if (propertyMap.first == "Size") {
          const auto* sizePtr = std::get_if<uint64_t>(&propertyMap.second);
          if (sizePtr == nullptr) {
            messages::internalError(asyncResp->res);
            break;
          }
          size = *sizePtr;
          break;
        }
      }
    } else if (interfaceMap.first == "xyz.openbmc_project.Time.EpochTime") {
      for (const auto& propertyMap : interfaceMap.second) {
        if (propertyMap.first == "Elapsed") {
          const uint64_t* usecsTimeStamp =
              std::get_if<uint64_t>(&propertyMap.second);
          if (usecsTimeStamp == nullptr) {
            messages::internalError(asyncResp->res);
            break;
          }
          timestampUs = *usecsTimeStamp;
          break;
        }
      }
    } else if (interfaceMap.first ==
               "xyz.openbmc_project.Common.OriginatedBy") {
      for (const auto& propertyMap : interfaceMap.second) {
        if (propertyMap.first == "OriginatorId") {
          const std::string* id = std::get_if<std::string>(&propertyMap.second);
          if (id == nullptr) {
            messages::internalError(asyncResp->res);
            break;
          }
          originatorId = *id;
        }

        if (propertyMap.first == "OriginatorType") {
          const std::string* type =
              std::get_if<std::string>(&propertyMap.second);
          if (type == nullptr) {
            messages::internalError(asyncResp->res);
            break;
          }

          originatorType = mapDbusOriginatorTypeToRedfish(*type);
          if (originatorType == log_entry::OriginatorTypes::Invalid) {
            messages::internalError(asyncResp->res);
            break;
          }
        }
      }
    } else if (interfaceMap.first ==
               "xyz.openbmc_project.Dump.Entry.FaultLog") {
      for (const auto& propertyMap : interfaceMap.second) {
        if (propertyMap.first == "Type") {
          const std::string* entryTypePtr =
              std::get_if<std::string>(&propertyMap.second);
          if (entryTypePtr == nullptr) {
            messages::internalError(asyncResp->res);
            break;
          }
          if (*entryTypePtr ==
              "xyz.openbmc_project.Common.FaultLogType.FaultLogTypes."
              "Crashdump") {
            entryType = "Crashdump";
          } else if (*entryTypePtr ==
                     "xyz.openbmc_project.Common.FaultLogType.FaultLogTypes."
                     "CPER") {
            entryType = "CPER";
          } else if (*entryTypePtr ==
                     "xyz.openbmc_project.Common.FaultLogType.FaultLogTypes."
                     "IliadCPER") {
            entryType = "IliadCPER";
          } else if (entryTypePtr->starts_with(kFaultLogTypePrefix)) {
            entryType = entryTypePtr->substr(kFaultLogTypePrefix.size());
          }
        } else if (propertyMap.first == "PrimaryLogId") {
          const std::string* primaryLogIdPtr =
              std::get_if<std::string>(&propertyMap.second);
          if (primaryLogIdPtr == nullptr) {
            messages::internalError(asyncResp->res);
            break;
          }
          primaryLogId = *primaryLogIdPtr;
        }
      }
    }
  }
}

static std::string getDumpEntriesPath(const Dump& dump) {
  std::string entriesPath;

  switch (dump.type) {
    case DumpType::BMC_DUMP:
      entriesPath = "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/";
      break;
    case DumpType::BMC_FAULT_LOG:
      entriesPath = "/redfish/v1/Managers/bmc/LogServices/FaultLog/Entries/";
      break;
    case DumpType::SYSTEM_DUMP:
      entriesPath = "/redfish/v1/Systems/system/LogServices/Dump/Entries/";
      break;
    case DumpType::SYSTEM_FAULT_LOG:
      if (dump.systemName) {
        entriesPath = "/redfish/v1/Systems/" + *dump.systemName +
                      "/LogServices/FaultLog/Entries/";
      }
      break;
  }

  // Returns empty string on error
  return entriesPath;
}

constexpr std::array<std::pair<std::string_view, std::string_view>, 2>
    systemNameToDumpEntryPath{
        {{"system1", "/xyz/openbmc_project/dump/faultlog/0"},
         {"system2", "/xyz/openbmc_project/dump/faultlog/1"}}};

inline std::optional<std::string> getDumpEntryPathFromDump(const Dump& dump) {
  if (!dump.systemName || *dump.systemName == "system") {
    return "/xyz/openbmc_project/dump/" +
           std::string(
               boost::algorithm::to_lower_copy(dumpTypeToString(dump.type))) +
           "/entry/";
  }

  for (const auto& mapping : systemNameToDumpEntryPath) {
    if (mapping.first == *dump.systemName) {
      return std::string(mapping.second) + "/entry/";
    }
  }

  return std::nullopt;
}

std::string getRedfishPrefixForDbusObjectPath(
    const sdbusplus::message::object_path& objectPath,
    std::string_view systemName) {
  if (objectPath.str.starts_with(kSystemAgnosticDumpEntryPathPrefix)) {
    return std::string(kDumpManagerCrashdumpPrefix);
  }
  return absl::StrCat(kDumpManagerCrashdumpPrefix, systemName, "_");
}

// This function queries the collectionUri, and add the fields from the
// collectionUri to asyncResp. When the collectionUri response has less
// faultLog entries, the additional fields in asyncResp will be removed.
//
// This can happen during log rotation. We want to avoid incomplete
// data in asyncResp in the middle of log rotation.
void queryFaultCollection(
    App& app, const crow::Request& origReq,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& collectionUri,
    std::unordered_map<std::string, nlohmann::json::json_pointer>&
        faultLogEntries,
    nlohmann::json& originalMembers) {
  std::error_code ec;
  crow::Request newReq({boost::beast::http::verb::get, collectionUri, 11}, ec);

  if (ec) {
    messages::internalError(asyncResp->res);
    return;
  }

  newReq.with_trust_bundle = origReq.with_trust_bundle;
  newReq.peer_authenticated = origReq.peer_authenticated;
  newReq.peer_privileges = origReq.peer_privileges;
  newReq.fromGrpc = origReq.fromGrpc;

  auto newAsyncResp = std::make_shared<bmcweb::AsyncResp>(asyncResp->strand_);
  newAsyncResp->response_type = asyncResp->response_type;

  newAsyncResp->res.setCompleteRequestHandler(
      [faultLogEntries{std::move(faultLogEntries)},
       originalMembers(std::move(originalMembers)),
       asyncResp](const crow::Response& subResp) mutable {
        if (!subResp.jsonValue.contains("Members")) {
          BMCWEB_LOG_WARNING << "Sub query response is empty.";
          return;
        }
        for (const auto& resItem : subResp.jsonValue["Members"]) {
          const std::string link = resItem["@odata.id"];
          if (!faultLogEntries.contains(link)) {
            // This could happen when there is inconsistency in cache.
            // Ignoring this specific entry.
            BMCWEB_LOG_WARNING << "Entry doesn't exist in response: " << link;
            continue;
          }

          // This path is within "Members". Since it has been moved to a
          // separate jsonArray, it looks like '/0/Links/RelatedLogEntries/0'
          // here.
          const std::string& jsonPath = faultLogEntries.at(link).to_string();
          std::vector<std::string> split;
          bmcweb::split(split, jsonPath, '/');
          if (split.size() < 2) {
            BMCWEB_LOG_WARNING << "Invalid JSON path for entry " << link;
            continue;
          }
          unsigned int memberIdx =
              static_cast<unsigned int>(std::stoi(split[1]));
          originalMembers[faultLogEntries.at(link)] = resItem;
          asyncResp->res.jsonValue["Members"].push_back(
              std::move(originalMembers[""_json_pointer / memberIdx]));
        }

        asyncResp->res.jsonValue["Members@odata.count"] =
            asyncResp->res.jsonValue["Members"].size();

        asyncResp->res.eventSourceIds.insert(
            asyncResp->res.eventSourceIds.end(), subResp.eventSourceIds.begin(),
            subResp.eventSourceIds.end());
      });

  app.handle(newReq, newAsyncResp);
  redfish::query_param::propogateError(asyncResp->res, newAsyncResp->res);
}

inline bool shouldEfficientExpandFaultLog(DumpType dumpType,
                                          uint64_t delegatedExpandLevel) {
  // We only apply efficient expand when delegated expand level is 2+,
  // as log services are auto-expanded.
  // And only BMC_FAULT_LOG and SYSTEM_FAULT_LOG is supported.
  return (dumpType == DumpType::BMC_FAULT_LOG ||
          dumpType == DumpType::SYSTEM_FAULT_LOG) &&
         delegatedExpandLevel > 1;
}

void getDumpEntryCollection(App& app, const crow::Request& req,
                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                            const Dump& dump,
                            const query_param::Query& delegatedQuery) {
  std::string entriesPath = getDumpEntriesPath(dump);
  if (entriesPath.empty()) {
    messages::internalError(asyncResp->res);
    return;
  }

  uint64_t filterTimestampUs = 0;
  uint64_t delegatedExpandLevel = delegatedQuery.expandLevel;

  if (!delegatedQuery.filter.empty()) {
    std::vector<std::string> filterParams;
    bmcweb::split(filterParams, delegatedQuery.filter, ' ');

    // Only supported filter query is "Created ge '<timestamp>'"
    if (filterParams.size() != 3 || filterParams[0] != "Created" ||
        filterParams[1] != "ge") {
      redfish::messages::queryParameterValueFormatError(
          asyncResp->res, "$filter", delegatedQuery.filter);
      asyncResp->res.result(boost::beast::http::status::not_implemented);
      return;
    }

    std::string& timestampStr = filterParams[2];
    if (timestampStr.size() < 2 || timestampStr.at(0) != '\'' ||
        timestampStr.at(timestampStr.size() - 1) != '\'') {
      BMCWEB_LOG_ERROR << "Filter Timestamp not quoted " << timestampStr;
      redfish::messages::queryParameterValueFormatError(
          asyncResp->res, "$filter", delegatedQuery.filter);
      return;
    }
    std::optional<redfish::time_utils::usSinceEpoch> filterTimestampUsChrono =
        redfish::time_utils::dateStringToEpoch(
            timestampStr.substr(1, timestampStr.size() - 2));
    if (filterTimestampUsChrono == std::nullopt) {
      BMCWEB_LOG_ERROR << "Filter Timestamp validation failure"
                       << filterParams[2];
      redfish::messages::queryParameterValueFormatError(
          asyncResp->res, "$filter", delegatedQuery.filter);
      return;
    }
    filterTimestampUs = filterTimestampUsChrono->count();
  }

  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
      "xyz.openbmc_project.Dump.Manager", {"/xyz/openbmc_project/dump"},
      context,
      // App's lifespan is tied with the program as it is created in the main
      // function
      [&app, asyncResp, entriesPath, dump, filterTimestampUs, req,
       delegatedExpandLevel](
          const boost::system::error_code& ec,
          const dbus::utility::ManagedObjectType& managedObjects) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DumpEntry resp_handler got error " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        // Remove ending slash
        std::string odataIdStr = entriesPath;
        if (!odataIdStr.empty()) {
          odataIdStr.pop_back();
        }

        asyncResp->res.jsonValue["@odata.type"] =
            "#LogEntryCollection.LogEntryCollection";
        asyncResp->res.jsonValue["@odata.id"] = std::move(odataIdStr);
        asyncResp->res.jsonValue["Name"] =
            dumpTypeToString(dump.type) + " Dump Entries";
        asyncResp->res.jsonValue["Description"] =
            "Collection of " + dumpTypeToString(dump.type) + " Dump Entries";

        nlohmann::json& entriesArray = asyncResp->res.jsonValue["Members"];
        entriesArray = nlohmann::json::array();
        std::optional<std::string> dumpEntryPath =
            getDumpEntryPathFromDump(dump);

        if (!dumpEntryPath) {
          BMCWEB_LOG_ERROR << "Cant convert system "
                           << dump.systemName.value_or("None")
                           << "to dumpEntryPath";
          messages::internalError(asyncResp->res);
          return;
        }

        dbus::utility::ManagedObjectType resp = managedObjects;
        std::sort(resp.begin(), resp.end(), [](const auto& l, const auto& r) {
          return AlphanumLess<std::string>()(l.first.filename(),
                                             r.first.filename());
        });

        // This maps the collection URI to all the entries and their json
        // pointer. This is used to fill in the entries in the final response.
        // Example:
        //  /redfish/v1/Systems/system1/LogServices/HostCper/Entries ->
        //    /redfish/v1/Systems/system1/LogServices/HostCper/Entries/1 ->
        //     /Members/Links/RelatedLogEntries/0
        std::unordered_map<
            std::string,
            std::unordered_map<std::string, nlohmann::json::json_pointer>>
            faultLogEntries;

        // This maps the collection URI to all the original members.
        // Example:
        //  /redfish/v1/Systems/system1/LogServices/HostCper/Entries ->
        //  [
        //        {
        //         "@odata.id": "../FaultLog/Entries/1",
        //        }
        //  ]
        std::unordered_map<std::string, nlohmann::json> faultLogOriginalMembers;

        for (auto& object : resp) {
          if (object.first.str.find(*dumpEntryPath) == std::string::npos) {
            continue;
          }
          uint64_t timestampUs = 0;
          uint64_t size = 0;
          std::string dumpStatus;
          std::string originatorId;
          std::string primaryLogId;
          std::string entryType;
          log_entry::OriginatorTypes originatorType =
              log_entry::OriginatorTypes::Internal;
          nlohmann::json::object_t thisEntry;

          std::string entryID = object.first.filename();
          if (entryID.empty()) {
            continue;
          }

          parseDumpEntryFromDbusObject(object, dumpStatus, size, timestampUs,
                                       originatorId, originatorType, entryType,
                                       primaryLogId, asyncResp);

          if (dumpStatus !=
                  "xyz.openbmc_project.Common.Progress.OperationStatus."
                  "Completed" &&
              !dumpStatus.empty()) {
            // Dump status is not Complete, no need to enumerate
            continue;
          }

          if (timestampUs < filterTimestampUs) {
            continue;
          }

          thisEntry["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
          thisEntry["@odata.id"] = entriesPath + entryID;
          thisEntry["Id"] = entryID;
          thisEntry["EntryType"] = "Event";
          thisEntry["Name"] = dumpTypeToString(dump.type) + " Dump Entry";
          thisEntry["Created"] =
              redfish::time_utils::getDateTimeUintUs(timestampUs);

          if (!originatorId.empty()) {
            thisEntry["Originator"] = originatorId;
            thisEntry["OriginatorType"] = originatorType;
          }

          if (dump.type == DumpType::BMC_DUMP) {
            thisEntry["DiagnosticDataType"] = "Manager";
            thisEntry["AdditionalDataURI"] =
                entriesPath + entryID + "/attachment";
            thisEntry["AdditionalDataSizeBytes"] = size;
          } else if (dump.type == DumpType::BMC_FAULT_LOG ||
                     dump.type == DumpType::SYSTEM_FAULT_LOG) {
            thisEntry["Created"] =
                redfish::time_utils::getDateTimeUintUs(timestampUs);
            thisEntry["DiagnosticDataType"] = "OEM";
            thisEntry["OEMDiagnosticDataType"] = "OpenBMC Fault Log";
            thisEntry["EntryType"] = "Oem";

            std::string systemPathSegment =
                dump.systemName ? *dump.systemName : "system";

            if (entryType == "CPER") {
              if (absl::StrContains(primaryLogId, "/Entries/")) {
                // This is for backward compatibility; we can remove it
                // later.
                thisEntry["AdditionalDataURI"] = crow::utility::urlFromPieces(
                    "redfish", "v1", "Systems", systemPathSegment,
                    "LogServices", primaryLogId);
              } else {
                // Will eventually be changed from AdditionalDataURI to
                // OriginOfCondition Link
                thisEntry["AdditionalDataURI"] =
#ifdef BMCWEB_ENABLE_CPER_CRASHDUMP_USE_FAULTLOG_ID
                    crow::utility::urlFromPieces(
                        "redfish", "v1", "Systems", systemPathSegment,
                        "LogServices", std::string(hostCperLogServiceName),
                        "Entries", entryID);
#else
                    crow::utility::urlFromPieces(
                        "redfish", "v1", "Systems", systemPathSegment,
                        "LogServices", std::string(hostCperLogServiceName),
                        "Entries", primaryLogId);
#endif
              }
              thisEntry["OemRecordFormat"] = "CPER";
            } else if (entryType == "IliadCPER") {
              thisEntry["AdditionalDataURI"] = crow::utility::urlFromPieces(
                  "redfish", "v1", "Systems", systemPathSegment, "LogServices",
                  "IliadCper", "Entries", primaryLogId);
              thisEntry["OemRecordFormat"] = "CPER";
            } else if (entryType == "Crashdump") {
              std::string prefixedEntryID = absl::StrCat(
                  getRedfishPrefixForDbusObjectPath(object.first,
                                                    systemPathSegment),
#ifdef BMCWEB_ENABLE_CPER_CRASHDUMP_USE_FAULTLOG_ID
                  entryID
#else
                  primaryLogId
#endif
              );
              thisEntry["AdditionalDataURI"] = crow::utility::urlFromPieces(
                  "redfish", "v1", "Systems", systemPathSegment, "LogServices",
                  "Crashdump", "Entries", prefixedEntryID);
              thisEntry["OemRecordFormat"] = "Crashdump";
            } else if (!entryType.empty() && entryType != "Event") {
              thisEntry["DiagnosticDataType"] = "OEM";
              thisEntry["AdditionalDataURI"] = entriesPath + entryID;
              thisEntry["OEMDiagnosticDataType"] = entryType;
              thisEntry["OemRecordFormat"] = entryType;

              if (!originatorId.empty()) {
                nlohmann::json::object_t originOfCondition;
                originOfCondition["@odata.id"] = originatorId;
                thisEntry["Links"]["OriginOfCondition"] =
                    std::move(originOfCondition);
              }
            } else {
              // entryType must be of CPER or CrashDump or else accessing
              // thisEntry["AdditionalDataURI"] becomes undefined behavior
              BMCWEB_LOG_ERROR << "entryType of faultLog is invalid";
              messages::internalError(asyncResp->res);
              return;
            }

            // Also export a RelatedLogEntry link to the AdditionalDataURI.
            thisEntry["Links"]["RelatedLogEntries"] = nlohmann::json::array();
            nlohmann::json::object_t relatedLogEntry;
            relatedLogEntry["@odata.id"] = thisEntry["AdditionalDataURI"];
            thisEntry["Links"]["RelatedLogEntries"].emplace_back(
                relatedLogEntry);
          } else if (dump.type == DumpType::SYSTEM_DUMP) {
            thisEntry["DiagnosticDataType"] = "OEM";
            thisEntry["OEMDiagnosticDataType"] = "System";
            thisEntry["AdditionalDataURI"] =
                entriesPath + entryID + "/attachment";
            thisEntry["AdditionalDataSizeBytes"] = size;
          }

          if (shouldEfficientExpandFaultLog(dump.type, delegatedExpandLevel)) {
            std::string dataUri = thisEntry["AdditionalDataURI"];
            std::string collectionUri =
                dataUri.substr(0, dataUri.rfind('/') + 1);
            if (!faultLogEntries.contains(collectionUri)) {
              faultLogEntries.emplace(
                  collectionUri,
                  std::unordered_map<std::string,
                                     nlohmann::json::json_pointer>());
              faultLogOriginalMembers.emplace(collectionUri,
                                              nlohmann::json::array());
            }
            auto jsonPath =
                ""_json_pointer /
                faultLogOriginalMembers[collectionUri].size() / "Links" /
                "RelatedLogEntries" /
                (thisEntry["Links"]["RelatedLogEntries"].size() - 1);
            faultLogEntries[collectionUri].emplace(dataUri, jsonPath);
            faultLogOriginalMembers[collectionUri].push_back(
                std::move(thisEntry));
          } else {
            entriesArray.push_back(std::move(thisEntry));
          }
        }
        asyncResp->res.jsonValue["Members@odata.count"] = entriesArray.size();

        if (shouldEfficientExpandFaultLog(dump.type, delegatedExpandLevel)) {
          // faultLogEntries and faultLogOriginamMemobers will be moved
          // into the completion handler of sub queries in
          // queryFaultCollection. It won't be availabe in this scope after
          // this loop.
          for (auto& [collectionUri, uriJsonPaths] : faultLogEntries) {
            nlohmann::json& originalMembers =
                faultLogOriginalMembers[collectionUri];
            queryFaultCollection(app, req, asyncResp, collectionUri,
                                 uriJsonPaths, originalMembers);
          }
        }
      });
}

inline void getDumpEntryById(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& entryID, const Dump& dump) {
  std::string entriesPath = getDumpEntriesPath(dump);
  if (entriesPath.empty()) {
    messages::internalError(asyncResp->res);
    return;
  }

  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
      "xyz.openbmc_project.Dump.Manager", {"/xyz/openbmc_project/dump"},
      context,
      [asyncResp, entryID, dump, entriesPath](
          const boost::system::error_code& ec,
          const dbus::utility::ManagedObjectType& resp) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DumpEntry resp_handler got error " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        bool foundDumpEntry = false;
        std::optional<std::string> dumpEntryPath =
            getDumpEntryPathFromDump(dump);

        if (!dumpEntryPath) {
          BMCWEB_LOG_ERROR << "Cant convert system "
                           << dump.systemName.value_or("None")
                           << "to dumpEntryPath";
          messages::internalError(asyncResp->res);
          return;
        }

        for (const auto& objectPath : resp) {
          if (objectPath.first.str != *dumpEntryPath + entryID) {
            continue;
          }

          foundDumpEntry = true;
          uint64_t timestampUs = 0;
          uint64_t size = 0;
          std::string dumpStatus;
          std::string originatorId;
          std::string primaryLogId;
          std::string entryType;
          log_entry::OriginatorTypes originatorType =
              log_entry::OriginatorTypes::Internal;

          parseDumpEntryFromDbusObject(
              objectPath, dumpStatus, size, timestampUs, originatorId,
              originatorType, entryType, primaryLogId, asyncResp);

          if (dumpStatus !=
                  "xyz.openbmc_project.Common.Progress.OperationStatus."
                  "Completed" &&
              !dumpStatus.empty()) {
            // Dump status is not Complete
            // return not found until status is changed to Completed
            messages::resourceNotFound(
                asyncResp->res, dumpTypeToString(dump.type) + " dump", entryID);
            return;
          }

          asyncResp->res.jsonValue["@odata.type"] =
              "#LogEntry.v1_11_0.LogEntry";
          asyncResp->res.jsonValue["@odata.id"] = entriesPath + entryID;
          asyncResp->res.jsonValue["Id"] = entryID;
          asyncResp->res.jsonValue["EntryType"] = "Event";
          asyncResp->res.jsonValue["Name"] =
              dumpTypeToString(dump.type) + " Dump Entry";
          asyncResp->res.jsonValue["Created"] =
              redfish::time_utils::getDateTimeUintUs(timestampUs);

          if (!originatorId.empty()) {
            asyncResp->res.jsonValue["Originator"] = originatorId;
            asyncResp->res.jsonValue["OriginatorType"] = originatorType;
          }

          if (dump.type == DumpType::BMC_DUMP) {
            asyncResp->res.jsonValue["DiagnosticDataType"] = "Manager";
            asyncResp->res.jsonValue["AdditionalDataURI"] =
                entriesPath + entryID + "/attachment";
            asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
          } else if (dump.type == DumpType::BMC_FAULT_LOG ||
                     dump.type == DumpType::SYSTEM_FAULT_LOG) {
            asyncResp->res.jsonValue["Created"] =
                redfish::time_utils::getDateTimeUintUs(timestampUs);
            asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
            asyncResp->res.jsonValue["OEMDiagnosticDataType"] =
                "OpenBMC Fault Log";
            asyncResp->res.jsonValue["EntryType"] = "Oem";

            std::string systemPathSegment =
                dump.systemName ? *dump.systemName : "system";

            if (entryType == "CPER") {
              if (absl::StrContains(primaryLogId, "/Entries/")) {
                // This is for backward compatibility; we can remove it
                // later.
                asyncResp->res.jsonValue["AdditionalDataURI"] =
                    crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                                 systemPathSegment,
                                                 "LogServices", primaryLogId);
              } else {
                // Will eventually be changed from AdditionalDataURI to
                // OriginOfCondition Link
                asyncResp->res.jsonValue["AdditionalDataURI"] =
#ifdef BMCWEB_ENABLE_CPER_CRASHDUMP_USE_FAULTLOG_ID
                    crow::utility::urlFromPieces(
                        "redfish", "v1", "Systems", systemPathSegment,
                        "LogServices", std::string(hostCperLogServiceName),
                        "Entries", entryID);
#else
                    crow::utility::urlFromPieces(
                        "redfish", "v1", "Systems", systemPathSegment,
                        "LogServices", std::string(hostCperLogServiceName),
                        "Entries", primaryLogId);
#endif
              }
              asyncResp->res.jsonValue["OemRecordFormat"] = "CPER";
            } else if (entryType == "IliadCPER") {
              asyncResp->res.jsonValue["AdditionalDataURI"] =
                  crow::utility::urlFromPieces(
                      "redfish", "v1", "Systems", systemPathSegment,
                      "LogServices", "IliadCper", "Entries", primaryLogId);
              asyncResp->res.jsonValue["OemRecordFormat"] = "CPER";
            } else if (entryType == "Crashdump") {
              std::string prefixedEntryID = absl::StrCat(
                  getRedfishPrefixForDbusObjectPath(objectPath.first,
                                                    systemPathSegment),
#ifdef BMCWEB_ENABLE_CPER_CRASHDUMP_USE_FAULTLOG_ID
                  entryID
#else
                  primaryLogId
#endif
              );
              asyncResp->res.jsonValue["AdditionalDataURI"] =
                  crow::utility::urlFromPieces(
                      "redfish", "v1", "Systems", systemPathSegment,
                      "LogServices", "Crashdump", "Entries", prefixedEntryID);
              asyncResp->res.jsonValue["OemRecordFormat"] = "Crashdump";
            } else if (!entryType.empty() && entryType != "Event") {
              asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
              asyncResp->res.jsonValue["AdditionalDataURI"] =
                  entriesPath + entryID;
              asyncResp->res.jsonValue["OEMDiagnosticDataType"] = entryType;
              asyncResp->res.jsonValue["OemRecordFormat"] = entryType;

              if (!originatorId.empty()) {
                nlohmann::json::object_t originOfCondition;
                originOfCondition["@odata.id"] = originatorId;
                asyncResp->res.jsonValue["Links"]["OriginOfCondition"] =
                    std::move(originOfCondition);
              }

              if (!primaryLogId.empty()) {
                std::ifstream ifs(primaryLogId,
                                  std::ios::in | std::ios::binary);
                if (ifs.is_open()) {
                  std::string cperData((std::istreambuf_iterator<char>(ifs)),
                                       (std::istreambuf_iterator<char>()));
                  std::string encodedData;
                  encodedData.resize(boost::beast::detail::base64::encoded_size(
                      cperData.size()));
                  encodedData.resize(boost::beast::detail::base64::encode(
                      &encodedData[0], cperData.data(), cperData.size()));
                  asyncResp->res.jsonValue["DiagnosticData"] =
                      std::move(encodedData);
                  ifs.close();
                } else {
                  BMCWEB_LOG_ERROR << "Failed to open file: " << primaryLogId;
                }
              }
            } else {
              // entryType must be of CPER or CrashDump or else accessing
              // thisEntry["AdditionalDataURI"] becomes undefined behavior
              BMCWEB_LOG_ERROR << "entryType of faultLog is invalid";
              messages::internalError(asyncResp->res);
              return;
            }

            // Also export a RelatedLogEntry link to the AdditionalDataURI.
            asyncResp->res.jsonValue["Links"]["RelatedLogEntries"] =
                nlohmann::json::array();
            nlohmann::json::object_t relatedLogEntry;
            relatedLogEntry["@odata.id"] =
                asyncResp->res.jsonValue["AdditionalDataURI"];
            asyncResp->res.jsonValue["Links"]["RelatedLogEntries"].emplace_back(
                relatedLogEntry);
          } else if (dump.type == DumpType::SYSTEM_DUMP) {
            asyncResp->res.jsonValue["DiagnosticDataType"] = "OEM";
            asyncResp->res.jsonValue["OEMDiagnosticDataType"] = "System";
            asyncResp->res.jsonValue["AdditionalDataURI"] =
                entriesPath + entryID + "/attachment";
            asyncResp->res.jsonValue["AdditionalDataSizeBytes"] = size;
          }
        }
        if (!foundDumpEntry) {
          BMCWEB_LOG_ERROR << "Can't find Dump Entry";
          messages::resourceNotFound(
              asyncResp->res, dumpTypeToString(dump.type) + " dump", entryID);
          return;
        }
      });
}

inline void deleteDumpEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                            const std::string& entryID, const Dump& dump) {
  auto respHandler = [asyncResp, entryID](const boost::system::error_code& ec) {
    BMCWEB_LOG_DEBUG << "Dump Entry doDelete callback: Done";
    if (ec) {
      if (ec.value() == EBADR) {
        messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
        return;
      }
      BMCWEB_LOG_ERROR << "Dump (DBus) doDelete respHandler got error " << ec
                       << " entryID=" << entryID;
      messages::internalError(asyncResp->res);
      return;
    }
  };

  std::optional<std::string> dumpEntryPath = getDumpEntryPathFromDump(dump);

  if (!dumpEntryPath) {
    BMCWEB_LOG_ERROR << "Cant convert system "
                     << dump.systemName.value_or("None") << "to dumpEntryPath";
    messages::internalError(asyncResp->res);
    return;
  }

  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_, respHandler, "xyz.openbmc_project.Dump.Manager",
      *dumpEntryPath + entryID, "xyz.openbmc_project.Object.Delete", "Delete");
}

constexpr const char* dumpsFolderBasePath =
    "/var/lib/phosphor-debug-collector/dumps";

inline bool getDumpFiles(crow::Response& resp, const std::string& dumpFilePath,
                         std::vector<std::filesystem::path>& dumpFiles) {
  std::error_code ec;
  std::filesystem::directory_iterator logPath(dumpFilePath, ec);
  if (ec) {
    BMCWEB_LOG_ERROR << ec.message();
    if (ec.value() == ENOENT) {
      // The directory didn't exist
      messages::resourceNotFound(resp, "", "");
    } else {
      messages::internalError(resp);
    }
    return false;
  }

  for (const std::filesystem::directory_entry& it : logPath) {
    std::string filename = it.path().filename();
    dumpFiles.emplace_back(it.path());
  }

  return true;
}

inline void downloadDumpEntry(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& entryID, const Dump& dump) {
  if (dump.type != DumpType::BMC_DUMP) {
    // We don't know for sure what resource was originally queried
    messages::resourceNotFound(asyncResp->res, "", "");
    return;
  }

  std::string dumpFolderPath = dumpsFolderBasePath;
  dumpFolderPath += "/" + entryID;
  std::vector<std::filesystem::path> dumpFiles;
  if (!getDumpFiles(asyncResp->res, dumpFolderPath, dumpFiles)) {
    // getDumpFiles() will have already written the error to the response
    BMCWEB_LOG_ERROR << "failed to get host log file path";
    return;
  }

  if (dumpFiles.size() != 1) {
    BMCWEB_LOG_ERROR << "Expected 1 dump file, found " << dumpFiles.size()
                     << " dump files";
    messages::internalError(asyncResp->res);
    return;
  }

  const std::string& dumpFile = dumpFiles.front().string();
  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
  int fd = open(dumpFile.c_str(), O_RDONLY);
  if (fd < 0) {
    BMCWEB_LOG_ERROR << "Failed to open dump file!";
    messages::internalError(asyncResp->res);
    return;
  }

  int64_t size = lseek(fd, 0, SEEK_END);
  if (size == -1) {
    messages::internalError(asyncResp->res);
    return;
  }

  // Arbitrary max size of 8MB
  constexpr int maxFileSize = 8 * 1024 * 1024;
  if (size > maxFileSize) {
    BMCWEB_LOG_ERROR << "File size " << size
                     << " exceeds maximum allowed size of " << maxFileSize;
    messages::internalError(asyncResp->res);
  }
  std::vector<char> data(static_cast<size_t>(size));
  int64_t rc = lseek(fd, 0, SEEK_SET);
  if (rc == -1) {
    messages::internalError(asyncResp->res);
    return;
  }
  rc = read(fd, data.data(), data.size());
  if ((rc == -1) || (rc != size)) {
    messages::internalError(asyncResp->res);
    return;
  }
  close(fd);

  std::string_view strData(data.data(), data.size());
  std::string output(strData);
  asyncResp->res.addHeader(boost::beast::http::field::content_type,
                           "application/octet-stream");
  asyncResp->res.body() = std::move(output);
}

inline DumpCreationProgress mapDbusStatusToDumpProgress(
    const std::string& status) {
  if (status == "xyz.openbmc_project.Common.Progress.OperationStatus.Failed" ||
      status == "xyz.openbmc_project.Common.Progress.OperationStatus.Aborted") {
    return DumpCreationProgress::DUMP_CREATE_FAILED;
  }
  if (status ==
      "xyz.openbmc_project.Common.Progress.OperationStatus.Completed") {
    return DumpCreationProgress::DUMP_CREATE_SUCCESS;
  }
  return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
}

inline DumpCreationProgress getDumpCompletionStatus(
    const dbus::utility::DBusPropertiesMap& values) {
  for (const auto& [key, val] : values) {
    if (key == "Status") {
      const std::string* value = std::get_if<std::string>(&val);
      if (value == nullptr) {
        BMCWEB_LOG_ERROR << "Status property value is null";
        return DumpCreationProgress::DUMP_CREATE_FAILED;
      }
      return mapDbusStatusToDumpProgress(*value);
    }
  }
  return DumpCreationProgress::DUMP_CREATE_INPROGRESS;
}

inline std::string getDumpEntryPath(const std::string& dumpPath) {
  if (dumpPath == "/xyz/openbmc_project/dump/bmc/entry") {
    return "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/";
  }
  if (dumpPath == "/xyz/openbmc_project/dump/system/entry") {
    return "/redfish/v1/Systems/system/LogServices/Dump/Entries/";
  }
  return "";
}

inline void createDumpTaskCallback(
    task::Payload&& payload,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const sdbusplus::message::object_path& createdObjPath) {
  const std::string dumpPath = createdObjPath.parent_path().str;
  const std::string dumpId = createdObjPath.filename();

  std::string dumpEntryPath = getDumpEntryPath(dumpPath);

  if (dumpEntryPath.empty()) {
    BMCWEB_LOG_ERROR << "Invalid dump type received";
    messages::internalError(asyncResp->res);
    return;
  }

  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, payload, createdObjPath,
       dumpEntryPath{std::move(dumpEntryPath)},
       dumpId](const boost::system::error_code& ec,
               const std::string& introspectXml) {
        if (ec) {
          BMCWEB_LOG_ERROR << "Introspect call failed with error: "
                           << ec.message();
          messages::internalError(asyncResp->res);
          return;
        }

        // Check if the created dump object has implemented Progress
        // interface to track dump completion. If yes, fetch the "Status"
        // property of the interface, modify the task state accordingly.
        // Else, return task completed.
        tinyxml2::XMLDocument doc;

        doc.Parse(introspectXml.data(), introspectXml.size());
        tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node");
        if (pRoot == nullptr) {
          BMCWEB_LOG_ERROR << "XML document failed to parse";
          messages::internalError(asyncResp->res);
          return;
        }
        tinyxml2::XMLElement* interfaceNode =
            pRoot->FirstChildElement("interface");

        bool isProgressIntfPresent = false;
        while (interfaceNode != nullptr) {
          const char* thisInterfaceName = interfaceNode->Attribute("name");
          if (thisInterfaceName != nullptr) {
            if (thisInterfaceName ==
                std::string_view("xyz.openbmc_project.Common.Progress")) {
              interfaceNode = interfaceNode->NextSiblingElement("interface");
              continue;
            }
            isProgressIntfPresent = true;
            break;
          }
          interfaceNode = interfaceNode->NextSiblingElement("interface");
        }

        std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
            [createdObjPath, dumpEntryPath, dumpId, isProgressIntfPresent](
                const boost::system::error_code& err, sdbusplus::message_t& msg,
                const std::shared_ptr<task::TaskData>& taskData) {
              if (err) {
                BMCWEB_LOG_ERROR << createdObjPath.str
                                 << ": Error in creating dump";
                taskData->messages.emplace_back(messages::internalError());
                taskData->state = "Cancelled";
                return task::completed;
              }

              if (isProgressIntfPresent) {
                dbus::utility::DBusPropertiesMap values;
                std::string prop;
                msg.read(prop, values);

                DumpCreationProgress dumpStatus =
                    getDumpCompletionStatus(values);
                if (dumpStatus == DumpCreationProgress::DUMP_CREATE_FAILED) {
                  BMCWEB_LOG_ERROR << createdObjPath.str
                                   << ": Error in creating dump";
                  taskData->state = "Cancelled";
                  return task::completed;
                }

                if (dumpStatus ==
                    DumpCreationProgress::DUMP_CREATE_INPROGRESS) {
                  BMCWEB_LOG_DEBUG << createdObjPath.str
                                   << ": Dump creation task is in progress";
                  return !task::completed;
                }
              }

              nlohmann::json retMessage = messages::success();
              taskData->messages.emplace_back(retMessage);

              std::string headerLoc = "Location: " + dumpEntryPath +
                                      http_helpers::urlEncode(dumpId);
              taskData->payload->httpHeaders.emplace_back(std::move(headerLoc));

              BMCWEB_LOG_DEBUG << createdObjPath.str
                               << ": Dump creation task completed";
              taskData->state = "Completed";
              return task::completed;
            },
            "type='signal',interface='org.freedesktop.DBus.Properties',"
            "member='PropertiesChanged',path='" +
                createdObjPath.str + "'");

        // The task timer is set to max time limit within which the
        // requested dump will be collected.
        task->startTimer(std::chrono::minutes(6));
        task->populateResp(asyncResp->res);
        task->payload.emplace(payload);
      },
      "xyz.openbmc_project.Dump.Manager", createdObjPath,
      "org.freedesktop.DBus.Introspectable", "Introspect");
}

inline void createDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const crow::Request& req, const Dump& dump) {
  std::string dumpPath = getDumpEntriesPath(dump);
  if (dumpPath.empty()) {
    messages::internalError(asyncResp->res);
    return;
  }

  std::optional<std::string> diagnosticDataType;
  std::optional<std::string> oemDiagnosticDataType;

  if (!redfish::json_util::readJsonAction(
          req, asyncResp->res, "DiagnosticDataType", diagnosticDataType,
          "OEMDiagnosticDataType", oemDiagnosticDataType)) {
    return;
  }

  if (dump.type == DumpType::SYSTEM_DUMP) {
    if (!oemDiagnosticDataType || !diagnosticDataType) {
      BMCWEB_LOG_ERROR
          << "CreateDump action parameter "
             "'DiagnosticDataType'/'OEMDiagnosticDataType' value not found!";
      messages::actionParameterMissing(
          asyncResp->res, "CollectDiagnosticData",
          "DiagnosticDataType & OEMDiagnosticDataType");
      return;
    }
    if ((*oemDiagnosticDataType != "System") ||
        (*diagnosticDataType != "OEM")) {
      BMCWEB_LOG_ERROR << "Wrong parameter values passed";
      messages::internalError(asyncResp->res);
      return;
    }
    dumpPath = "/redfish/v1/Systems/system/LogServices/Dump/";
  } else if (dump.type == DumpType::BMC_DUMP) {
    if (!diagnosticDataType) {
      BMCWEB_LOG_ERROR
          << "CreateDump action parameter 'DiagnosticDataType' not found!";
      messages::actionParameterMissing(asyncResp->res, "CollectDiagnosticData",
                                       "DiagnosticDataType");
      return;
    }
    if (*diagnosticDataType != "Manager") {
      BMCWEB_LOG_ERROR
          << "Wrong parameter value passed for 'DiagnosticDataType'";
      messages::internalError(asyncResp->res);
      return;
    }
    dumpPath = "/redfish/v1/Managers/bmc/LogServices/Dump/";
  } else {
    BMCWEB_LOG_ERROR << "CreateDump failed. Unknown dump type";
    messages::internalError(asyncResp->res);
    return;
  }

  std::vector<std::pair<std::string, std::variant<std::string, uint64_t>>>
      createDumpParamVec;

  if (req.session != nullptr) {
    createDumpParamVec.emplace_back(
        "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorId",
        req.session->clientIp);
    createDumpParamVec.emplace_back(
        "xyz.openbmc_project.Dump.Create.CreateParameters.OriginatorType",
        "xyz.openbmc_project.Common.OriginatedBy.OriginatorTypes.Client");
  }

  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, payload(task::Payload(req)), dumpPath](
          const boost::system::error_code& ec, const sdbusplus::message_t& msg,
          const sdbusplus::message::object_path& objPath) mutable {
        if (ec) {
          BMCWEB_LOG_ERROR << "CreateDump resp_handler got error " << ec;
          const sd_bus_error* dbusError = msg.get_error();
          if (dbusError == nullptr) {
            messages::internalError(asyncResp->res);
            return;
          }

          BMCWEB_LOG_ERROR << "CreateDump DBus error: " << dbusError->name
                           << " and error msg: " << dbusError->message;
          if (std::string_view("xyz.openbmc_project.Common.Error.NotAllowed") ==
              dbusError->name) {
            messages::resourceInStandby(asyncResp->res);
            return;
          }
          if (std::string_view(
                  "xyz.openbmc_project.Dump.Create.Error.Disabled") ==
              dbusError->name) {
            messages::serviceDisabled(asyncResp->res, dumpPath);
            return;
          }
          if (std::string_view(
                  "xyz.openbmc_project.Common.Error.Unavailable") ==
              dbusError->name) {
            messages::resourceInUse(asyncResp->res);
            return;
          }
          // Other Dbus errors such as:
          // xyz.openbmc_project.Common.Error.InvalidArgument &
          // org.freedesktop.DBus.Error.InvalidArgs are all related to
          // the dbus call that is made here in the bmcweb
          // implementation and has nothing to do with the client's
          // input in the request. Hence, returning internal error
          // back to the client.
          messages::internalError(asyncResp->res);
          return;
        }
        BMCWEB_LOG_DEBUG << "Dump Created. Path: " << objPath.str;
        createDumpTaskCallback(std::move(payload), asyncResp, objPath);
      },
      "xyz.openbmc_project.Dump.Manager",
      "/xyz/openbmc_project/dump/" +
          std::string(
              boost::algorithm::to_lower_copy(dumpTypeToString(dump.type))),
      "xyz.openbmc_project.Dump.Create", "CreateDump", createDumpParamVec);
}

inline std::optional<std::string> getDumpManagerCollectionPath(
    const Dump& dump) {
  if (!dump.systemName || *dump.systemName == "system") {
    return "/xyz/openbmc_project/dump/" +
           std::string(
               boost::algorithm::to_lower_copy(dumpTypeToString(dump.type)));
  }

  for (const auto& mapping : systemNameToDumpEntryPath) {
    if (mapping.first == *dump.systemName) {
      return std::string(mapping.second);
    }
  }

  return std::nullopt;
}

inline void clearDump(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const Dump& dump) {
  std::optional<std::string> dumpManagerCollectionPath =
      getDumpManagerCollectionPath(dump);

  if (!dumpManagerCollectionPath) {
    BMCWEB_LOG_ERROR << "Cant get dumpManagerCollectionPath from system "
                     << dump.systemName.value_or("none");
    messages::internalError(asyncResp->res);
    return;
  }

  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp](const boost::system::error_code& ec) {
        if (ec) {
          BMCWEB_LOG_ERROR << "clearDump resp_handler got error " << ec;
          messages::internalError(asyncResp->res);
          return;
        }
      },
      "xyz.openbmc_project.Dump.Manager", *dumpManagerCollectionPath,
      "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
}

inline static void parseCrashdumpParameters(
    const dbus::utility::DBusPropertiesMap& params, std::string& filename,
    std::string& timestamp, std::string& logfile) {
  const std::string* filenamePtr = nullptr;
  const std::string* timestampPtr = nullptr;
  const std::string* logfilePtr = nullptr;

  const bool success = sdbusplus::unpackPropertiesNoThrow(
      dbus_utils::UnpackErrorPrinter(), params, "Timestamp", timestampPtr,
      "Filename", filenamePtr, "Log", logfilePtr);

  if (!success) {
    return;
  }

  if (filenamePtr != nullptr) {
    filename = *filenamePtr;
  }

  if (timestampPtr != nullptr) {
    timestamp = *timestampPtr;
  }

  if (logfilePtr != nullptr) {
    logfile = *logfilePtr;
  }
}

inline static std::optional<size_t> parsePostCodeHostIndex(
    std::string_view systemName, bool multiHost) {
  if (!multiHost) {
    if (systemName == "system") {
      return 0;
    }
    return std::nullopt;
  }
  constexpr std::string_view prefix = "system";
  if (!systemName.starts_with(prefix) || systemName.size() <= prefix.size()) {
    return std::nullopt;
  }
  std::string_view numberPart = systemName.substr(prefix.size());
  size_t number = 0;
  if (!absl::SimpleAtoi(numberPart, &number) || number == 0) {
    return std::nullopt;
  }
  return number;
}

inline static std::string getPostCodeServiceName(size_t hostIndex) {
  return absl::StrCat("xyz.openbmc_project.State.Boot.PostCode", hostIndex);
}

inline static std::string getPostCodeObjectPath(size_t hostIndex) {
  return absl::StrCat("/xyz/openbmc_project/State/Boot/PostCode", hostIndex);
}

template <typename Callback>
inline void getPostCodeHostContext(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, Callback&& callback) {
  redfish::system_utils::getSystemInformation(
      asyncResp, systemName,
      [systemName, cb = std::forward<Callback>(callback)](
          const std::shared_ptr<bmcweb::AsyncResp>& aResp,
          const std::string& systemPath) {
        bool multiHost = !systemPath.empty();
        auto hostIndex = parsePostCodeHostIndex(systemName, multiHost);
        if (!hostIndex) {
          messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
          return;
        }
        std::string serviceName = getPostCodeServiceName(*hostIndex);
        std::string objectPath = getPostCodeObjectPath(*hostIndex);
        cb(aResp, systemName, *hostIndex, serviceName, objectPath);
      });
}

inline void handleLogServices(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemPath) {
  // If the systemPath is empty, then the system is single host
  bool multiHost = !systemPath.empty();

  // Default systemName is system and change if system is multi-host
  std::string systemName = "system";

  if (multiHost) {
    systemName = sdbusplus::message::object_path(systemPath).filename();
  }

  // Collections don't include the static data added by SubRoute
  // because it has a duplicate entry for members
  asyncResp->res.jsonValue["@odata.type"] =
      "#LogServiceCollection.LogServiceCollection";
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices";
  asyncResp->res.jsonValue["Name"] = "System Log Services Collection";
  asyncResp->res.jsonValue["Description"] =
      "Collection of LogServices for this Computer System";

  nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
  logServiceArray = nlohmann::json::array();

#ifdef BMCWEB_ENABLE_REDFISH_HOST_LOGGER
  nlohmann::json::object_t hostlogger;
  hostlogger["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/HostLogger";
  logServiceArray.push_back(std::move(hostlogger));
#endif

#ifdef BMCWEB_ENABLE_REDFISH_SYSTEM_FAULT_LOG
  nlohmann::json::object_t faultLog;
  faultLog["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/FaultLog";
  logServiceArray.push_back(std::move(faultLog));
#endif

#ifdef BMCWEB_ENABLE_ILIAD_EVENT_LOG
  nlohmann::json::object_t iliadLog;
  iliadLog["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/IliadCper";
  logServiceArray.push_back(std::move(iliadLog));
#endif

#ifdef HEALTH_POPULATE
  nlohmann::json::object_t healthMonitorLog;
  healthMonitorLog["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/HealthMonitor";
  logServiceArray.push_back(std::move(healthMonitorLog));
#endif /* HEALTH_POPULATE */

  nlohmann::json::object_t crashdump;
  crashdump["@odata.id"] = absl::StrCat("/redfish/v1/Systems/", systemName,
                                        "/LogServices/Crashdump");
  logServiceArray.push_back(std::move(crashdump));

  // Similar to the structure of the ComputerSystem Handlers, we will separate
  // multi-host features and singlehost features.
  if (!multiHost) {
#ifdef BMCWEB_ENABLE_REDFISH_EVENT_LOG
    nlohmann::json::object_t eventLog;
    eventLog["@odata.id"] = "/redfish/v1/Systems/system/LogServices/EventLog";
    logServiceArray.push_back(std::move(eventLog));
#endif

#ifdef BMCWEB_ENABLE_RASMANAGER_EVENT_LOG
    nlohmann::json::object_t rasManagerLog;
    rasManagerLog["@odata.id"] =
        "/redfish/v1/Systems/system/LogServices/HostCper";
    logServiceArray.push_back(std::move(rasManagerLog));
#endif

#ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG
    nlohmann::json::object_t dumpLog;
    dumpLog["@odata.id"] = "/redfish/v1/Systems/system/LogServices/Dump";
    logServiceArray.push_back(std::move(dumpLog));
#endif

#ifdef BMCWEB_ENABLE_PPR
    nlohmann::json::object_t ppr;
    ppr["@odata.id"] =
        "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair";
    logServiceArray.push_back(std::move(ppr));
#endif

#ifdef BMCWEB_ENABLE_REDFISH_EXTERNAL_STORER
    // This is the ExternalStorer integration point
    auto externalStorerHook = external_storer::rememberLogServices();
    if (externalStorerHook != nullptr) {
      for (const auto& instance : externalStorerHook->listInstances()) {
        nlohmann::json::object_t externalStorerInstance;
        externalStorerInstance["@odata.id"] =
            "/redfish/v1/Systems/system/LogServices/" + instance;
        logServiceArray.push_back(std::move(externalStorerInstance));
      }
    }
#endif

#ifdef BMCWEB_ENABLE_REDFISH_BOOT_TIME_LOG
    nlohmann::json::object_t bootTime;
    bootTime["@odata.id"] =
        "/redfish/v1/Systems/" + systemName + "/LogServices/BootTime";
    logServiceArray.push_back(std::move(bootTime));
#endif
  }

  constexpr std::array<std::string_view, 1> interfaces = {
      "xyz.openbmc_project.State.Boot.PostCode"};
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      "/", 0, interfaces, requestContext,
      [asyncResp, systemName, multiHost](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreePathsResponse& subtreePath) {
        if (ec) {
          BMCWEB_LOG_ERROR << ec;
          return;
        }

        auto hostIndex = parsePostCodeHostIndex(systemName, multiHost);
        if (!hostIndex) {
          return;
        }

        std::string targetPostCodeObject = getPostCodeObjectPath(*hostIndex);

        for (const auto& pathStr : subtreePath) {
          if (pathStr == targetPostCodeObject) {
            nlohmann::json& logServiceArrayLocal =
                asyncResp->res.jsonValue["Members"];
            nlohmann::json::object_t member;
            member["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Systems", systemName, "LogServices",
                "PostCodes");

            logServiceArrayLocal.push_back(std::move(member));

            asyncResp->res.jsonValue["Members@odata.count"] =
                logServiceArrayLocal.size();
            return;
          }
        }
      });
  asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();
}

void handleSystemLogServicesCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  redfish::system_utils::getSystemInformation(asyncResp, systemName,
                                              handleLogServices);
}

void requestRoutesSystemLogServiceCollection(App& app) {
  /**
   * Functions triggers appropriate requests on DBus
   */
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
      .privileges(redfish::privileges::getLogServiceCollection)
      .methods(boost::beast::http::verb::get)(
          [&app](const crow::Request& req,
                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                 const std::string& systemName) {
            handleSystemLogServicesCollectionGet(app, req, asyncResp,
                                                 systemName);
          });
}

constexpr const char* hostLoggerFolderPath = "/var/log/console";

#if ENABLE_SYSTEM_LOG_REVERSE
// Hardcoding mapping of system1 -> S2 and system2 -> S1
constexpr std::array<std::pair<std::string_view, std::string_view>, 2>
    systemNameToLogPrefix{{{"system1", "S2"}, {"system2", "S1"}}};
#else
constexpr std::array<std::pair<std::string_view, std::string_view>, 2>
    systemNameToLogPrefix{{{"system1", "S1"}, {"system2", "S2"}}};
#endif

inline bool getHostLoggerFiles(
    const std::string& hostLoggerFilePath,
    std::vector<std::filesystem::path>& hostLoggerFiles,
    const std::string& systemName, bool multiHost) {
  std::error_code ec;
  std::filesystem::directory_iterator logPath(hostLoggerFilePath, ec);
  if (ec) {
    BMCWEB_LOG_ERROR << ec.message();
    return false;
  }

  // Setting default filePrefix is log
  std::string filePrefix = defaultLogPrefix;

  // For multi-host systems, the prefix will change based on which host
  if (multiHost) {
    // Right now we dont have a guarateed and extendable way to determine
    // which file is for which host. Will hardcode for now and fix later
    bool systemFound = false;
    for (const auto& mapping : systemNameToLogPrefix) {
      if (mapping.first == systemName) {
        filePrefix += mapping.second;
        systemFound = true;
        break;
      }
    }

    if (!systemFound) {
      BMCWEB_LOG_ERROR << "Could not find HostLogPrefix for system "
                       << systemName;
      return false;
    }
  }

  for (const std::filesystem::directory_entry& it : logPath) {
    std::string filename = it.path().filename();
    // Prefix of each log files is "log". Find the file and save the
    // path
    if (filename.starts_with(filePrefix)) {
      hostLoggerFiles.emplace_back(it.path());
    }
  }
  // As the log files rotate, they are appended with a ".#" that is higher for
  // the older logs. Since we start from oldest logs, sort the name in
  // descending order.
  std::sort(hostLoggerFiles.rbegin(), hostLoggerFiles.rend(),
            AlphanumLess<std::string>());

  return true;
}

inline bool getHostLoggerEntries(
    const std::vector<std::filesystem::path>& hostLoggerFiles, uint64_t skip,
    uint64_t top, std::vector<std::string>& logEntries, size_t& logCount) {
  GzFileReader logFile;

  // Go though all log files and expose host logs.
  for (const std::filesystem::path& it : hostLoggerFiles) {
    if (!logFile.gzGetLines(it.string(), skip, top, logEntries, logCount)) {
      BMCWEB_LOG_ERROR << "fail to expose host logs";
      return false;
    }
  }
  // Get lastMessage from constructor by getter
  std::string lastMessage = logFile.getLastMessage();
  if (!lastMessage.empty()) {
    logCount++;
    if (logCount > skip && logCount <= (skip + top)) {
      logEntries.push_back(lastMessage);
    }
  }
  return true;
}

inline void fillHostLoggerEntryJson(const std::string& logEntryID,
                                    const std::string& msg,
                                    nlohmann::json::object_t& logEntryJson,
                                    const std::string& systemName) {
  // Fill in the log entry with the gathered data.
  logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
  logEntryJson["@odata.id"] = crow::utility::urlFromPieces(
      "redfish", "v1", "Systems", systemName, "LogServices", "HostLogger",
      "Entries", logEntryID);
  logEntryJson["Name"] = "Host Logger Entry";
  logEntryJson["Id"] = logEntryID;
  logEntryJson["Message"] = msg;
  logEntryJson["EntryType"] = "Oem";
  logEntryJson["Severity"] = "OK";
  logEntryJson["OemRecordFormat"] = "Host Logger Entry";
}

inline void handleSystemHostLogger(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemPath) {
  // Default systemName is system and change if system is multi-host
  std::string systemName = "system";
  if (!systemPath.empty()) {
    systemName = sdbusplus::message::object_path(systemPath).filename();
  }

  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/HostLogger";
  asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_1_0.LogService";
  asyncResp->res.jsonValue["Name"] = "Host Logger Service";
  asyncResp->res.jsonValue["Description"] = "Host Logger Service";
  asyncResp->res.jsonValue["Id"] = "HostLogger";
  asyncResp->res.jsonValue["Entries"]["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/HostLogger/Entries";
}

void requestRoutesSystemHostLogger(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(
          [&app](const crow::Request& req,
                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                 const std::string& systemName) {
            if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
              return;
            }
            redfish::system_utils::getSystemInformation(asyncResp, systemName,
                                                        handleSystemHostLogger);
          });
}

inline void handleSystemHostLoggerCollection(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemPath, const query_param::Query& delegatedQuery) {
  // If the systemPath is empty, then the system is single host
  bool multiHost = !systemPath.empty();

  // Default systemName is system and change if system is multi-host
  std::string systemName = "system";
  if (multiHost) {
    systemName = sdbusplus::message::object_path(systemPath).filename();
  }

  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/HostLogger/Entries";
  asyncResp->res.jsonValue["@odata.type"] =
      "#LogEntryCollection.LogEntryCollection";
  asyncResp->res.jsonValue["Name"] = "HostLogger Entries";
  asyncResp->res.jsonValue["Description"] = "Collection of HostLogger Entries";
  nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
  logEntryArray = nlohmann::json::array();
  asyncResp->res.jsonValue["Members@odata.count"] = 0;

  std::vector<std::filesystem::path> hostLoggerFiles;
  if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles, systemName,
                          multiHost)) {
    BMCWEB_LOG_ERROR << "fail to get host log file path";
    return;
  }
  // If we weren't provided top and skip limits, use the defaults.
  size_t skip = delegatedQuery.skip.value_or(0);
  size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
  size_t logCount = 0;
  // This vector only store the entries we want to expose that
  // control by skip and top.
  std::vector<std::string> logEntries;
  if (!getHostLoggerEntries(hostLoggerFiles, skip, top, logEntries, logCount)) {
    messages::internalError(asyncResp->res);
    return;
  }
  // If vector is empty, that means skip value larger than total
  // log count
  if (logEntries.empty()) {
    asyncResp->res.jsonValue["Members@odata.count"] = logCount;
    return;
  }
  if (!logEntries.empty()) {
    for (size_t i = 0; i < logEntries.size(); i++) {
      nlohmann::json::object_t hostLogEntry;
      fillHostLoggerEntryJson(std::to_string(skip + i), logEntries[i],
                              hostLogEntry, systemName);
      logEntryArray.push_back(std::move(hostLogEntry));
    }

    asyncResp->res.jsonValue["Members@odata.count"] = logCount;
    if (skip + top < logCount) {
      asyncResp->res.jsonValue["Members@odata.nextLink"] =
          "/redfish/v1/Systems/" + systemName +
          "/LogServices/HostLogger/Entries?$skip=" + std::to_string(skip + top);
    }
  }
}

inline void handleGetSystemHostLoggerCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  query_param::QueryCapabilities capabilities = {
      .canDelegateTop = true,
      .canDelegateSkip = true,
  };
  query_param::Query delegatedQuery;
  if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
                                                delegatedQuery, capabilities)) {
    return;
  }
  redfish::system_utils::getSystemInformation(
      asyncResp, systemName,
      [delegatedQuery](const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                       const std::string& systemPath) {
        handleSystemHostLoggerCollection(aResp, systemPath, delegatedQuery);
      });
}

void requestRoutesSystemHostLoggerCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetSystemHostLoggerCollection, std::ref(app)));
}

inline void handleSystemHostLoggerLogEntry(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemPath, const std::string& param) {
  // If the systemPath is empty, then the system is single host
  bool multiHost = !systemPath.empty();

  // Default systemName is system and change if system is multi-host
  std::string systemName = "system";
  if (multiHost) {
    systemName = sdbusplus::message::object_path(systemPath).filename();
  }

  const std::string& targetID = param;

  uint64_t idInt = 0;

  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
  const char* end = targetID.data() + targetID.size();

  auto [ptr, ec] = std::from_chars(targetID.data(), end, idInt);
  if (ec == std::errc::invalid_argument ||
      ec == std::errc::result_out_of_range) {
    messages::resourceNotFound(asyncResp->res, "LogEntry", param);
    return;
  }

  std::vector<std::filesystem::path> hostLoggerFiles;
  if (!getHostLoggerFiles(hostLoggerFolderPath, hostLoggerFiles, systemName,
                          multiHost)) {
    BMCWEB_LOG_ERROR << "fail to get host log file path";
    return;
  }

  size_t logCount = 0;
  size_t top = 1;
  std::vector<std::string> logEntries;
  // We can get specific entry by skip and top. For example, if we
  // want to get nth entry, we can set skip = n-1 and top = 1 to
  // get that entry
  if (!getHostLoggerEntries(hostLoggerFiles, idInt, top, logEntries,
                            logCount)) {
    messages::internalError(asyncResp->res);
    return;
  }

  if (!logEntries.empty()) {
    nlohmann::json::object_t hostLogEntry;
    fillHostLoggerEntryJson(targetID, logEntries[0], hostLogEntry, systemName);
    asyncResp->res.jsonValue.update(hostLogEntry);
    return;
  }

  // Requested ID was not found
  messages::resourceNotFound(asyncResp->res, "LogEntry", param);
}

inline void handleGetSystemHostLoggerLogEntry(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& param) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  redfish::system_utils::getSystemInformation(
      asyncResp, systemName,
      [param](const std::shared_ptr<bmcweb::AsyncResp>& aResp,
              const std::string& systemPath) {
        handleSystemHostLoggerLogEntry(aResp, systemPath, param);
      });
}

void requestRoutesSystemHostLoggerLogEntry(App& app) {
  BMCWEB_ROUTE(
      app, "/redfish/v1/Systems/<str>/LogServices/HostLogger/Entries/<str>/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetSystemHostLoggerLogEntry, std::ref(app)));
}

#ifdef HEALTH_POPULATE
void handleHealthMonitorLogServiceGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  // Helper lambda to build the successful response, avoiding code
  // duplication.
  auto buildResponse = [asyncResp, systemName]() {
    asyncResp->res.jsonValue["@odata.id"] =
        "/redfish/v1/Systems/" + systemName + "/LogServices/HealthMonitor";
    asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_1_0.LogService";
    asyncResp->res.jsonValue["Name"] = "Health Monitor Log Service";
    asyncResp->res.jsonValue["Description"] = "Health Monitor Log Service";
    asyncResp->res.jsonValue["Id"] = "HealthMonitor";
    asyncResp->res.jsonValue["Entries"]["@odata.id"] =
        "/redfish/v1/Systems/" + systemName +
        "/LogServices/HealthMonitor/Entries";
  };

  // Query D-Bus to verify the requested system exists.
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      "/xyz/openbmc_project/inventory", 0, systemInventoryInterfaces,
      requestContext,
      [asyncResp, systemName, buildResponse = std::move(buildResponse)](
          const boost::system::error_code& ec,
          const std::vector<std::string>& systemPaths) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        system_utils::findSystemPathAndTriggerCallback(
            asyncResp, systemName, systemPaths,
            [buildResponse = std::move(buildResponse)](
                const std::shared_ptr<bmcweb::AsyncResp>& /*resp*/,
                const std::string& /*objectPath*/) { buildResponse(); });
      });
}

void requestRoutesHealthMonitorLogService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/HealthMonitor/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleHealthMonitorLogServiceGet, std::ref(app)));
}

void handleHealthMonitorLogEntryCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  // Helper lambda to build the response once the system is validated.
  auto processEntries = [asyncResp, systemName]() {
    asyncResp->res.jsonValue["@odata.type"] =
        "#LogEntryCollection.LogEntryCollection";
    asyncResp->res.jsonValue["@odata.id"] =
        "/redfish/v1/Systems/" + systemName +
        "/LogServices/HealthMonitor/Entries";
    asyncResp->res.jsonValue["Name"] = "Health Monitor Log Entries";
    asyncResp->res.jsonValue["Description"] =
        "Collection of Health Monitor Log Entries";

    nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
    asyncResp->res.jsonValue["Members@odata.count"] =
        HealthStatusCache::getInstance().fillLogEntries(logEntryArray,
                                                        systemName);
  };

  // Query D-Bus to verify the requested system exists.
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      "/xyz/openbmc_project/inventory", 0, systemInterfaces, requestContext,
      [asyncResp, systemName, processEntries = std::move(processEntries)](
          const boost::system::error_code& ec,
          const std::vector<std::string>& systemPaths) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        system_utils::findSystemPathAndTriggerCallback(
            asyncResp, systemName, systemPaths,
            [processEntries = std::move(processEntries)](
                const std::shared_ptr<bmcweb::AsyncResp>& /*resp*/,
                const std::string& /*objectPath*/) { processEntries(); });
      });
}

void requestRoutesHealthMonitorLogEntryCollection(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/HealthMonitor/Entries/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleHealthMonitorLogEntryCollectionGet, std::ref(app)));
}

void handleHealthMonitorLogEntryGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& entryId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  // Helper lambda to retrieve the specific entry once the system is
  // validated.
  auto processEntry = [asyncResp, systemName, entryId]() {
    const std::string& targetID = entryId;
    size_t idx = std::stoul(targetID);
    nlohmann::json::object_t logEntry;
    HealthStatusCache::getInstance().fillLogEntry(logEntry, idx, systemName);

    if (logEntry.empty()) {
      messages::resourceNotFound(asyncResp->res, "LogEntry", targetID);
      return;
    }
    asyncResp->res.jsonValue.update(logEntry);
  };

  // Query D-Bus to verify the requested system exists.
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      "/xyz/openbmc_project/inventory", 0, systemInterfaces, requestContext,
      [asyncResp, systemName, processEntry = std::move(processEntry)](
          const boost::system::error_code& ec,
          const std::vector<std::string>& systemPaths) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        system_utils::findSystemPathAndTriggerCallback(
            asyncResp, systemName, systemPaths,
            [processEntry = std::move(processEntry)](
                const std::shared_ptr<bmcweb::AsyncResp>& /*resp*/,
                const std::string& /*objectPath*/) { processEntry(); });
      });
}

void requestRoutesHealthMonitorLogEntry(App& app) {
  BMCWEB_ROUTE(
      app, "/redfish/v1/Systems/<str>/LogServices/HealthMonitor/Entries/<str>/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleHealthMonitorLogEntryGet, std::ref(app)));
}
#endif /* HEALTH_POPULATE */

inline void handleBMCLogServicesCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  // Collections don't include the static data added by SubRoute
  // because it has a duplicate entry for members
  asyncResp->res.jsonValue["@odata.type"] =
      "#LogServiceCollection.LogServiceCollection";
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Managers/bmc/LogServices";
  asyncResp->res.jsonValue["Name"] = "Open BMC Log Services Collection";
  asyncResp->res.jsonValue["Description"] =
      "Collection of LogServices for this Manager";
  nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
  logServiceArray = nlohmann::json::array();

#ifdef BMCWEB_ENABLE_REDFISH_BMC_JOURNAL
  nlohmann::json::object_t journal;
  journal["@odata.id"] = "/redfish/v1/Managers/bmc/LogServices/Journal";
  logServiceArray.push_back(std::move(journal));
#endif

#ifdef BMCWEB_ENABLE_REDFISH_BOOT_TIME_LOG
  nlohmann::json::object_t bootTime;
  bootTime["@odata.id"] = "/redfish/v1/Managers/bmc/LogServices/BootTime";
  logServiceArray.push_back(std::move(bootTime));
#endif

  asyncResp->res.jsonValue["Members@odata.count"] = logServiceArray.size();

#ifdef BMCWEB_ENABLE_REDFISH_DUMP_LOG
  constexpr std::array<std::string_view, 1> interfaces = {
      "xyz.openbmc_project.Collection.DeleteAll"};
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      "/xyz/openbmc_project/dump", 0, interfaces, requestContext,
      [asyncResp](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
        if (ec) {
          BMCWEB_LOG_ERROR
              << "handleBMCLogServicesCollectionGet respHandler got error "
              << ec;
          // Assume that getting an error simply means there are no dump
          // LogServices. Return without adding any error response.
          return;
        }

        nlohmann::json& logServiceArrayLocal =
            asyncResp->res.jsonValue["Members"];

        for (const std::string& path : subTreePaths) {
          if (path == "/xyz/openbmc_project/dump/bmc") {
            nlohmann::json::object_t member;
            member["@odata.id"] = "/redfish/v1/Managers/bmc/LogServices/Dump";
            logServiceArrayLocal.push_back(std::move(member));
          } else if (path == "/xyz/openbmc_project/dump/faultlog") {
            nlohmann::json::object_t member;
            member["@odata.id"] =
                "/redfish/v1/Managers/bmc/LogServices/FaultLog";
            logServiceArrayLocal.push_back(std::move(member));
          }
        }

        asyncResp->res.jsonValue["Members@odata.count"] =
            logServiceArrayLocal.size();
      });
#endif
}

void requestRoutesBMCLogServiceCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/")
      .privileges(redfish::privileges::getLogServiceCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleBMCLogServicesCollectionGet, std::ref(app)));
}

inline void handleGetBMCJournalLogService(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_1_0.LogService";
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Managers/bmc/LogServices/Journal";
  asyncResp->res.jsonValue["Name"] = "Open BMC Journal Log Service";
  asyncResp->res.jsonValue["Description"] = "BMC Journal Log Service";
  asyncResp->res.jsonValue["Id"] = "Journal";
  asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";

  std::pair<std::string, std::string> redfishDateTimeOffset =
      redfish::time_utils::getDateTimeOffsetNow();
  asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
  asyncResp->res.jsonValue["DateTimeLocalOffset"] =
      redfishDateTimeOffset.second;

  asyncResp->res.jsonValue["Entries"]["@odata.id"] =
      "/redfish/v1/Managers/bmc/LogServices/Journal/Entries";
}

void requestRoutesBMCJournalLogService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Journal/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetBMCJournalLogService, std::ref(app)));
}

static int fillBMCJournalLogEntryJson(
    const std::string& bmcJournalLogEntryID, sd_journal* journal,
    nlohmann::json::object_t& bmcJournalLogEntryJson) {
  // Get the Log Entry contents
  int ret = 0;

  std::string message;
  std::string_view syslogID;
  ret = getJournalMetadata(journal, "SYSLOG_IDENTIFIER", syslogID);
  if (ret < 0) {
    BMCWEB_LOG_ERROR << "Failed to read SYSLOG_IDENTIFIER field: "
                     << strerror(-ret);
  }
  if (!syslogID.empty()) {
    message += std::string(syslogID) + ": ";
  }

  std::string_view msg;
  ret = getJournalMetadata(journal, "MESSAGE", msg);
  if (ret < 0) {
    BMCWEB_LOG_ERROR << "Failed to read MESSAGE field: " << strerror(-ret);
    return 1;
  }
  message += std::string(msg);

  // Get the severity from the PRIORITY field
  int64_t severity = 8;  // Default to an invalid priority
  ret = getJournalMetadataToInt64(journal, "PRIORITY", severity);
  if (ret < 0) {
    BMCWEB_LOG_ERROR << "Failed to read PRIORITY field: " << strerror(-ret);
  }

  // Get the Created time from the timestamp
  std::string entryTimeStr;
  if (!getEntryTimestamp(journal, entryTimeStr)) {
    return 1;
  }

  // Fill in the log entry with the gathered data
  bmcJournalLogEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
  bmcJournalLogEntryJson["@odata.id"] = crow::utility::urlFromPieces(
      "redfish", "v1", "Managers", "bmc", "LogServices", "Journal", "Entries",
      bmcJournalLogEntryID);
  bmcJournalLogEntryJson["Name"] = "BMC Journal Entry";
  bmcJournalLogEntryJson["Id"] = bmcJournalLogEntryID;
  bmcJournalLogEntryJson["Message"] = std::move(message);
  bmcJournalLogEntryJson["EntryType"] = "Oem";
  bmcJournalLogEntryJson["Severity"] = severity <= 2   ? "Critical"
                                       : severity <= 4 ? "Warning"
                                                       : "OK";
  bmcJournalLogEntryJson["OemRecordFormat"] = "BMC Journal Entry";
  bmcJournalLogEntryJson["Created"] = std::move(entryTimeStr);
  return 0;
}

inline void handleGetBMCJournalLogEntryCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  query_param::QueryCapabilities capabilities = {
      .canDelegateTop = true,
      .canDelegateSkip = true,
      .canDelegateFilter = true,
  };
  query_param::Query delegatedQuery;
  if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
                                                delegatedQuery, capabilities)) {
    return;
  }

  size_t skip = delegatedQuery.skip.value_or(0);
  size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);

  // Collections don't include the static data added by SubRoute
  // because it has a duplicate entry for members
  asyncResp->res.jsonValue["@odata.type"] =
      "#LogEntryCollection.LogEntryCollection";
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Managers/bmc/LogServices/Journal/Entries";
  asyncResp->res.jsonValue["Name"] = "Open BMC Journal Entries";
  asyncResp->res.jsonValue["Description"] = "Collection of BMC Journal Entries";
  nlohmann::json& logEntryArray = asyncResp->res.jsonValue["Members"];
  logEntryArray = nlohmann::json::array();

  // Go through the journal and use the timestamp to create a
  // unique ID for each entry
  sd_journal* journalTmp = nullptr;
  int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
  if (ret < 0) {
    BMCWEB_LOG_ERROR << "failed to open journal: " << strerror(-ret);
    messages::internalError(asyncResp->res);
    return;
  }
  std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal(
      journalTmp, sd_journal_close);
  journalTmp = nullptr;

  if (!delegatedQuery.filter.empty()) {
    std::string_view filter = delegatedQuery.filter;
    // We expect the filter to be in the form of "Service eq 'value'" or
    // "Slice eq 'value'".
    // We only support a single expression for now.
    // We need to parse this string to get the key and value.
    // The simple parser assumes the format "Key eq 'Value'"

    // Split by space
    std::vector<std::string> chunks;
    bmcweb::split(chunks, filter, ' ');

    if (chunks.size() != 3 || chunks[1] != "eq") {
      messages::queryParameterValueFormatError(asyncResp->res,
                                               std::string(filter), "$filter");
      return;
    }

    absl::string_view key = chunks[0];
    absl::string_view value = chunks[2];

    // Remove quotes from value
    if (!absl::ConsumePrefix(&value, "'") ||
        !absl::ConsumeSuffix(&value, "'")) {
      messages::queryParameterValueFormatError(asyncResp->res,
                                               std::string(filter), "$filter");
      return;
    }

    std::string match;
    if (key == "Service") {
      match = "_SYSTEMD_UNIT=" + std::string(value);
    } else if (key == "Slice") {
      match = "_SYSTEMD_SLICE=" + std::string(value);
    } else {
      messages::queryParameterValueFormatError(asyncResp->res,
                                               std::string(filter), "$filter");
      return;
    }
    sd_journal_add_match(journal.get(), match.c_str(), match.size());
  }

  uint64_t entryCount = 0;
  // Reset the unique ID on the first entry
  bool firstEntry = true;
  SD_JOURNAL_FOREACH(journal.get()) {
    entryCount++;
    // Handle paging using skip (number of entries to skip from
    // the start) and top (number of entries to display)
    if (entryCount <= skip || entryCount > skip + top) {
      continue;
    }

    std::string idStr;
    if (!getUniqueEntryID(journal.get(), idStr, firstEntry)) {
      continue;
    }
    firstEntry = false;

    nlohmann::json::object_t bmcJournalLogEntry;
    if (fillBMCJournalLogEntryJson(idStr, journal.get(), bmcJournalLogEntry) !=
        0) {
      messages::internalError(asyncResp->res);
      return;
    }
    logEntryArray.push_back(std::move(bmcJournalLogEntry));
  }
  asyncResp->res.jsonValue["Members@odata.count"] = entryCount;
  if (skip + top < entryCount) {
    asyncResp->res.jsonValue["Members@odata.nextLink"] =
        "/redfish/v1/Managers/bmc/LogServices/Journal/Entries?$skip=" +
        std::to_string(skip + top);
  }
}

void requestRoutesBMCJournalLogEntryCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/")
      .privileges(redfish::privileges::getLogEntryCollection)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleGetBMCJournalLogEntryCollection, std::ref(app)));
}

inline void handleGetBMCJournalLogEntry(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& entryID) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  // Convert the unique ID back to a timestamp to find the entry
  uint64_t ts = 0;
  uint64_t index = 0;
  if (!getTimestampFromID(asyncResp, entryID, ts, index)) {
    return;
  }

  sd_journal* journalTmp = nullptr;
  int ret = sd_journal_open(&journalTmp, SD_JOURNAL_LOCAL_ONLY);
  if (ret < 0) {
    BMCWEB_LOG_ERROR << "failed to open journal: " << strerror(-ret);
    messages::internalError(asyncResp->res);
    return;
  }
  std::unique_ptr<sd_journal, decltype(&sd_journal_close)> journal(
      journalTmp, sd_journal_close);
  journalTmp = nullptr;
  // Go to the timestamp in the log and move to the entry at the
  // index tracking the unique ID
  std::string idStr;
  bool firstEntry = true;
  ret = sd_journal_seek_realtime_usec(journal.get(), ts);
  if (ret < 0) {
    BMCWEB_LOG_ERROR << "failed to seek to an entry in journal"
                     << strerror(-ret);
    messages::internalError(asyncResp->res);
    return;
  }
  for (uint64_t i = 0; i <= index; i++) {
    sd_journal_next(journal.get());
    if (!getUniqueEntryID(journal.get(), idStr, firstEntry)) {
      messages::internalError(asyncResp->res);
      return;
    }
    firstEntry = false;
  }
  // Confirm that the entry ID matches what was requested
  if (idStr != entryID) {
    messages::resourceNotFound(asyncResp->res, "LogEntry", entryID);
    return;
  }

  nlohmann::json::object_t bmcJournalLogEntry;
  if (fillBMCJournalLogEntryJson(entryID, journal.get(), bmcJournalLogEntry) !=
      0) {
    messages::internalError(asyncResp->res);
    return;
  }
  asyncResp->res.jsonValue.update(bmcJournalLogEntry);
}

void requestRoutesBMCJournalLogEntry(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/<str>/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetBMCJournalLogEntry, std::ref(app)));
}

namespace internal {
void getDumpServiceInfo(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const Dump& dump) {
  std::string dumpPath;
  std::string overWritePolicy;
  bool collectDiagnosticDataSupported = false;

  switch (dump.type) {
    case DumpType::BMC_DUMP:
      dumpPath = "/redfish/v1/Managers/bmc/LogServices/Dump";
      overWritePolicy = "WrapsWhenFull";
      collectDiagnosticDataSupported = true;
      break;
    case DumpType::BMC_FAULT_LOG:
      dumpPath = "/redfish/v1/Managers/bmc/LogServices/FaultLog";
      overWritePolicy = "Unknown";
      collectDiagnosticDataSupported = false;
      break;
    case DumpType::SYSTEM_DUMP:
      dumpPath = "/redfish/v1/Systems/system/LogServices/Dump";
      overWritePolicy = "WrapsWhenFull";
      collectDiagnosticDataSupported = true;
      break;
    case DumpType::SYSTEM_FAULT_LOG:
      if (dump.systemName) {
        dumpPath =
            "/redfish/v1/Systems/" + *dump.systemName + "/LogServices/FaultLog";
        overWritePolicy = "Unknown";
        collectDiagnosticDataSupported = false;
      }
      break;
  }

  asyncResp->res.jsonValue["@odata.id"] = dumpPath;
  asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
  asyncResp->res.jsonValue["Name"] =
      dumpTypeToString(dump.type) + " Dump LogService";
  asyncResp->res.jsonValue["Description"] =
      dumpTypeToString(dump.type) + " Dump LogService";
  asyncResp->res.jsonValue["Id"] = std::filesystem::path(dumpPath).filename();
  asyncResp->res.jsonValue["OverWritePolicy"] = std::move(overWritePolicy);

  std::pair<std::string, std::string> redfishDateTimeOffset =
      redfish::time_utils::getDateTimeOffsetNow();
  asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
  asyncResp->res.jsonValue["DateTimeLocalOffset"] =
      redfishDateTimeOffset.second;

  asyncResp->res.jsonValue["Entries"]["@odata.id"] = dumpPath + "/Entries";

  if (collectDiagnosticDataSupported) {
    asyncResp->res
        .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]["target"] =
        dumpPath + "/Actions/LogService.CollectDiagnosticData";
  }

  constexpr std::array<std::string_view, 1> interfaces = {deleteAllInterface};
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      "/xyz/openbmc_project/dump", 0, interfaces, requestContext,
      [asyncResp, dump, dumpPath](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreePathsResponse& subTreePaths) {
        if (ec) {
          BMCWEB_LOG_ERROR << "getDumpServiceInfo respHandler got error " << ec;
          // Assume that getting an error simply means there are no dump
          // LogServices. Return without adding any error response.
          return;
        }

        std::optional<std::string> dumpManagerCollectionPath =
            getDumpManagerCollectionPath(dump);

        if (!dumpManagerCollectionPath) {
          BMCWEB_LOG_ERROR << "Cant get dumpManagerCollectionPath from system "
                           << dump.systemName.value_or("none");
          messages::internalError(asyncResp->res);
          return;
        }

        for (const std::string& path : subTreePaths) {
          if (path == *dumpManagerCollectionPath) {
            asyncResp->res
                .jsonValue["Actions"]["#LogService.ClearLog"]["target"] =
                dumpPath + "/Actions/LogService.ClearLog";
            break;
          }
        }
      });
}
}  // namespace internal

inline void handleLogServicesDumpServiceGet(
    crow::App& app, DumpType dumpType, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  internal::getDumpServiceInfo(asyncResp, Dump{.type = dumpType});
}

inline void handleLogServicesDumpServiceComputerSystemGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& id) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (id != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", id);
    return;
  }
  internal::getDumpServiceInfo(asyncResp, Dump{.type = DumpType::SYSTEM_DUMP});
}

inline void handleLogServicesDumpEntriesCollectionGet(
    crow::App& app, DumpType dumpType, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  query_param::QueryCapabilities capabilities = {
      .canDelegateExpandLevel = 2,
      .canDelegateFilter = true,
  };
  query_param::Query delegatedQuery;
  if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
                                                delegatedQuery, capabilities)) {
    return;
  }
  getDumpEntryCollection(app, req, asyncResp, Dump{.type = dumpType},
                         delegatedQuery);
}

inline void handleLogServicesDumpEntriesCollectionComputerSystemGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId) {
  query_param::QueryCapabilities capabilities = {
      .canDelegateExpandLevel = 2,
      .canDelegateFilter = true,
  };
  query_param::Query delegatedQuery;

  if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
                                                delegatedQuery, capabilities)) {
    return;
  }
  if (chassisId != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
    return;
  }
  getDumpEntryCollection(app, req, asyncResp,
                         Dump{.type = DumpType::SYSTEM_DUMP}, delegatedQuery);
}

inline void handleLogServicesDumpEntryGet(
    crow::App& app, DumpType dumpType, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& dumpId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  getDumpEntryById(asyncResp, dumpId, Dump{.type = dumpType});
}

inline void handleLogServicesDumpEntryComputerSystemGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& dumpId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (chassisId != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
    return;
  }
  getDumpEntryById(asyncResp, dumpId, Dump{.type = DumpType::SYSTEM_DUMP});
}

inline void handleLogServicesDumpEntryDelete(
    crow::App& app, DumpType dumpType, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& dumpId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  deleteDumpEntry(asyncResp, dumpId, Dump{.type = dumpType});
}

inline void handleLogServicesDumpEntryComputerSystemDelete(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& dumpId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (chassisId != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
    return;
  }
  deleteDumpEntry(asyncResp, dumpId, Dump{.type = DumpType::SYSTEM_DUMP});
}

inline void handleLogServicesDumpEntryDownloadGet(
    crow::App& app, DumpType dumpType, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& dumpId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  downloadDumpEntry(asyncResp, dumpId, Dump{.type = dumpType});
}

inline void handleLogServicesDumpCollectDiagnosticDataPost(
    crow::App& app, DumpType dumpType, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  createDump(asyncResp, req, Dump{.type = dumpType});
}

inline void handleLogServicesDumpCollectDiagnosticDataComputerSystemPost(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (chassisId != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
    return;
  }
  createDump(asyncResp, req, Dump{.type = DumpType::SYSTEM_DUMP});
}

inline void handleLogServicesDumpClearLogPost(
    crow::App& app, DumpType dumpType, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  clearDump(asyncResp, Dump{.type = dumpType});
}

inline void handleLogServicesDumpClearLogComputerSystemPost(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (chassisId != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", chassisId);
    return;
  }
  clearDump(asyncResp, Dump{.type = DumpType::SYSTEM_DUMP});
}

inline void handleLogServiceFaultLogEntriesGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  query_param::QueryCapabilities capabilities = {
      .canDelegateExpandLevel = 2,
      .canDelegateFilter = true,
  };
  query_param::Query delegatedQuery;
  if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
                                                delegatedQuery, capabilities)) {
    return;
  }
  getDumpEntryCollection(
      app, req, asyncResp,
      Dump{.type = DumpType::SYSTEM_FAULT_LOG, .systemName = systemName},
      delegatedQuery);
}

void requestRoutesBMCDumpService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleLogServicesDumpServiceGet, std::ref(app), DumpType::BMC_DUMP));
}

void requestRoutesBMCDumpEntryCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/")
      .privileges(redfish::privileges::getLogEntryCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLogServicesDumpEntriesCollectionGet,
                          std::ref(app), DumpType::BMC_DUMP));
}

void requestRoutesBMCDumpEntry(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleLogServicesDumpEntryGet, std::ref(app), DumpType::BMC_DUMP));

  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/")
      .privileges(redfish::privileges::deleteLogEntry)
      .methods(boost::beast::http::verb::delete_)(std::bind_front(
          handleLogServicesDumpEntryDelete, std::ref(app), DumpType::BMC_DUMP));
}

void requestRoutesBMCDumpEntryDownload(App& app) {
  BMCWEB_ROUTE(
      app, "/redfish/v1/Managers/bmc/LogServices/Dump/Entries/<str>/attachment")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLogServicesDumpEntryDownloadGet, std::ref(app),
                          DumpType::BMC_DUMP));
}

void requestRoutesBMCDumpCreate(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Managers/bmc/LogServices/Dump/Actions/"
               "LogService.CollectDiagnosticData/")
      .privileges(redfish::privileges::postLogService)
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleLogServicesDumpCollectDiagnosticDataPost,
                          std::ref(app), DumpType::BMC_DUMP));
}

void requestRoutesBMCDumpClear(App& app) {
  BMCWEB_ROUTE(
      app,
      "/redfish/v1/Managers/bmc/LogServices/Dump/Actions/LogService.ClearLog/")
      .privileges(redfish::privileges::postLogService)
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleLogServicesDumpClearLogPost, std::ref(app),
                          DumpType::BMC_DUMP));
}

void requestRoutesFaultLogDumpService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/FaultLog/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLogServicesDumpServiceGet, std::ref(app),
                          DumpType::BMC_FAULT_LOG));

  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/FaultLog/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(
          [&app](const crow::Request& req,
                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                 const std::string& systemName) {
            if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
              return;
            }
            internal::getDumpServiceInfo(
                asyncResp, Dump{.type = DumpType::SYSTEM_FAULT_LOG,
                                .systemName = systemName});
          });
}

void requestRoutesFaultLogDumpEntryCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/FaultLog/Entries/")
      .privileges(redfish::privileges::getLogEntryCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLogServicesDumpEntriesCollectionGet,
                          std::ref(app), DumpType::BMC_FAULT_LOG));

  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/FaultLog/Entries/")
      .privileges(redfish::privileges::getLogEntryCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLogServiceFaultLogEntriesGet, std::ref(app)));
}

void requestRoutesFaultLogDumpEntry(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Managers/bmc/LogServices/FaultLog/Entries/<str>/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLogServicesDumpEntryGet, std::ref(app),
                          DumpType::BMC_FAULT_LOG));

  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/FaultLog/Entries/<str>/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(
          [&app](const crow::Request& req,
                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                 const std::string& systemName, const std::string& dumpId) {
            if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
              return;
            }
            getDumpEntryById(asyncResp, dumpId,
                             Dump{.type = DumpType::SYSTEM_FAULT_LOG,
                                  .systemName = systemName});
          });

  BMCWEB_ROUTE(app,
               "/redfish/v1/Managers/bmc/LogServices/FaultLog/Entries/<str>/")
      .privileges(redfish::privileges::deleteLogEntry)
      .methods(boost::beast::http::verb::delete_)(
          std::bind_front(handleLogServicesDumpEntryDelete, std::ref(app),
                          DumpType::BMC_FAULT_LOG));

  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/FaultLog/Entries/<str>/")
      .privileges(redfish::privileges::deleteLogEntry)
      .methods(boost::beast::http::verb::delete_)(
          [&app](const crow::Request& req,
                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                 const std::string& systemName, const std::string& dumpId) {
            if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
              return;
            }
            deleteDumpEntry(asyncResp, dumpId,
                            Dump{.type = DumpType::SYSTEM_FAULT_LOG,
                                 .systemName = systemName});
          });
}

void requestRoutesFaultLogDumpClear(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Managers/bmc/LogServices/FaultLog/Actions/"
               "LogService.ClearLog/")
      .privileges(redfish::privileges::postLogService)
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleLogServicesDumpClearLogPost, std::ref(app),
                          DumpType::BMC_FAULT_LOG));

  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/FaultLog/Actions/"
               "LogService.ClearLog/")
      .privileges(redfish::privileges::postLogService)
      .methods(boost::beast::http::verb::post)(
          [&app](const crow::Request& req,
                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                 const std::string& systemName) {
            if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
              return;
            }
            clearDump(asyncResp, Dump{.type = DumpType::SYSTEM_FAULT_LOG,
                                      .systemName = systemName});
          });
}

void requestRoutesSystemDumpService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleLogServicesDumpServiceComputerSystemGet, std::ref(app)));
}

void requestRoutesSystemDumpEntryCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/")
      .privileges(redfish::privileges::getLogEntryCollection)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleLogServicesDumpEntriesCollectionComputerSystemGet,
          std::ref(app)));
}

void requestRoutesSystemDumpEntry(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleLogServicesDumpEntryComputerSystemGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Dump/Entries/<str>/")
      .privileges(redfish::privileges::deleteLogEntry)
      .methods(boost::beast::http::verb::delete_)(std::bind_front(
          handleLogServicesDumpEntryComputerSystemDelete, std::ref(app)));
}

void requestRoutesSystemDumpCreate(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/"
               "LogService.CollectDiagnosticData/")
      .privileges(redfish::privileges::postLogService)
      .methods(boost::beast::http::verb::post)(std::bind_front(
          handleLogServicesDumpCollectDiagnosticDataComputerSystemPost,
          std::ref(app)));
}

void requestRoutesSystemDumpClear(App& app) {
  BMCWEB_ROUTE(
      app,
      "/redfish/v1/Systems/<str>/LogServices/Dump/Actions/LogService.ClearLog/")
      .privileges(redfish::privileges::postLogService)
      .methods(boost::beast::http::verb::post)(std::bind_front(
          handleLogServicesDumpClearLogComputerSystemPost, std::ref(app)));
}

#ifdef BMCWEB_ENABLE_RASMANAGER_EVENT_LOG
inline void handleLogServicesRasManagerGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (systemName != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", systemName);
    return;
  }

  // Copy over the static data to include the entries added by
  // SubRoute
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Systems/system/LogServices/HostCper";
  asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
  asyncResp->res.jsonValue["Name"] = "Open BMC Oem RasManager Service";
  asyncResp->res.jsonValue["Description"] = "Oem RasManager Service";
  asyncResp->res.jsonValue["Id"] = "RasManager";
  asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";

  std::pair<std::string, std::string> redfishDateTimeOffset =
      redfish::time_utils::getDateTimeOffsetNow();
  asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
  asyncResp->res.jsonValue["DateTimeLocalOffset"] =
      redfishDateTimeOffset.second;

  asyncResp->res.jsonValue["Entries"]["@odata.id"] =
      crow::utility::urlFromPieces("redfish", "v1", "Systems", "system",
                                   "LogServices", "HostCper", "Entries");
  asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]["target"] =
      "/redfish/v1/Systems/system/LogServices/HostCper/Actions/"
      "LogService.ClearLog";
}

void requestRoutesRasManagerLogService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/HostCper/")
      .privileges({{"ConfigureManager"}})
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLogServicesRasManagerGet, std::ref(app)));
}

inline void handleLogServicesRasManagerClearLogPost(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (systemName != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", systemName);
    return;
  }
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp](const boost::system::error_code& ec, const std::string&) {
        if (ec) {
          messages::internalError(asyncResp->res);
          return;
        }
        messages::success(asyncResp->res);
      },
      rasManagerObject, rasManagerPath, deleteAllInterface, "DeleteAll");
}

void requestRoutesRasManagerLogClear(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/HostCper/Actions/"
               "LogService.ClearLog/")
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::post)(std::bind_front(
          handleLogServicesRasManagerClearLogPost, std::ref(app)));
}

inline static void logRasManagerEntry(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& logID, nlohmann::json& logEntryJson) {
  auto getStoredLogCallback =
      [asyncResp, logID, &logEntryJson](
          const boost::system::error_code& ec,
          const dbus::utility::DBusPropertiesMap& params) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "failed to get log ec: " << ec.message();
          if (ec.value() ==
              boost::system::linux_error::bad_request_descriptor) {
            messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
          } else {
            messages::internalError(asyncResp->res);
          }
          return;
        }

        uint64_t timestampMs = 0;
        const uint64_t* timestampPtr = nullptr;
        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), params, "TimestampMs",
            timestampPtr);

        if (!success) {
          return;
        }

        if (timestampPtr != nullptr) {
          timestampMs = *timestampPtr;
        }

        nlohmann::json::object_t logEntry;
        logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
        logEntry["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Systems", "system", "LogServices", "HostCper",
            "Entries", logID);
        logEntry["Name"] = "RasManager";
        logEntry["Id"] = logID;
        logEntry["EntryType"] = "Oem";
        logEntry["DiagnosticDataType"] = "CPER";
        logEntry["OemRecordFormat"] = "CPER";
        logEntry["Created"] =
            redfish::time_utils::getDateTimeUintMs(timestampMs);

        // read bin data from file and then encode it to boost base64
        std::string cperFile = rasManagerLogPath + logID + ".cpr";
        std::ifstream ifs(cperFile, std::ios::in | std::ios::binary);
        if (!ifs.is_open()) {
          BMCWEB_LOG_ERROR << "Failed to open file: " << cperFile;
          return;
        }
        std::string cperData((std::istreambuf_iterator<char>(ifs)),
                             (std::istreambuf_iterator<char>()));
        std::string encodedData;
        encodedData.resize(
            boost::beast::detail::base64::encoded_size(cperData.size()));
        encodedData.resize(boost::beast::detail::base64::encode(
            &encodedData[0], cperData.data(), cperData.size()));
        logEntry["DiagnosticData"] = std::move(encodedData);
        ifs.close();

        // If logEntryJson references an array of LogEntry resources
        // ('Members' list), then push this as a new entry, otherwise set it
        // directly
        if (logEntryJson.is_array()) {
          logEntryJson.push_back(logEntry);
          asyncResp->res.jsonValue["Members@odata.count"] = logEntryJson.size();
        } else {
          logEntryJson.update(logEntry);
        }
      };
  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      rasManagerObject, rasManagerPath + std::string("/") + logID,
      "xyz.openbmc_project.Time.EpochTime", context,
      std::move(getStoredLogCallback));
}

inline void handleLogServicesRasManagerEntriesCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (systemName != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", systemName);
    return;
  }

  constexpr std::array<std::string_view, 1> interfaces = {
      "xyz.openbmc_project.Time.EpochTime"};
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      rasManagerPath, 0, interfaces, requestContext,
      [asyncResp](const boost::system::error_code& ec,
                  const std::vector<std::string>& resp) {
        if (ec) {
          if (ec.value() != boost::system::errc::no_such_file_or_directory) {
            BMCWEB_LOG_DEBUG << "failed to get entries ec: " << ec.message();
            messages::internalError(asyncResp->res);
            return;
          }
        }
        asyncResp->res.jsonValue["@odata.type"] =
            "#LogEntryCollection.LogEntryCollection";
        asyncResp->res.jsonValue["@odata.id"] =
            "/redfish/v1/Systems/system/LogServices/HostCper/Entries";
        asyncResp->res.jsonValue["Name"] = "Open BMC RasManager Entries";
        asyncResp->res.jsonValue["Description"] =
            "Collection of RasManager Entries";
        asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
        asyncResp->res.jsonValue["Members@odata.count"] = 0;

        for (const std::string& path : resp) {
          const sdbusplus::message::object_path objPath(path);
          // Get the log ID
          std::string logID = objPath.filename();
          if (logID.empty()) {
            continue;
          }
          // Add the log entry to the array
          logRasManagerEntry(asyncResp, logID,
                             asyncResp->res.jsonValue["Members"]);
        }
      });
}

void requestRoutesRasManagerLogEntryCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/HostCper/Entries/")
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleLogServicesRasManagerEntriesCollectionGet, std::ref(app)));
}

inline void handleLogServicesRasManagerEntryGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& param) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (systemName != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", systemName);
    return;
  }
  const std::string& logID = param;

  logRasManagerEntry(asyncResp, logID, asyncResp->res.jsonValue);
}

void requestRoutesRasManagerLogEntry(App& app) {
  // Note: Deviated from redfish privilege registry for GET & HEAD
  // method for security reasons.

  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/HostCper/Entries/<str>/")
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLogServicesRasManagerEntryGet, std::ref(app)));
}
#endif  // BMCWEB_ENABLE_RASMANAGER_EVENT_LOG

#ifdef BMCWEB_ENABLE_ILIAD_EVENT_LOG
inline void handleLogServicesIliadGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  // TODO: b/488145767, this handler duplicates the error log to all systems.
  //  This is not ideal.
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  // Copy over the static data to include the entries added by
  // SubRoute
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/IliadCper";
  asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
  asyncResp->res.jsonValue["Name"] = "Open BMC Iliad Event Service";
  asyncResp->res.jsonValue["Description"] = "Iliad Event Service";
  asyncResp->res.jsonValue["Id"] = "IliadCper";
  asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";

  std::pair<std::string, std::string> redfishDateTimeOffset =
      redfish::time_utils::getDateTimeOffsetNow();
  asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
  asyncResp->res.jsonValue["DateTimeLocalOffset"] =
      redfishDateTimeOffset.second;

  asyncResp->res.jsonValue["Entries"]["@odata.id"] =
      crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                   "LogServices", "IliadCper", "Entries");
  asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]["target"] =
      "/redfish/v1/Systems/" + systemName +
      "/LogServices/IliadCper/Actions/"
      "LogService.ClearLog";
}

void requestRoutesIliadLogService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/IliadCper/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLogServicesIliadGet, std::ref(app)));
}

// TODO: b/487370130, write a unit time test for this function.
inline static void logIliadEntry(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& logID,
    bool isCollection) {
  nlohmann::json& logEntryJson = isCollection
                                     ? asyncResp->res.jsonValue["Members"]
                                     : asyncResp->res.jsonValue;
  auto getStoredLogCallback =
      [asyncResp, systemName, logID, &logEntryJson](
          const boost::system::error_code& ec,
          const dbus::utility::DBusPropertiesMap& params) {
        if (ec) {
          BMCWEB_LOG_ALWAYS << "failed to get log ec: " << ec.message();
          if (ec.value() ==
              boost::system::linux_error::bad_request_descriptor) {
            messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
          } else {
            messages::internalError(asyncResp->res);
          }
          return;
        }
        std::string cperFileName;
        const std::string* fileNamePtr = nullptr;
        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), params, "Path", fileNamePtr);

        if (!success) {
          BMCWEB_LOG_ERROR << "Failed to unpack FilePath property for logID: "
                           << logID;
          return;
        }

        if (fileNamePtr != nullptr) {
          cperFileName = *fileNamePtr;
        }
        nlohmann::json::object_t logEntry;
        logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
        logEntry["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Systems", systemName, "LogServices", "IliadCper",
            "Entries", logID);
        logEntry["Name"] = "Iliad Manager";
        logEntry["Id"] = logID;
        logEntry["EntryType"] = "Oem";
        logEntry["DiagnosticDataType"] = "CPER";
        logEntry["OemRecordFormat"] = "CPER";

        // read bin data from file and then encode it to boost base64
        std::ifstream ifs(cperFileName, std::ios::in | std::ios::binary);
        if (!ifs.is_open()) {
          BMCWEB_LOG_ERROR << "Failed to open file: " << cperFileName;
          return;
        }
        std::string cperData((std::istreambuf_iterator<char>(ifs)),
                             (std::istreambuf_iterator<char>()));
        std::string encodedData;
        encodedData.resize(
            boost::beast::detail::base64::encoded_size(cperData.size()));
        encodedData.resize(boost::beast::detail::base64::encode(
            &encodedData[0], cperData.data(), cperData.size()));
        logEntry["DiagnosticData"] = std::move(encodedData);
        ifs.close();

        // If logEntryJson references an array of LogEntry resources
        // ('Members' list), then push this as a new entry, otherwise set it
        // directly
        if (logEntryJson.is_array()) {
          logEntryJson.push_back(logEntry);
          asyncResp->res.jsonValue["Members@odata.count"] = logEntryJson.size();
        } else {
          logEntryJson.update(logEntry);
        }
      };
  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      iliadObject, iliadPath + logID, "xyz.openbmc_project.Common.FilePath",
      context, std::move(getStoredLogCallback));
}

inline void handleLogServicesIliadEntriesCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  constexpr std::array<std::string_view, 1> interfaces = {
      "xyz.openbmc_project.Common.FilePath"};
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      iliadPath, 0, interfaces, requestContext,
      [asyncResp, systemName](const boost::system::error_code& ec,
                              const std::vector<std::string>& resp) {
        if (ec) {
          if (ec.value() != boost::system::errc::io_error) {
            BMCWEB_LOG_DEBUG << "failed to get entries ec: " << ec.message();
            messages::internalError(asyncResp->res);
            return;
          }
        }
        asyncResp->res.jsonValue["@odata.type"] =
            "#LogEntryCollection.LogEntryCollection";
        asyncResp->res.jsonValue["@odata.id"] =
            "/redfish/v1/Systems/" + systemName +
            "/LogServices/IliadCper/Entries";
        asyncResp->res.jsonValue["Name"] = "Open BMC Iliad Cper Entries";
        asyncResp->res.jsonValue["Description"] =
            "Collection of Iliad Cper Entries";
        asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
        asyncResp->res.jsonValue["Members@odata.count"] = 0;
        for (const std::string& path : resp) {
          const sdbusplus::message::object_path objPath(path);
          // Get the log ID
          std::string logID = objPath.filename();

          if (logID.empty()) {
            continue;
          }
          // Add the log entry to the array
          logIliadEntry(asyncResp, systemName, logID, true);
        }
      });
}

void requestRoutesIliadLogEntryCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/IliadCper/Entries/")
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleLogServicesIliadEntriesCollectionGet, std::ref(app)));
}

inline void handleLogServicesIliadEntryGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& param) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  const std::string& logID = param;

  logIliadEntry(asyncResp, systemName, logID, false);
}

void requestRoutesIliadLogEntry(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/IliadCper/Entries/<str>/")
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLogServicesIliadEntryGet, std::ref(app)));
}
#endif  // BMCWEB_ENABLE_Iliad_EVENT_LOG

void handleGetCrashdumpService(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  redfish::system_utils::getSystemInformation(
      asyncResp, systemName,
      [systemName](const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& /*systemPath*/) {
        // Copy over the static data to include the entries added by
        // SubRoute
        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Systems", systemName, "LogServices", "Crashdump");
        asyncResp->res.jsonValue["@odata.type"] =
            "#LogService.v1_2_0.LogService";
        asyncResp->res.jsonValue["Name"] = "Crashdump Service";
        asyncResp->res.jsonValue["Description"] = "Crashdump Service";
        asyncResp->res.jsonValue["Id"] = "Crashdump";
        asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";

        std::pair<std::string, std::string> redfishDateTimeOffset =
            redfish::time_utils::getDateTimeOffsetNow();
        asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
        asyncResp->res.jsonValue["DateTimeLocalOffset"] =
            redfishDateTimeOffset.second;

        asyncResp->res.jsonValue["Entries"]["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                         "LogServices", "Crashdump", "Entries");

        // Currently only support these in single host.
        if (systemName == "system") {
          asyncResp->res
              .jsonValue["Actions"]["#LogService.ClearLog"]["target"] =
              "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/"
              "LogService.ClearLog";
          asyncResp->res
              .jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
                        ["target"] =
              "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/"
              "LogService.CollectDiagnosticData";
        }
      });
}

void requestRoutesCrashdumpService(App& app) {
  // Note: Deviated from redfish privilege registry for GET & HEAD
  // method for security reasons.
  /**
   * Functions triggers appropriate requests on DBus
   */
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/")
      // This is incorrect, should be:
      // .privileges(redfish::privileges::getLogService)
      .privileges({{"ConfigureManager"}})
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetCrashdumpService, std::ref(app)));
}

inline void handlePostCrashdumpClear(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (systemName != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", systemName);
    return;
  }
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp](const boost::system::error_code& ec, const std::string&) {
        if (ec) {
          messages::internalError(asyncResp->res);
          return;
        }
        messages::success(asyncResp->res);
      },
      crashdumpObject, crashdumpPath, deleteAllInterface, "DeleteAll");
}

void requestRoutesCrashdumpClear(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/"
               "LogService.ClearLog/")
      // This is incorrect, should be:
      // .privileges(redfish::privileges::postLogService)
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handlePostCrashdumpClear, std::ref(app)));
}

inline static void logCrashdumpEntry(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& logID,
    nlohmann::json& logEntryJson) {
  auto getStoredLogCallback =
      [asyncResp, systemName, logID, &logEntryJson](
          const boost::system::error_code& ec,
          const dbus::utility::DBusPropertiesMap& params) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "failed to get log ec: " << ec.message();
          return;
        }

        std::string timestamp{};
        std::string filename{};
        std::string logfile{};
        parseCrashdumpParameters(params, filename, timestamp, logfile);

        if (filename.empty() || timestamp.empty()) {
          return;
        }

        std::string prefixedLogID =
            absl::StrCat(kPrimaryCrashdumpPrefix, logID);
        std::string crashdumpURI = absl::StrCat(
            "/redfish/v1/Systems/", systemName,
            "/LogServices/Crashdump/Entries/", prefixedLogID, "/", filename);
        nlohmann::json::object_t logEntry;
        logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
        logEntry["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Systems", systemName, "LogServices", "Crashdump",
            "Entries", prefixedLogID);
        logEntry["Name"] = "CPU Crashdump";
        logEntry["Id"] = logID;
        logEntry["EntryType"] = "Oem";
        logEntry["AdditionalDataURI"] = std::move(crashdumpURI);
        logEntry["DiagnosticDataType"] = "OEM";
        if constexpr (bmcwebEnableAmd) {
          logEntry["OEMDiagnosticDataType"] = "CPER";
        } else {
          logEntry["OEMDiagnosticDataType"] = "PECICrashdump";
        }
        logEntry["Created"] = std::move(timestamp);

        // If logEntryJson references an array of LogEntry resources
        // ('Members' list), then push this as a new entry, otherwise set it
        // directly
        if (logEntryJson.is_array()) {
          logEntryJson.push_back(logEntry);
          asyncResp->res.jsonValue["Members@odata.count"] = logEntryJson.size();
        } else {
          logEntryJson.update(logEntry);
        }
      };
  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      crashdumpObject, absl::StrCat(crashdumpPath, "/", logID),
      crashdumpInterface, context, std::move(getStoredLogCallback));
}

inline std::optional<uint64_t> elapsedTimestampFromDbusObject(
    const dbus::utility::ManagedObjectType::value_type& object) {
  for (const auto& interfaceMap : object.second) {
    if (interfaceMap.first != "xyz.openbmc_project.Time.EpochTime") {
      continue;
    }
    for (const auto& propertyMap : interfaceMap.second) {
      if (propertyMap.first == "Elapsed") {
        const uint64_t* usecsTimeStamp =
            std::get_if<uint64_t>(&propertyMap.second);
        if (usecsTimeStamp != nullptr) {
          return *usecsTimeStamp;
        }
      }
    }
  }
  return std::nullopt;
}

inline std::optional<std::string> getFaultLogStringPropertyFromDbusObject(
    const dbus::utility::ManagedObjectType::value_type& object,
    std::string_view propertyName) {
  for (const auto& interfaceMap : object.second) {
    if (interfaceMap.first != "xyz.openbmc_project.Dump.Entry.FaultLog") {
      continue;
    }
    for (const auto& propertyMap : interfaceMap.second) {
      if (propertyMap.first == propertyName) {
        const std::string* val = std::get_if<std::string>(&propertyMap.second);
        if (val != nullptr) {
          return *val;
        }
      }
    }
  }
  return std::nullopt;
}

inline std::optional<std::string> primaryLogIdFromDbusObject(
    const dbus::utility::ManagedObjectType::value_type& object) {
  return getFaultLogStringPropertyFromDbusObject(object, "PrimaryLogId");
}

inline std::optional<std::string> prettyNameFromDbusObject(
    const dbus::utility::ManagedObjectType::value_type& object) {
  return getFaultLogStringPropertyFromDbusObject(object, "PrettyName");
}

inline bool isDumpManagerCrashdumpType(
    const dbus::utility::ManagedObjectType::value_type& object) {
  for (const auto& interfaceMap : object.second) {
    if (interfaceMap.first == "xyz.openbmc_project.Dump.Entry.FaultLog") {
      for (const auto& propertyMap : interfaceMap.second) {
        if (propertyMap.first == "Type") {
          const std::string* typePtr =
              std::get_if<std::string>(&propertyMap.second);
          if (typePtr != nullptr) {
            return *typePtr ==
                       "xyz.openbmc_project.Common.FaultLogType.FaultLogTypes."
                       "Crashdump" ||
                   *typePtr == "Crashdump";
          }
        }
      }
    }
  }
  return false;
}

std::optional<std::string> crashdumpFolderPathFromSystemName(
    std::string_view systemName, std::string_view basePathPrefix) {
  constexpr std::array<std::pair<std::string_view, std::string_view>, 2>
      systemNameToHostCrashdumpPath = {{
          {"system1", "/var/run/pldm/event/repo/host0/Crashdump/"},
          {"system2", "/var/run/pldm/event/repo/host1/Crashdump/"},
      }};

  for (const auto& [name, path] : systemNameToHostCrashdumpPath) {
    if (name == systemName) {
      return absl::StrCat(basePathPrefix, path);
    }
  }
  return std::nullopt;
}

inline std::optional<std::string> getCrashdumpFilePathFromDbusObject(
    const dbus::utility::ManagedObjectType::value_type& object,
    std::string_view systemName, std::string_view basePathPrefix = "") {
  std::optional<std::string> logPath =
      getFaultLogStringPropertyFromDbusObject(object, "Log");
  if (logPath && !logPath->empty()) {
    return absl::StrCat(basePathPrefix, *logPath);
  }
  std::optional<std::string> crashdumpFolderPath =
      crashdumpFolderPathFromSystemName(systemName, basePathPrefix);
  if (!crashdumpFolderPath) {
    return std::nullopt;
  }
  std::optional<std::string> primaryLogId = primaryLogIdFromDbusObject(object);
  if (!primaryLogId || primaryLogId->empty()) {
    BMCWEB_LOG_ERROR << "Entry for " << object.first.str
                     << " does not have PrimaryLogId";
    return std::nullopt;
  }
  return absl::StrCat(*crashdumpFolderPath, *primaryLogId);
}

inline bool populateDumpManagerCrashdumpEntryJson(
    const dbus::utility::ManagedObjectType::value_type& object,
    const std::string& systemName,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    nlohmann::json& entryJson, std::string_view basePathPrefix = "") {
  if (!isDumpManagerCrashdumpType(object)) {
    return false;
  }

  std::optional<uint64_t> timestampUs = elapsedTimestampFromDbusObject(object);
  if (!timestampUs) {
    BMCWEB_LOG_ERROR << "Entry for " << object.first.str
                     << " does not have a timestamp";
    messages::internalError(asyncResp->res);
    return false;
  }

  std::string rawEntryID = object.first.filename();
  std::string prefixedEntryID = absl::StrCat(
      getRedfishPrefixForDbusObjectPath(object.first, systemName), rawEntryID);

  entryJson["@odata.type"] = "#LogEntry.v1_11_0.LogEntry";
  entryJson["@odata.id"] = crow::utility::urlFromPieces(
      "redfish", "v1", "Systems", systemName, "LogServices", "Crashdump",
      "Entries", prefixedEntryID);
  entryJson["Id"] = rawEntryID;
  entryJson["EntryType"] = "Oem";
  entryJson["Name"] = "Host Crashdump Entry";
  std::optional<std::string> prettyName = prettyNameFromDbusObject(object);
  if (prettyName && !prettyName->empty()) {
    entryJson["Name"] = *prettyName;
  }
  entryJson["Created"] = redfish::time_utils::getDateTimeUintUs(*timestampUs);

  entryJson["DiagnosticDataType"] = "CPER";

  std::optional<std::string> fullFilePath = getCrashdumpFilePathFromDbusObject(
      object, systemName, basePathPrefix);
  if (!fullFilePath) {
    messages::internalError(asyncResp->res);
    return false;
  }

  std::ifstream ifs(*fullFilePath, std::ios::in | std::ios::binary);
  if (!ifs.is_open()) {
    messages::internalError(asyncResp->res);
    return false;
  }
  std::string fileData((std::istreambuf_iterator<char>(ifs)),
                       (std::istreambuf_iterator<char>()));
  std::string encodedData;
  encodedData.resize(
      boost::beast::detail::base64::encoded_size(fileData.size()));
  encodedData.resize(boost::beast::detail::base64::encode(
      &encodedData[0], fileData.data(), fileData.size()));
  entryJson["DiagnosticData"] = std::move(encodedData);
  ifs.close();

  return true;
}

inline void appendDumpManagerCrashdumpEntries(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, std::string_view basePathPrefix = "") {
  std::optional<std::string> targetPathPrefix = getDumpEntryPathFromDump(
      Dump{.type = DumpType::BMC_FAULT_LOG, .systemName = systemName});
  if (!targetPathPrefix) {
    return;
  }

  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
      "xyz.openbmc_project.Dump.Manager", {"/xyz/openbmc_project/dump"},
      context,
      [asyncResp, systemName, targetPrefix{*targetPathPrefix},
       basePathPrefix{std::string(basePathPrefix)}](
          const boost::system::error_code& ec,
          const dbus::utility::ManagedObjectType& managedObjects) {
        // We cant return error since we cant expect all daemons to be on all
        // platforms.
        if (ec) {
          BMCWEB_LOG_DEBUG << "appendDumpManagerCrashdumpEntries got ec: "
                           << ec;
          return;
        }

        dbus::utility::ManagedObjectType resp = managedObjects;
        std::sort(resp.begin(), resp.end(), [](const auto& l, const auto& r) {
          return AlphanumLess<std::string>()(l.first.filename(),
                                             r.first.filename());
        });

        for (const auto& object : resp) {
          if (!object.first.str.starts_with(targetPrefix) &&
              !object.first.str.starts_with(
                  kSystemAgnosticDumpEntryPathPrefix)) {
            continue;
          }
          if (object.first.filename().empty()) {
            continue;
          }

          nlohmann::json thisEntry;
          if (populateDumpManagerCrashdumpEntryJson(
                  object, systemName, asyncResp, thisEntry, basePathPrefix)) {
            nlohmann::json& members = asyncResp->res.jsonValue["Members"];
            members.push_back(std::move(thisEntry));
            asyncResp->res.jsonValue["Members@odata.count"] = members.size();
          }
        }
      });
}

inline void getDumpManagerCrashdumpEntryById(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& rawEntryID,
    std::string_view targetPathPrefix,
    std::string_view basePathPrefix = "") {
  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
      "xyz.openbmc_project.Dump.Manager", {"/xyz/openbmc_project/dump"},
      context,
      [asyncResp, systemName, rawEntryID,
       targetObjectPath{absl::StrCat(targetPathPrefix, rawEntryID)},
       basePathPrefix{std::string(basePathPrefix)}](
          const boost::system::error_code& ec,
          const dbus::utility::ManagedObjectType& resp) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "getDumpManagerCrashdumpEntryById got ec: " << ec;
          messages::resourceNotFound(
              asyncResp->res, "LogEntry",
              absl::StrCat(kDumpManagerCrashdumpPrefix, rawEntryID));
          return;
        }

        bool foundEntry = false;
        for (const auto& objectPath : resp) {
          if (objectPath.first.str != targetObjectPath) {
            continue;
          }

          if (!isDumpManagerCrashdumpType(objectPath)) {
            break;
          }

          foundEntry = true;
          nlohmann::json entryJson;
          if (populateDumpManagerCrashdumpEntryJson(objectPath, systemName,
                                                    asyncResp, entryJson,
                                                    basePathPrefix)) {
            asyncResp->res.jsonValue = std::move(entryJson);
          }
          break;
        }

        if (!foundEntry) {
          messages::resourceNotFound(
              asyncResp->res, "LogEntry",
              absl::StrCat(kDumpManagerCrashdumpPrefix, rawEntryID));
        }
      });
}

inline void getSystemSpecificCrashdumpEntryById(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& rawEntryID,
    std::string_view basePathPrefix = "") {
  std::optional<std::string> targetPathPrefix = getDumpEntryPathFromDump(
      Dump{.type = DumpType::BMC_FAULT_LOG, .systemName = systemName});
  if (!targetPathPrefix) {
    std::string prefixedID = absl::StrCat(
        kDumpManagerCrashdumpPrefix, systemName, "_", rawEntryID);
    messages::resourceNotFound(asyncResp->res, "LogEntry", prefixedID);
    return;
  }
  getDumpManagerCrashdumpEntryById(asyncResp, systemName, rawEntryID,
                                   *targetPathPrefix, basePathPrefix);
}

inline void getSystemAgnosticCrashdumpEntryById(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& rawEntryID,
    std::string_view basePathPrefix = "") {
  getDumpManagerCrashdumpEntryById(asyncResp, systemName, rawEntryID,
                                   kSystemAgnosticDumpEntryPathPrefix,
                                   basePathPrefix);
}

inline void appendPrimaryCrashdumpEntries(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  constexpr std::array<std::string_view, 1> interfaces = {crashdumpInterface};
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      "/", 0, interfaces, requestContext,
      [asyncResp, systemName](const boost::system::error_code& ec,
                              const std::vector<std::string>& resp) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "failed to get entries ec: " << ec.message();
          return;
        }

        for (const std::string& path : resp) {
          const sdbusplus::message::object_path objPath(path);
          // Get the log ID
          std::string logID = objPath.filename();
          if (logID.empty()) {
            continue;
          }
          // Add the log entry to the array
          logCrashdumpEntry(asyncResp, systemName, logID,
                            asyncResp->res.jsonValue["Members"]);
        }
      });
}

void handleGetCrashdumpEntryCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  handleGetCrashdumpEntryCollection(app, req, asyncResp, systemName, "");
}

void handleGetCrashdumpEntryCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& basePathPrefix) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  redfish::system_utils::getSystemInformation(
      asyncResp, systemName,
      [systemName, basePathPrefix](
          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
          const std::string& /*systemPath*/) {
        asyncResp->res.jsonValue["@odata.type"] =
            "#LogEntryCollection.LogEntryCollection";
        asyncResp->res.jsonValue["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                         "LogServices", "Crashdump", "Entries");
        asyncResp->res.jsonValue["Name"] = "Crashdump Entries";
        asyncResp->res.jsonValue["Description"] =
            "Collection of Crashdump Entries";
        asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
        asyncResp->res.jsonValue["Members@odata.count"] = 0;

        appendPrimaryCrashdumpEntries(asyncResp, systemName);
        appendDumpManagerCrashdumpEntries(asyncResp, systemName,
                                          basePathPrefix);
      });
}

void requestRoutesCrashdumpEntryCollection(App& app) {
  // Note: Deviated from redfish privilege registry for GET & HEAD
  // method for security reasons.
  /**
   * Functions triggers appropriate requests on DBus
   */
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/")
      // This is incorrect, should be.
      // .privileges(redfish::privileges::postLogEntryCollection)
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::get)(
          [&app](const crow::Request& req,
                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                 const std::string& systemName) {
            handleGetCrashdumpEntryCollection(app, req, asyncResp, systemName);
          });
}

void handleGetCrashdumpEntry(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& param) {
  handleGetCrashdumpEntry(app, req, asyncResp, systemName, param, "");
}

void handleGetCrashdumpEntry(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& param,
    const std::string& basePathPrefix) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  const std::string& logID = param;

  redfish::system_utils::getSystemInformation(
      asyncResp, systemName,
      [systemName, logID, basePathPrefix](
          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
          const std::string& /*systemPath*/) {
        std::string systemSpecificDumpManagerPrefix =
            absl::StrCat(kDumpManagerCrashdumpPrefix, systemName, "_");
        if (logID.starts_with(kPrimaryCrashdumpPrefix)) {
          std::string rawID = logID.substr(kPrimaryCrashdumpPrefix.size());
          logCrashdumpEntry(asyncResp, systemName, rawID,
                            asyncResp->res.jsonValue);
        } else if (logID.starts_with(systemSpecificDumpManagerPrefix)) {
          std::string rawID =
              logID.substr(systemSpecificDumpManagerPrefix.size());
          getSystemSpecificCrashdumpEntryById(asyncResp, systemName, rawID,
                                              basePathPrefix);
        } else if (logID.starts_with(kDumpManagerCrashdumpPrefix)) {
          std::string rawID = logID.substr(kDumpManagerCrashdumpPrefix.size());
          getSystemAgnosticCrashdumpEntryById(asyncResp, systemName, rawID,
                                              basePathPrefix);
        } else {
          messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
        }
      });
}

void requestRoutesCrashdumpEntry(App& app) {
  // Note: Deviated from redfish privilege registry for GET & HEAD
  // method for security reasons.

  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/")
      // this is incorrect, should be
      // .privileges(redfish::privileges::getLogEntry)
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::get)(
          [&app](const crow::Request& req,
                 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                 const std::string& systemName, const std::string& param) {
            handleGetCrashdumpEntry(app, req, asyncResp, systemName, param);
          });
}

inline void handleGetCrashdumpFile(
    [[maybe_unused]] App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& logID,
    const std::string& fileName) {
  // Do not call getRedfishRoute here since the crashdump file is not a
  // Redfish resource.

  redfish::system_utils::getSystemInformation(
      asyncResp, systemName,
      [logID, fileName, url(boost::urls::url(req.url()))](
          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
          const std::string& /*systemPath*/) {
        if (!logID.starts_with(kPrimaryCrashdumpPrefix)) {
          messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
          return;
        }
        std::string rawLogID = logID.substr(kPrimaryCrashdumpPrefix.size());

        auto getStoredLogCallback =
            [asyncResp, logID, fileName, url](
                const boost::system::error_code& ec,
                const std::vector<
                    std::pair<std::string, dbus::utility::DbusVariantType>>&
                    resp) {
              if (ec) {
                BMCWEB_LOG_DEBUG << "failed to get log ec: " << ec.message();
                messages::internalError(asyncResp->res);
                return;
              }

              std::string dbusFilename{};
              std::string dbusTimestamp{};
              std::string dbusFilepath{};

              parseCrashdumpParameters(resp, dbusFilename, dbusTimestamp,
                                       dbusFilepath);

              if (dbusFilename.empty() || dbusTimestamp.empty() ||
                  dbusFilepath.empty()) {
                messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
                return;
              }

              // Verify the file name parameter is correct
              if (fileName != dbusFilename) {
                messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
                return;
              }

              if (!std::filesystem::exists(dbusFilepath)) {
                messages::resourceNotFound(asyncResp->res, "LogEntry", logID);
                return;
              }
              std::ifstream ifs(dbusFilepath, std::ios::in | std::ios::binary);
              asyncResp->res.body() =
                  std::string(std::istreambuf_iterator<char>{ifs}, {});

              // Configure this to be a file download when accessed
              // from a browser
              asyncResp->res.addHeader(
                  boost::beast::http::field::content_disposition, "attachment");
            };
        managedStore::ManagedObjectStoreContext context(asyncResp);
        managedStore::GetManagedObjectStore()->getAllProperties(
            crashdumpObject, absl::StrCat(crashdumpPath, "/", rawLogID),
            crashdumpInterface, context, std::move(getStoredLogCallback));
      });
}

void requestRoutesCrashdumpFile(App& app) {
  // Note: Deviated from redfish privilege registry for GET & HEAD
  // method for security reasons.
  BMCWEB_ROUTE(
      app,
      "/redfish/v1/Systems/<str>/LogServices/Crashdump/Entries/<str>/<str>/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetCrashdumpFile, std::ref(app)));
}

enum class OEMDiagnosticType : std::uint8_t {
  onDemand,
  telemetry,
  invalid,
};

inline OEMDiagnosticType getOEMDiagnosticType(std::string_view oemDiagStr) {
  if (oemDiagStr == "OnDemand") {
    return OEMDiagnosticType::onDemand;
  }
  if (oemDiagStr == "Telemetry") {
    return OEMDiagnosticType::telemetry;
  }

  return OEMDiagnosticType::invalid;
}

inline void handlePostCrashdumpCollect(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  if (systemName != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", systemName);
    return;
  }

  std::string diagnosticDataType;
  std::string oemDiagnosticDataType;
  if (!redfish::json_util::readJsonAction(
          req, asyncResp->res, "DiagnosticDataType", diagnosticDataType,
          "OEMDiagnosticDataType", oemDiagnosticDataType)) {
    return;
  }

  if (diagnosticDataType != "OEM") {
    BMCWEB_LOG_ERROR << "Only OEM DiagnosticDataType supported for Crashdump";
    messages::actionParameterValueFormatError(
        asyncResp->res, diagnosticDataType, "DiagnosticDataType",
        "CollectDiagnosticData");
    return;
  }

  OEMDiagnosticType oemDiagType = getOEMDiagnosticType(oemDiagnosticDataType);

  std::string iface;
  std::string method;
  std::string taskMatchStr;
  if (oemDiagType == OEMDiagnosticType::onDemand) {
    iface = crashdumpOnDemandInterface;
    method = "GenerateOnDemandLog";
    if constexpr (bmcwebEnableAmd) {
      taskMatchStr =
          "type='signal',"
          "interface='org.freedesktop.DBus.Properties',"
          "member='PropertiesChanged',"
          "arg0namespace='com.amd.crashdump'";
    } else {
      taskMatchStr =
          "type='signal',"
          "interface='org.freedesktop.DBus.Properties',"
          "member='PropertiesChanged',"
          "arg0namespace='com.intel.crashdump'";
    }
  } else if (oemDiagType == OEMDiagnosticType::telemetry) {
    iface = crashdumpTelemetryInterface;
    method = "GenerateTelemetryLog";
    if constexpr (bmcwebEnableAmd) {
      taskMatchStr =
          "type='signal',"
          "interface='org.freedesktop.DBus.Properties',"
          "member='PropertiesChanged',"
          "arg0namespace='com.amd.crashdump'";
    } else {
      taskMatchStr =
          "type='signal',"
          "interface='org.freedesktop.DBus.Properties',"
          "member='PropertiesChanged',"
          "arg0namespace='com.intel.crashdump'";
    }
  } else {
    BMCWEB_LOG_ERROR << "Unsupported OEMDiagnosticDataType: "
                     << oemDiagnosticDataType;
    messages::actionParameterValueFormatError(
        asyncResp->res, oemDiagnosticDataType, "OEMDiagnosticDataType",
        "CollectDiagnosticData");
    return;
  }

  auto collectCrashdumpCallback = [asyncResp, payload(task::Payload(req)),
                                   taskMatchStr](
                                      const boost::system::error_code& ec,
                                      const std::string&) mutable {
    if (ec) {
      if (ec.value() == boost::system::errc::operation_not_supported) {
        messages::resourceInStandby(asyncResp->res);
      } else if (ec.value() == boost::system::errc::device_or_resource_busy) {
        messages::serviceTemporarilyUnavailable(asyncResp->res, "60");
      } else {
        messages::internalError(asyncResp->res);
      }
      return;
    }
    std::shared_ptr<task::TaskData> task = task::TaskData::createTask(
        [](const boost::system::error_code& err, sdbusplus::message_t&,
           const std::shared_ptr<task::TaskData>& taskData) {
          if (!err) {
            taskData->messages.emplace_back(
                messages::taskCompletedOK(std::to_string(taskData->index)));
            taskData->state = "Completed";
          }
          return task::completed;
        },
        taskMatchStr);

    task->startTimer(std::chrono::minutes(5));
    task->populateResp(asyncResp->res);
    task->payload.emplace(std::move(payload));
  };

  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_, std::move(collectCrashdumpCallback), crashdumpObject,
      crashdumpPath, iface, method);
}

void requestRoutesCrashdumpCollect(App& app) {
  // Note: Deviated from redfish privilege registry for GET & HEAD
  // method for security reasons.
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/Crashdump/Actions/"
               "LogService.CollectDiagnosticData/")
      // The below is incorrect;  Should be ConfigureManager
      // .privileges(redfish::privileges::postLogService)
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handlePostCrashdumpCollect, std::ref(app)));
}

inline void handlePostDBusLogServiceActionsClear(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (systemName != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", systemName);
    return;
  }
  BMCWEB_LOG_DEBUG << "Do delete all entries.";

  // Process response from Logging service.
  auto respHandler = [asyncResp](const boost::system::error_code& ec) {
    BMCWEB_LOG_DEBUG << "doClearLog resp_handler callback: Done";
    if (ec) {
      // TODO Handle for specific error code
      BMCWEB_LOG_ERROR << "doClearLog resp_handler got error " << ec;
      asyncResp->res.result(boost::beast::http::status::internal_server_error);
      return;
    }

    asyncResp->res.result(boost::beast::http::status::no_content);
  };

  // Make call to Logging service to request Clear Log
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_, respHandler, "xyz.openbmc_project.Logging",
      "/xyz/openbmc_project/logging",
      "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
}

/**
 * DBusLogServiceActionsClear class supports POST method for ClearLog action.
 */
void requestRoutesDBusLogServiceActionsClear(App& app) {
  /**
   * Function handles POST method request.
   * The Clear Log actions does not require any parameter.The action deletes
   * all entries found in the Entries collection for this Log Service.
   */

  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/EventLog/Actions/"
               "LogService.ClearLog/")
      .privileges(redfish::privileges::postLogService)
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handlePostDBusLogServiceActionsClear, std::ref(app)));
}

inline void handleGetPostCodesLogService(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  getPostCodeHostContext(
      asyncResp, systemName,
      [](const std::shared_ptr<bmcweb::AsyncResp>& aResp,
         const std::string& sysName, size_t /*hostIndex*/,
         const std::string& /*serviceName*/,
         const std::string& /*objectPath*/) {
        aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Systems", sysName, "LogServices", "PostCodes");
        aResp->res.jsonValue["@odata.type"] = "#LogService.v1_1_0.LogService";
        aResp->res.jsonValue["Name"] = "POST Code Log Service";
        aResp->res.jsonValue["Description"] = "POST Code Log Service";
        aResp->res.jsonValue["Id"] = "PostCodes";
        aResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
        aResp->res.jsonValue["Entries"]["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems", sysName,
                                         "LogServices", "PostCodes", "Entries");

        std::pair<std::string, std::string> redfishDateTimeOffset =
            redfish::time_utils::getDateTimeOffsetNow();
        aResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
        aResp->res.jsonValue["DateTimeLocalOffset"] =
            redfishDateTimeOffset.second;

        aResp->res.jsonValue["Actions"]["#LogService.ClearLog"] = {
            {"target", crow::utility::urlFromPieces(
                           "redfish", "v1", "Systems", sysName, "LogServices",
                           "PostCodes", "Actions", "LogService.ClearLog")}};
      });
}

/****************************************************
 * Redfish PostCode interfaces
 * using DBUS interface: getPostCodesTS
 ******************************************************/
void requestRoutesPostCodesLogService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/PostCodes/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetPostCodesLogService, std::ref(app)));
}

inline void handlePostPostCodesClear(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  getPostCodeHostContext(
      asyncResp, systemName,
      [](const std::shared_ptr<bmcweb::AsyncResp>& aResp,
         const std::string& /*sysName*/, size_t /*hostIndex*/,
         const std::string& serviceName, const std::string& objectPath) {
        BMCWEB_LOG_DEBUG << "Do delete all postcodes entries.";

        // Make call to post-code service to request clear all
        managedStore::GetManagedObjectStore()
            ->PostDbusCallToIoContextThreadSafe(
                aResp->strand_,
                absl::AnyInvocable<void(const boost::system::error_code&)>{
                    [aResp](const boost::system::error_code& ec) {
                      if (ec) {
                        // TODO Handle for specific error code
                        BMCWEB_LOG_ERROR
                            << "doClearPostCodes resp_handler got error " << ec;
                        aResp->res.result(
                            boost::beast::http::status::internal_server_error);
                        messages::internalError(aResp->res);
                        return;
                      }
                      messages::success(aResp->res);
                    }},
                serviceName, objectPath,
                "xyz.openbmc_project.Collection.DeleteAll", "DeleteAll");
      });
}

void requestRoutesPostCodesClear(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/PostCodes/Actions/"
               "LogService.ClearLog/")
      // The following privilege is incorrect;  It should be ConfigureManager
      // .privileges(redfish::privileges::postLogService)
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handlePostPostCodesClear, std::ref(app)));
}

/**
 * @brief Parse post code ID and get the current value and index value
 *        eg: postCodeID=B1-2, currentValue=1, index=2
 *
 * @param[in]  postCodeID     Post Code ID
 * @param[out] currentValue   Current value
 * @param[out] index          Index value
 *
 * @return bool true if the parsing is successful, false the parsing fails
 */
inline static bool parsePostCode(const std::string& postCodeID,
                                 uint64_t& currentValue, uint16_t& index) {
  std::vector<std::string> split;
  bmcweb::split(split, postCodeID, '-');
  if (split.size() != 2 || split[0].length() < 2 || split[0].front() != 'B') {
    return false;
  }

  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
  const char* start = split[0].data() + 1;
  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
  const char* end = split[0].data() + split[0].size();
  auto [ptrIndex, ecIndex] = std::from_chars(start, end, index);

  if (ptrIndex != end || ecIndex != std::errc()) {
    return false;
  }

  start = split[1].data();

  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
  end = split[1].data() + split[1].size();
  auto [ptrValue, ecValue] = std::from_chars(start, end, currentValue);

  return ptrValue == end && ecValue == std::errc();
}

static bool fillPostCodeEntry(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& chassisId, const std::string& systemName,
    const boost::container::flat_map<
        uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>& postcode,
    const uint16_t bootIndex, const uint64_t codeIndex = 0,
    const uint64_t skip = 0, const uint64_t top = 0) {
  // Get the Message from the MessageRegistry
  const registries::Message* message =
      registries::getMessage("OpenBMC.0.2.BIOSPOSTCode");

  uint64_t currentCodeIndex = 0;
  uint64_t firstCodeTimeUs = 0;
  for (const std::pair<uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
           code : postcode) {
    currentCodeIndex++;
    std::string postcodeEntryID =
        "B" + std::to_string(bootIndex) + "-" +
        std::to_string(currentCodeIndex);  // 1 based index in EntryID string

    uint64_t usecSinceEpoch = code.first;
    uint64_t usTimeOffset = 0;

    if (1 == currentCodeIndex) {  // already incremented
      firstCodeTimeUs = code.first;
    } else {
      usTimeOffset = code.first - firstCodeTimeUs;
    }

    // skip if no specific codeIndex is specified and currentCodeIndex does
    // not fall between top and skip
    if ((codeIndex == 0) &&
        (currentCodeIndex <= skip || currentCodeIndex > top)) {
      continue;
    }

    // skip if a specific codeIndex is specified and does not match the
    // currentIndex
    if ((codeIndex > 0) && (currentCodeIndex != codeIndex)) {
      // This is done for simplicity. 1st entry is needed to calculate
      // time offset. To improve efficiency, one can get to the entry
      // directly (possibly with flatmap's nth method)
      continue;
    }

    // currentCodeIndex is within top and skip or equal to specified code
    // index

    // Get the Created time from the timestamp
    std::string entryTimeStr;
    entryTimeStr = redfish::time_utils::getDateTimeUintUs(usecSinceEpoch);

    // assemble messageArgs: BootIndex, TimeOffset(100us), PostCode(hex)
    std::ostringstream hexCode;
    hexCode << "0x" << std::setfill('0') << std::setw(2) << std::hex
            << std::get<0>(code.second);
    std::ostringstream timeOffsetStr;
    // Set Fixed -Point Notation
    timeOffsetStr << std::fixed;
    // Set precision to 4 digits
    timeOffsetStr << std::setprecision(4);
    // Add double to stream
    timeOffsetStr << static_cast<double>(usTimeOffset) / 1000 / 1000;
    std::vector<std::string> messageArgs = {std::to_string(bootIndex),
                                            timeOffsetStr.str(), hexCode.str()};

    // Get MessageArgs template from message registry
    std::string msg;
    if (message != nullptr) {
      msg = message->message;

      // fill in this post code value
      int i = 0;
      for (const std::string& messageArg : messageArgs) {
        std::string argStr = "%" + std::to_string(++i);
        size_t argPos = msg.find(argStr);
        if (argPos != std::string::npos) {
          msg.replace(argPos, argStr.length(), messageArg);
        }
      }
    }

    // Get Severity template from message registry
    std::string severity;
    if (message != nullptr) {
      severity = message->messageSeverity;
    }

    // Format entry
    nlohmann::json::object_t bmcLogEntry;
    bmcLogEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
    bmcLogEntry["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Systems", systemName, "LogServices", "PostCodes",
        "Entries", postcodeEntryID);
    bmcLogEntry["Name"] = "POST Code Log Entry";
    bmcLogEntry["Id"] = postcodeEntryID;
    bmcLogEntry["Message"] = std::move(msg);
    bmcLogEntry["MessageId"] = "OpenBMC.0.2.BIOSPOSTCode";
    bmcLogEntry["MessageArgs"] = std::move(messageArgs);
    bmcLogEntry["EntryType"] = "Event";
    bmcLogEntry["Severity"] = std::move(severity);
    bmcLogEntry["Created"] = entryTimeStr;
    if (!std::get<std::vector<uint8_t>>(code.second).empty()) {
      bmcLogEntry["AdditionalDataURI"] = crow::utility::urlFromPieces(
          "redfish", "v1", "Systems", systemName, "LogServices", "PostCodes",
          "Entries", postcodeEntryID, "attachment");
    }
    // Set PostCode OriginOfCondition to Mobo Chassis to get devpaths
    nlohmann::json::object_t originOfCondition;
    originOfCondition["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId);
    nlohmann::json::object_t links;
    links["OriginOfCondition"] = std::move(originOfCondition);
    bmcLogEntry["Links"] = std::move(links);

    // codeIndex is only specified when querying single entry, return only
    // that entry in this case
    if (codeIndex != 0) {
      aResp->res.jsonValue.update(bmcLogEntry);
      return true;
    }

    nlohmann::json& logEntryArray = aResp->res.jsonValue["Members"];
    logEntryArray.push_back(std::move(bmcLogEntry));
  }

  // Return value is always false when querying multiple entries
  return false;
}

static void getPostCodeForEntry(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                                const std::string& systemName,
                                const std::string& serviceName,
                                const std::string& objectPath,
                                const std::string& entryId) {
  uint16_t bootIndex = 0;
  uint64_t codeIndex = 0;
  if (!parsePostCode(entryId, codeIndex, bootIndex)) {
    // Requested ID was not found
    messages::resourceNotFound(aResp->res, "LogEntry", entryId);
    return;
  }

  if (bootIndex == 0 || codeIndex == 0) {
    // 0 is an invalid index
    messages::resourceNotFound(aResp->res, "LogEntry", entryId);
    return;
  }

  getMainChassisId(aResp, [entryId, bootIndex, codeIndex, systemName,
                           serviceName, objectPath](
                              const std::string& chassisId,
                              const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        aRsp->strand_,
        absl::AnyInvocable<void(
            const boost::system::error_code&,
            const boost::container::flat_map<
                uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&)>{
            [aRsp, chassisId, systemName, entryId, bootIndex, codeIndex](
                const boost::system::error_code& ec,
                const boost::container::flat_map<
                    uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
                    postcode) {
              if (ec) {
                BMCWEB_LOG_DEBUG << "DBUS POST CODE PostCode response error";
                messages::internalError(aRsp->res);
                return;
              }

              if (postcode.empty()) {
                messages::resourceNotFound(aRsp->res, "LogEntry", entryId);
                return;
              }

              if (!fillPostCodeEntry(aRsp, chassisId, systemName, postcode,
                                     bootIndex, codeIndex)) {
                messages::resourceNotFound(aRsp->res, "LogEntry", entryId);
                return;
              }
            }},
        serviceName, objectPath, "xyz.openbmc_project.State.Boot.PostCode",
        "GetPostCodesWithTimeStamp", bootIndex);
  });
}

static void getPostCodeForBoot(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                               const std::string& systemName,
                               const std::string& serviceName,
                               const std::string& objectPath,
                               const uint16_t bootIndex,
                               const uint16_t bootCount,
                               const uint64_t entryCount, size_t skip,
                               size_t top) {
  getMainChassisId(aResp, [systemName, serviceName, objectPath, bootIndex,
                           bootCount, entryCount, skip, top](
                              const std::string& chassisId,
                              const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        aRsp->strand_,
        absl::AnyInvocable<void(
            const boost::system::error_code&,
            const boost::container::flat_map<
                uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&)>{
            [aRsp, chassisId, systemName, serviceName, objectPath, bootIndex,
             bootCount, entryCount, skip,
             top](const boost::system::error_code& ec,
                  const boost::container::flat_map<
                      uint64_t, std::tuple<uint64_t, std::vector<uint8_t>>>&
                      postcode) {
              if (ec) {
                BMCWEB_LOG_DEBUG << "DBUS POST CODE PostCode response error";
                messages::internalError(aRsp->res);
                return;
              }

              uint64_t endCount = entryCount;
              if (!postcode.empty()) {
                endCount = entryCount + postcode.size();
                if (skip < endCount && (top + skip) > entryCount) {
                  uint64_t thisBootSkip =
                      std::max(static_cast<uint64_t>(skip), entryCount) -
                      entryCount;
                  uint64_t thisBootTop =
                      std::min(static_cast<uint64_t>(top + skip), endCount) -
                      entryCount;
                  fillPostCodeEntry(aRsp, chassisId, systemName, postcode,
                                    bootIndex, 0, thisBootSkip, thisBootTop);
                }
                aRsp->res.jsonValue["Members@odata.count"] = endCount;
              }

              // continue to previous bootIndex
              if (bootIndex < bootCount) {
                getPostCodeForBoot(aRsp, systemName, serviceName, objectPath,
                                   static_cast<uint16_t>(bootIndex + 1),
                                   bootCount, endCount, skip, top);
              } else if (skip + top < endCount) {
                aRsp->res.jsonValue["Members@odata.nextLink"] = absl::StrCat(
                    "/redfish/v1/Systems/", systemName,
                    "/LogServices/PostCodes/Entries?$skip=", skip + top);
              }
            }},
        serviceName, objectPath, "xyz.openbmc_project.State.Boot.PostCode",
        "GetPostCodesWithTimeStamp", bootIndex);
  });
}

static void getCurrentBootNumber(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& systemName, const std::string& serviceName,
    const std::string& objectPath, size_t skip, size_t top) {
  uint64_t entryCount = 0;
  managedStore::ManagedObjectStoreContext requestContext(aResp);

  dbus_utils::getProperty<uint16_t>(
      serviceName, objectPath, "xyz.openbmc_project.State.Boot.PostCode",
      "CurrentBootCycleCount", requestContext,
      [aResp, systemName, serviceName, objectPath, entryCount, skip, top](
          const boost::system::error_code& ec, const uint16_t bootCount) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
          messages::internalError(aResp->res);
          return;
        }
        getPostCodeForBoot(aResp, systemName, serviceName, objectPath, 1,
                           bootCount, entryCount, skip, top);
      });
}

inline void handleGetPostCodesEntryCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  query_param::QueryCapabilities capabilities = {
      .canDelegateTop = true,
      .canDelegateSkip = true,
  };
  query_param::Query delegatedQuery;
  if (!redfish::setUpRedfishRouteWithDelegation(app, req, asyncResp,
                                                delegatedQuery, capabilities)) {
    return;
  }

  getPostCodeHostContext(
      asyncResp, systemName,
      [delegatedQuery](const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                       const std::string& sysName, size_t /*hostIndex*/,
                       const std::string& serviceName,
                       const std::string& objectPath) {
        aResp->res.jsonValue["@odata.type"] =
            "#LogEntryCollection.LogEntryCollection";
        aResp->res.jsonValue["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems", sysName,
                                         "LogServices", "PostCodes", "Entries");
        aResp->res.jsonValue["Name"] = "BIOS POST Code Log Entries";
        aResp->res.jsonValue["Description"] =
            "Collection of POST Code Log Entries";
        aResp->res.jsonValue["Members"] = nlohmann::json::array();
        aResp->res.jsonValue["Members@odata.count"] = 0;
        size_t skip = delegatedQuery.skip.value_or(0);
        size_t top = delegatedQuery.top.value_or(query_param::Query::maxTop);
        getCurrentBootNumber(aResp, sysName, serviceName, objectPath, skip,
                             top);
      });
}

void requestRoutesPostCodesEntryCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/")
      .privileges(redfish::privileges::getLogEntryCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetPostCodesEntryCollection, std::ref(app)));
}

inline void handleGetPostCodesEntryAdditionalData(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& postCodeID) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  if (http_helpers::isContentTypeAllowed(req.getHeaderValue("Accept"),
                                         http_helpers::ContentType::OctetStream,
                                         true)) {
    asyncResp->res.result(boost::beast::http::status::bad_request);
    return;
  }

  getPostCodeHostContext(
      asyncResp, systemName,
      [postCodeID](const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                   const std::string& /*sysName*/, size_t /*hostIndex*/,
                   const std::string& serviceName,
                   const std::string& objectPath) {
        uint64_t currentValue = 0;
        uint16_t index = 0;
        if (!parsePostCode(postCodeID, currentValue, index)) {
          messages::resourceNotFound(aResp->res, "LogEntry", postCodeID);
          return;
        }

        managedStore::GetManagedObjectStore()
            ->PostDbusCallToIoContextThreadSafe(
                aResp->strand_,
                absl::AnyInvocable<void(const boost::system::error_code&,
                                        const std::vector<std::tuple<
                                            uint64_t, std::vector<uint8_t>>>&)>{
                    [aResp, postCodeID, currentValue](
                        const boost::system::error_code& ec,
                        const std::vector<std::tuple<
                            uint64_t, std::vector<uint8_t>>>& postcodes) {
                      if (ec.value() == EBADR) {
                        messages::resourceNotFound(aResp->res, "LogEntry",
                                                   postCodeID);
                        return;
                      }
                      if (ec) {
                        BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
                        messages::internalError(aResp->res);
                        return;
                      }

                      size_t value = static_cast<size_t>(currentValue) - 1;
                      if (value == std::string::npos ||
                          postcodes.size() < currentValue) {
                        BMCWEB_LOG_WARNING << "Wrong currentValue value";
                        messages::resourceNotFound(aResp->res, "LogEntry",
                                                   postCodeID);
                        return;
                      }

                      const auto& [tID, c] = postcodes[value];
                      if (c.empty()) {
                        BMCWEB_LOG_WARNING << "No found post code data";
                        messages::resourceNotFound(aResp->res, "LogEntry",
                                                   postCodeID);
                        return;
                      }
                      // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                      const char* d = reinterpret_cast<const char*>(c.data());
                      std::string_view strData(d, c.size());

                      aResp->res.addHeader(
                          boost::beast::http::field::content_type,
                          "application/octet-stream");
                      aResp->res.addHeader(
                          boost::beast::http::field::content_transfer_encoding,
                          "Base64");
                      aResp->res.body() = crow::utility::base64encode(strData);
                    }},
                serviceName, objectPath,
                "xyz.openbmc_project.State.Boot.PostCode", "GetPostCodes",
                index);
      });
}

void requestRoutesPostCodesEntryAdditionalData(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/<str>/"
               "attachment/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleGetPostCodesEntryAdditionalData, std::ref(app)));
}

inline void handleGetPostCodesEntry(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& targetID) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  getPostCodeHostContext(
      asyncResp, systemName,
      [targetID](const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                 const std::string& sysName, size_t /*hostIndex*/,
                 const std::string& serviceName,
                 const std::string& objectPath) {
        getPostCodeForEntry(aResp, sysName, serviceName, objectPath, targetID);
      });
}

void requestRoutesPostCodesEntry(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/PostCodes/Entries/<str>/")
      .privileges(redfish::privileges::getLogEntry)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGetPostCodesEntry, std::ref(app)));
}

static void handleBootTimeLogServiceGet(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_1_0.LogService";
  asyncResp->res.jsonValue["Name"] = "Boot Time Log Service";
  asyncResp->res.jsonValue["Description"] = "Boot Time Log Service";
  asyncResp->res.jsonValue["Id"] = "BootTime";
  asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
  asyncResp->res.jsonValue["LogEntryType"] = "Multiple";

  std::pair<std::string, std::string> redfishDateTimeOffset =
      redfish::time_utils::getDateTimeOffsetNow();
  asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
  asyncResp->res.jsonValue["DateTimeLocalOffset"] =
      redfishDateTimeOffset.second;
}

void handleSystemBootTimeLogServiceGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  // Only for single host
  if (systemName != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", systemName);
    return;
  }
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/BootTime";
  asyncResp->res.jsonValue["Entries"]["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/BootTime/Entries";
  handleBootTimeLogServiceGet(asyncResp);
}

void handleManagerBootTimeLogServiceGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Managers/bmc/LogServices/BootTime";
  asyncResp->res.jsonValue["Entries"]["@odata.id"] =
      "/redfish/v1/Managers/bmc/LogServices/BootTime/Entries";
  handleBootTimeLogServiceGet(asyncResp);
}

void requestRoutesBootTimeLogService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/BootTime/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleSystemBootTimeLogServiceGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/BootTime/")
      .privileges(redfish::privileges::getLogService)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleManagerBootTimeLogServiceGet, std::ref(app)));
}

inline static std::string generateBootTimeLogId(
    BootTimeDataType diagnosticsDataType, const size_t index) {
  return bootTimeDataTypeToString(diagnosticsDataType) + std::to_string(index);
}

static std::shared_ptr<nlohmann::json::object_t> makeBootTimeLogEntry(
    BootTimeDataType diagnosticsDataType,
    const nlohmann::json::object_t& diagnosticDataJson, const size_t index,
    const std::string& parentODataId) {
  nlohmann::json::object_t logEntry;
  const std::string id = generateBootTimeLogId(diagnosticsDataType, index);
  // required properties start
  logEntry["@odata.id"] = parentODataId + "/" + id;
  logEntry["@odata.type"] = "#LogEntry.v1_15_0.LogEntry";
  logEntry["Name"] = "Boot Time Log Entry";
  logEntry["Id"] = id;
  logEntry["EntryType"] = "Oem";
  // required properties end
  logEntry["OEMDiagnosticDataType"] =
      bootTimeDataTypeToString(diagnosticsDataType);
  std::string jsonStr = nlohmann::json(diagnosticDataJson).dump();
  logEntry["Message"] = jsonStr;
  const std::string base64DiagnosticData = crow::utility::base64encode(jsonStr);
  logEntry["DiagnosticData"] = base64DiagnosticData;
  return std::make_shared<nlohmann::json::object_t>(logEntry);
}

static void getBootTimeCheckpointLogEntries(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& host,
    const std::shared_ptr<const std::string>& parentODataId,
    const std::shared_ptr<size_t>& specificIndex,
    const std::function<void(const nlohmann::json& logEntryArray)>&
        successCallback) {
#ifdef UNIT_TEST_BUILD
  dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
      managedStore::GetManagedObjectStore())
      ->PostDbusCallToIoContextThreadSafe(
#else
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
#endif
          aResp->strand_,
          [aResp, parentODataId, specificIndex, successCb{successCallback}](
              const boost::system::error_code& ec,
              const std::vector<BootTimeCheckpoint>& checkpoints) {
            if (ec) {
              BMCWEB_LOG_DEBUG << "DBUS Boot Time checkpoints response error";
              messages::internalError(aResp->res);
              return;
            }
            std::span<const BootTimeCheckpoint> filteredCheckpoints;
            if (specificIndex != nullptr) {
              const size_t index = *specificIndex;
              if (index >= checkpoints.size()) {
                messages::resourceNotFound(
                    aResp->res, "LogEntry",
                    generateBootTimeLogId(BootTimeDataType::CHECKPOINT, index));
                return;
              }
              filteredCheckpoints = std::span<const BootTimeCheckpoint>(
                  std::next(checkpoints.begin(), static_cast<int>(index)),
                  std::next(checkpoints.begin(), static_cast<int>(index + 1)));
            } else {
              filteredCheckpoints =
                  std::span<const BootTimeCheckpoint>(checkpoints);
            }
            nlohmann::json logEntryArray = nlohmann::json::array();
            size_t currentIndex = specificIndex == nullptr ? 0 : *specificIndex;
            for (const BootTimeCheckpoint& checkpoint : filteredCheckpoints) {
              const auto [name, wallTime, monoTime] = checkpoint;
              nlohmann::json::object_t diagnosticDataJson;
              diagnosticDataJson["Name"] = name;
              diagnosticDataJson["WallTimeMs"] = wallTime;
              diagnosticDataJson["MonoTimeMs"] = monoTime;
              try {
                std::shared_ptr<nlohmann::json::object_t> logEntry =
                    makeBootTimeLogEntry(BootTimeDataType::CHECKPOINT,
                                         diagnosticDataJson, currentIndex,
                                         *parentODataId);
                logEntryArray.push_back(std::move(*logEntry));
              } catch (...) {
                // May face error while parsing data to json or to base64
                BMCWEB_LOG_DEBUG
                    << "Error while making Boot time log entry for Checkpoint"
                    << std::to_string(currentIndex);
                messages::internalError(aResp->res);
                return;
              }
              currentIndex++;
            }
            successCb(logEntryArray);
          },
          "com.google.gbmc.boot_time_monitor",
          "/xyz/openbmc_project/time/boot/" + host,
          "xyz.openbmc_project.Time.Boot.Checkpoint", "GetCheckpointList");
}

static void getBootTimeDurationLogEntries(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& host,
    const std::shared_ptr<const std::string>& parentODataId,
    const std::shared_ptr<size_t>& specificIndex,
    const std::function<void(const nlohmann::json& logEntryArray)>&
        successCallback) {
#ifdef UNIT_TEST_BUILD
  dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
      managedStore::GetManagedObjectStore())
      ->PostDbusCallToIoContextThreadSafe(
#else
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
#endif
          aResp->strand_,
          [aResp, parentODataId, specificIndex, successCb{successCallback}](
              const boost::system::error_code& ec,
              const std::vector<BootTimeDuration>& durations) {
            if (ec) {
              BMCWEB_LOG_DEBUG << "DBUS Boot Time durations response error";
              messages::internalError(aResp->res);
              return;
            }
            std::span<const BootTimeDuration> filteredDurations;
            if (specificIndex != nullptr) {
              const size_t index = *specificIndex;
              if (index >= durations.size()) {
                messages::resourceNotFound(
                    aResp->res, "LogEntry",
                    generateBootTimeLogId(BootTimeDataType::DURATION, index));
                return;
              }
              filteredDurations = std::span<const BootTimeDuration>(
                  std::next(durations.begin(), static_cast<int>(index)),
                  std::next(durations.begin(), static_cast<int>(index + 1)));
            } else {
              filteredDurations = std::span<const BootTimeDuration>(durations);
            }
            nlohmann::json logEntryArray = nlohmann::json::array();
            size_t currentIndex = specificIndex == nullptr ? 0 : *specificIndex;
            for (const BootTimeDuration& duration : filteredDurations) {
              nlohmann::json::object_t diagnosticDataJson;
              const auto [name, durationMs] = duration;
              diagnosticDataJson["Name"] = name;
              diagnosticDataJson["DurationMs"] = durationMs;
              try {
                std::shared_ptr<nlohmann::json::object_t> logEntry =
                    makeBootTimeLogEntry(BootTimeDataType::DURATION,
                                         diagnosticDataJson, currentIndex,
                                         *parentODataId);
                logEntryArray.push_back(std::move(*logEntry));
              } catch (...) {
                // May face error while parsing data to json or to base64
                BMCWEB_LOG_DEBUG
                    << "Error while making Boot time log entry for Duration"
                    << std::to_string(currentIndex);
                messages::internalError(aResp->res);
                return;
              }
              currentIndex++;
            }
            successCb(logEntryArray);
          },
          "com.google.gbmc.boot_time_monitor",
          "/xyz/openbmc_project/time/boot/" + host,
          "xyz.openbmc_project.Time.Boot.Duration", "GetAdditionalDurations");
}

static void getBootTimeStatisticLogEntry(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& host,
    const std::shared_ptr<const std::string>& parentODataId,
    const std::function<void(const nlohmann::json& logEntryArray)>&
        successCallback) {
  managedStore::ManagedObjectStoreContext requestContext(aResp);
  dbus_utils::getProperty<bool>(
      "com.google.gbmc.boot_time_monitor",
      "/xyz/openbmc_project/time/boot/" + host,
      "xyz.openbmc_project.Time.Boot.Statistic", "IsRebooting", requestContext,
      [aResp, parentODataId, successCb{successCallback}](
          const boost::system::error_code& ec, const bool rebooting) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "DBUS Boot Time rebooting response error" << ec;
          messages::internalError(aResp->res);
          return;
        }
        nlohmann::json logEntryArray = nlohmann::json::array();
        nlohmann::json::object_t diagnosticDataJson;
        diagnosticDataJson["IsRebooting"] = rebooting;
        try {
          std::shared_ptr<nlohmann::json::object_t> logEntry =
              makeBootTimeLogEntry(BootTimeDataType::STATISTIC,
                                   diagnosticDataJson, 0, *parentODataId);
          logEntryArray.push_back(std::move(*logEntry));
        } catch (...) {
          // May face error while parsing data to json or to base64
          BMCWEB_LOG_DEBUG
              << "Error while making Boot time log entry for Statistic0";
          messages::internalError(aResp->res);
          return;
        }
        successCb(logEntryArray);
      });
}

inline void addBootLogEntriesToRespAndCount(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const nlohmann::json& logEntryArray) {
  for (auto entry : logEntryArray) {
    asyncResp->res.jsonValue["Members"].push_back(std::move(entry));
  }
  asyncResp->res.jsonValue["Members@odata.count"] =
      asyncResp->res.jsonValue["Members"].size();
}

inline void handleBootTimeLogsEntryCollectionGet(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& host) {
  asyncResp->res.jsonValue["@odata.type"] =
      "#LogEntryCollection.LogEntryCollection";
  asyncResp->res.jsonValue["Name"] = "Boot Time Log Entries";
  asyncResp->res.jsonValue["Description"] =
      "Collection of Boot time Log Entries with checkpoints and duration";

  std::shared_ptr<const std::string> parentId =
      std::make_shared<const std::string>(
          asyncResp->res.jsonValue["@odata.id"]);
  asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
  getBootTimeCheckpointLogEntries(
      asyncResp, host, parentId, nullptr,
      std::bind_front(addBootLogEntriesToRespAndCount, asyncResp));
  getBootTimeDurationLogEntries(
      asyncResp, host, parentId, nullptr,
      std::bind_front(addBootLogEntriesToRespAndCount, asyncResp));
  getBootTimeStatisticLogEntry(
      asyncResp, host, parentId,
      std::bind_front(addBootLogEntriesToRespAndCount, asyncResp));
}

void handleSystemBootTimeLogsEntryCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  // only for single host
  if (systemName != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", systemName);
    return;
  }

  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Systems/" + systemName + "/LogServices/BootTime/Entries";
  handleBootTimeLogsEntryCollectionGet(asyncResp, "host0");
}

void handleManagerBootTimeLogsEntryCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Managers/bmc/LogServices/BootTime/Entries";
  handleBootTimeLogsEntryCollectionGet(asyncResp, "bmc");
}

void requestRoutesBootTimeLogEntryCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/BootTime/Entries/")
      .privileges(redfish::privileges::getLogEntryCollection)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleSystemBootTimeLogsEntryCollectionGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/BootTime/Entries/")
      .privileges(redfish::privileges::getLogEntryCollection)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleManagerBootTimeLogsEntryCollectionGet, std::ref(app)));
}

static bool parseBootTimeLogEntryId(const std::string& entryId,
                                    BootTimeDataType& dataType, size_t& index) {
  size_t typeIndex = 0;
  for (const std::string_view type : bootTimeDataTypeString) {
    if (entryId.starts_with(type.data())) {
      // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
      auto [_, ec] = std::from_chars(entryId.c_str() + type.length(),
                                     entryId.c_str() + entryId.length(), index);
      // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
      // calling std::errc without any argument means successful parse
      if (ec != std::errc()) {
        return false;
      }
      dataType = static_cast<BootTimeDataType>(typeIndex);
      return (dataType != BootTimeDataType::STATISTIC || index == 0);
    }
    typeIndex++;
  }
  return false;
}

inline void mergeBootLogEntryToResp(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::shared_ptr<const std::string>& entryId,
    const nlohmann::json& logEntryArray) {
  if (asyncResp->res.jsonValue.contains("error")) {
    return;
  }
  if (logEntryArray.empty()) {
    messages::resourceNotFound(asyncResp->res, "LogEntry", *entryId);
    return;
  }
  asyncResp->res.jsonValue.merge_patch(logEntryArray[0]);
}

inline void handleBootTimeLogsEntryGet(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& host, const std::string& entryId,
    const std::string& parentODataId) {
  BootTimeDataType dataType = BootTimeDataType::CHECKPOINT;
  size_t index = 0;
  if (!parseBootTimeLogEntryId(entryId, dataType, index)) {
    messages::resourceNotFound(asyncResp->res, "LogEntry", entryId);
    return;
  }
  std::shared_ptr<const std::string> parentId =
      std::make_shared<const std::string>(parentODataId);
  std::shared_ptr<const std::string> entryIdPtr =
      std::make_shared<const std::string>(entryId);
  std::shared_ptr<size_t> indexPt = std::make_shared<size_t>(index);
  if (dataType == BootTimeDataType::CHECKPOINT) {
    getBootTimeCheckpointLogEntries(
        asyncResp, host, parentId, indexPt,
        std::bind_front(mergeBootLogEntryToResp, asyncResp, entryIdPtr));
  } else if (dataType == BootTimeDataType::DURATION) {
    getBootTimeDurationLogEntries(
        asyncResp, host, parentId, indexPt,
        std::bind_front(mergeBootLogEntryToResp, asyncResp, entryIdPtr));
  } else {
    getBootTimeStatisticLogEntry(
        asyncResp, host, parentId,
        std::bind_front(mergeBootLogEntryToResp, asyncResp, entryIdPtr));
  }
}

void handleSystemBootTimeLogsEntryGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& entryId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  // only for single host
  if (systemName != "system") {
    messages::resourceNotFound(asyncResp->res, "ComputerSystem", systemName);
    return;
  }
  handleBootTimeLogsEntryGet(
      asyncResp, "host0", entryId,
      "/redfish/v1/Systems/" + systemName + "/LogServices/BootTime/Entries");
}
void handleManagerBootTimeLogsEntryGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& entryId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  handleBootTimeLogsEntryGet(
      asyncResp, "bmc", entryId,
      "/redfish/v1/Managers/bmc/LogServices/BootTime/Entries");
}

void requestRoutesBootTimeLogEntry(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/<str>/LogServices/BootTime/Entries/<str>")
      .privileges(redfish::privileges::getLogEntryCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleSystemBootTimeLogsEntryGet, std::ref(app)));

  BMCWEB_ROUTE(app,
               "/redfish/v1/Managers/bmc/LogServices/BootTime/Entries/<str>")
      .privileges(redfish::privileges::getLogEntryCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleManagerBootTimeLogsEntryGet, std::ref(app)));
}

void handlePPRServiceGet(App& app, const crow::Request& req,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  // Copy over the static data to include the entries added by SubRoute
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair";
  asyncResp->res.jsonValue["@odata.type"] = "#LogService.v1_2_0.LogService";
  asyncResp->res.jsonValue["Name"] = "Open BMC Oem PPR Service";
  asyncResp->res.jsonValue["Description"] = "Oem Post Package Repair Service";
  asyncResp->res.jsonValue["Id"] = "Oem ppr";
  asyncResp->res.jsonValue["OverWritePolicy"] = "WrapsWhenFull";
  asyncResp->res.jsonValue["Members"] = {
      {{"@odata.id",
        "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair/"
        "Config"}},
      {{"@odata.id",
        "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair/"
        "Status"}},
  };
  asyncResp->res.jsonValue["Members@odata.count"] =
      asyncResp->res.jsonValue["Members"].size();
  asyncResp->res.jsonValue["Actions"] = {
      {"#PostPackageRepair.SetRepairConfig",
       {{"target",
         "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair/"
         "Actions/PostPackageRepair.SetRepairConfig"}}},
      {"#PostPackageRepair.SetRepairData",
       {{"target",
         "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair/"
         "Actions/PostPackageRepair.SetRepairData"}}}};
}

void getPostPackageRepairStatus(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      requestContext.GetStrand(),
      [asyncResp](
          const boost::system::error_code& ec,
          const std::vector<std::tuple<uint16_t, uint16_t, uint16_t, uint16_t,
                                       std::vector<uint16_t>>>&
              postpackagerepairstatus) {
        if (ec) {
          BMCWEB_LOG_ERROR
              << "DBUS response error in getPostPackageRepairStatus"
              << ec.message();
          messages::internalError(asyncResp->res);
          return;
        }

        BMCWEB_LOG_DEBUG << "D-Bus getPostPackageRepairStatus success size : "
                         << postpackagerepairstatus.size();

        nlohmann::json pprDataOut = nlohmann::json::array();
        int count = 0;
        for (const auto& resolveList : postpackagerepairstatus) {
          BMCWEB_LOG_INFO << "Testing : " << std::get<0>(resolveList);
          uint16_t repairEntryNum = std::get<0>(resolveList);
          uint16_t repairType = std::get<1>(resolveList);
          uint16_t socNum = std::get<2>(resolveList);
          uint16_t repairResult = std::get<3>(resolveList);
          std::vector<uint16_t> payload = std::get<4>(resolveList);

          nlohmann::json jsonPpr = {{"repairEntryNum", repairEntryNum},
                                    {"repairType", repairType},
                                    {"socNum", socNum},
                                    {"repairResult", repairResult},
                                    {"payload", payload}};
          pprDataOut.push_back(jsonPpr);
          count++;
        }

        asyncResp->res.jsonValue["Members"] = pprDataOut;
        asyncResp->res.jsonValue["Members@odata.count"] = count;
      },
      pprFileObject, pprFilePath, pprFileInterface,
      "getPostPackageRepairStatus");
}

void handlePPRStatusGet(App& app, const crow::Request& req,
                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.type"] = "#LogEntry.v1_4_0.LogEntry";
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair/"
      "Status";
  asyncResp->res.jsonValue["Name"] = "Post Package Repair Entries";
  asyncResp->res.jsonValue["Description"] =
      "Collection of Post Package Repair Entries";
  asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
  asyncResp->res.jsonValue["Members@odata.count"] = 0;

  getPostPackageRepairStatus(asyncResp);
}

void setPostPackageRepairData(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const uint16_t Index,
    const uint16_t repairEntryNum, const uint16_t repairType,
    const uint16_t socNum, std::vector<uint16_t>& payload) {
  std::optional<bool> RecordAdd = true;
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      requestContext.GetStrand(),
      [asyncResp, RecordAdd, Index, requestContext](
          const boost::system::error_code& ec, const bool& recordAdd) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS POST Package Repair Record Add error";
          messages::internalError(asyncResp->res);
          return;
        }
        BMCWEB_LOG_DEBUG << "DBUS POST Package Repair Record Added : "
                         << int(recordAdd);

        managedStore::GetManagedObjectStore()->setProperty(
            pprFileObject, pprFilePath, pprFileInterface, "RecordAdd",
            *RecordAdd,
            [asyncResp, Index,
             requestContext](const boost::system::error_code& ec) {
              if (ec) {
                BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
                messages::internalError(asyncResp->res);
                return;
              }
              BMCWEB_LOG_INFO << "D-Bus Record Add success";

              managedStore::GetManagedObjectStore()
                  ->PostDbusCallToIoContextThreadSafe(
                      requestContext.GetStrand(),
                      [asyncResp](const boost::system::error_code& ec,
                                  const uint32_t& startRuntimeRepair) {
                        if (ec) {
                          BMCWEB_LOG_ERROR << "DBUS start Runtime Repair error";
                          messages::internalError(asyncResp->res);
                          return;
                        }
                        BMCWEB_LOG_INFO
                            << "DBUS success start Runtime Repair : "
                            << startRuntimeRepair;
                      },
                      pprFileObject, pprFilePath, pprFileInterface,
                      "startRuntimeRepair", Index);
            });
      },
      pprFileObject, pprFilePath, pprFileInterface, "setPostPackageRepairData",
      repairEntryNum, repairType, socNum, payload);
}

static bool& getOobPprEnable() {
  static bool oobPprEnable = false;
  return oobPprEnable;
}

void handlePPRFilePost(App& app, const crow::Request& req,
                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  uint16_t RepairType = 0;
  uint16_t RepairEntryNum = 0;
  uint16_t SocNum = 0;
  uint16_t Index = 0;
  uint16_t RuntimeIndex = 0;
  nlohmann::json jsonRequest;
  bool& oobPprEnable = getOobPprEnable();

  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  dbus_utils::getProperty<bool>(
      pprFileObject, pprFilePath, pprFileInterface, "oobPprEnable",
      requestContext,
      [asyncResp, &oobPprEnable](const boost::system::error_code& ec,
                                 const bool oobPpr) {
        if (ec) {
          BMCWEB_LOG_ERROR << "D-Bus responses error for OOB PPR Enable: "
                           << ec;
          messages::internalError(asyncResp->res);
          return;
        }
        oobPprEnable = oobPpr;
      });

  if (!oobPprEnable) {
    BMCWEB_LOG_ERROR << "Error: OOB PPR is Not Enabled";
    messages::internalError(asyncResp->res);
    return;
  }

  if (!json_util::processJsonFromRequest(asyncResp->res, req, jsonRequest)) {
    BMCWEB_LOG_ERROR << "Error: Json value not readable";
    messages::malformedJSON(asyncResp->res);
    return;
  }

  for (const auto& el : jsonRequest["pprDataIn"].items()) {
    std::vector<uint16_t> Payload;

    BMCWEB_LOG_DEBUG << "Key " << el.key();
    BMCWEB_LOG_DEBUG << "value " << el.value();

    if (!json_util::readJson(el.value(), asyncResp->res, "RepairType",
                             RepairType, "RepairEntryNum", RepairEntryNum,
                             "SocNum", SocNum, "Payload", Payload)) {
      BMCWEB_LOG_ERROR << "Error: Issue with Json value read";
      messages::malformedJSON(asyncResp->res);
      return;
    }

    if ((RepairType & kPPRTypeBoottimeMask) == 0) {
      RuntimeIndex++;
      if (RuntimeIndex > kMaxRuntimePPRCount) {
        BMCWEB_LOG_ERROR << "Error: Exceed Runtime PPR Max Entry of "
                         << kMaxRuntimePPRCount;
        messages::invalidObject(asyncResp->res,
                                "Runtime PPR entries exceed PPR Max Entry of " +
                                    std::to_string(kMaxRuntimePPRCount));
        return;
      }
    }

    setPostPackageRepairData(asyncResp, Index, RepairEntryNum, RepairType,
                             SocNum, Payload);
    Index++;
  }

  messages::success(asyncResp->res);
}

void getPostPackageRepairConfig(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp) {
  managedStore::ManagedObjectStoreContext requestContext(aResp);
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      requestContext.GetStrand(),
      [aResp](const boost::system::error_code& ec,
              const std::vector<uint16_t>& postpackagerepairconfig) {
        if (ec) {
          BMCWEB_LOG_ERROR
              << "DBUS response error in getPostPackageRepairConfig"
              << ec.message();
          messages::internalError(aResp->res);
          return;
        }

        nlohmann::json pprConfig = nlohmann::json::array();

        bool RtToBt = false;
        bool BtSetToHard = false;
        bool& oobPprEnable = getOobPprEnable();

        oobPprEnable = (postpackagerepairconfig[0] != 0);
        RtToBt = (postpackagerepairconfig[1] != 0);
        BtSetToHard = (postpackagerepairconfig[2] != 0);

        nlohmann::json jsonPpr = {{"OobPprEnable", oobPprEnable},
                                  {"autoScheduleRtAsBtPpr", RtToBt},
                                  {"autoScheduleBtAsHard", BtSetToHard}};
        pprConfig.push_back(jsonPpr);

        aResp->res.jsonValue["Members"] = pprConfig;
        aResp->res.jsonValue["Members@odata.count"] = 1;
      },
      pprFileObject, pprFilePath, pprFileInterface,
      "getPostPackageRepairConfig");
}

void setPostPackageRepairConfig(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const uint16_t& flag,
    const bool& data) {
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      requestContext.GetStrand(),
      [asyncResp](const boost::system::error_code& ec, const bool& result) {
        if (ec) {
          BMCWEB_LOG_ERROR
              << "DBUS response error in setPostPackageRepairConfig"
              << ec.message();
          messages::internalError(asyncResp->res);
          return;
        }
        BMCWEB_LOG_DEBUG << "DBUS POST Package Repair Config Changed : "
                         << int(result);
      },
      pprFileObject, pprFilePath, pprFileInterface,
      "setPostPackageRepairConfig", flag, data);
}

void handlePPRConfigGet(App& app, const crow::Request& req,
                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.type"] = "#LogEntry.v1_4_0.LogEntry";
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair/"
      "Config";
  asyncResp->res.jsonValue["Name"] = "Post Package Repair Config";
  asyncResp->res.jsonValue["Description"] = "Post Package Repair Configuration";
  asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
  asyncResp->res.jsonValue["Members@odata.count"] = 0;

  getPostPackageRepairConfig(asyncResp);
}

void handlePPRConfigPost(App& app, const crow::Request& req,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  std::optional<bool> BtSetToHard;
  std::optional<bool> RtToBt;
  uint16_t flag = 0;
  bool data = false;
  nlohmann::json jsonRequest;

  if (!json_util::processJsonFromRequest(asyncResp->res, req, jsonRequest)) {
    BMCWEB_LOG_ERROR << "Error: Json value not readable";
    messages::malformedJSON(asyncResp->res);
    return;
  }

  if (!json_util::readJson(jsonRequest, asyncResp->res, "autoScheduleBtAsHard",
                           BtSetToHard, "autoScheduleRtAsBtPpr", RtToBt)) {
    return;
  }
  if (BtSetToHard) {
    flag = kBtSetToHardMask;
    data = BtSetToHard.value();
  }
  if (RtToBt) {
    flag = kRtToBtMask;
    data = RtToBt.value();
  }
  if (flag == 0) {
    std::cout << "PPR Config Error: post command, Param not found\n";
    return;
  }
  setPostPackageRepairConfig(asyncResp, flag, data);
  messages::success(asyncResp->res);
}

void requestRoutesPPRService(App& app) {
  BMCWEB_ROUTE(
      app, "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair/")
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handlePPRServiceGet, std::ref(app)));
}

void requestRoutesPPRStatus(App& app) {
  BMCWEB_ROUTE(
      app,
      "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair/Status")
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handlePPRStatusGet, std::ref(app)));
}

void requestRoutesPPRFile(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/system/LogServices/Oem/Amd/"
               "PostPackageRepair/Actions/PostPackageRepair.SetRepairData")
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handlePPRFilePost, std::ref(app)));
}

void requestRoutesPPRConfig(App& app) {
  BMCWEB_ROUTE(
      app,
      "/redfish/v1/Systems/system/LogServices/Oem/Amd/PostPackageRepair/Config")
      .privileges({{"ConfigureComponents"}})
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handlePPRConfigGet, std::ref(app)));
  BMCWEB_ROUTE(app,
               "/redfish/v1/Systems/system/LogServices/Oem/Amd/"
               "PostPackageRepair/Actions/PostPackageRepair.SetRepairConfig")
      .privileges({{"ConfigureManager"}})
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handlePPRConfigPost, std::ref(app)));
}

}  // namespace redfish
