#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_REDFISH_AGGREGATOR_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_REDFISH_AGGREGATOR_H_

#include <algorithm>
#include <array>
#include <chrono>  // NOLINT
#include <cstddef>
#include <cstdint>
#include <functional>
#include <limits>
#include <memory>
#include <random>
#include <string>
#include <string_view>
#include <system_error>  // NOLINT
#include <unordered_map>
#include <utility>
#include <variant>

#include "boost/algorithm/string/predicate.hpp"  // NOLINT
#include "boost/url/parse.hpp"  // NOLINT
#include "boost/url/url.hpp"  // NOLINT
#include "bmcweb_config.h"
#include "http_client.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "utility.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "request_stats.hpp"
#include "aggregation_utils.hpp"
#include "error_messages.hpp"
#include <nlohmann/json.hpp>
#include "managed_store.hpp"
#include "managed_store_types.hpp"

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

namespace redfish {

constexpr unsigned int aggregatorReadBodyLimit = 50 * 1024 * 1024;  // 50MB

enum class Result : std::uint8_t { LocalHandle, NoLocalHandle };

enum class SearchType : std::uint8_t {
  Collection,
  CollOrCon,
  ContainsSubordinate,
  Resource
};

struct RdeSatelliteConfig {
  std::string name;
  std::string vid;
  std::string udevid;
  std::string usbport;
  std::string objectpath;
};

// clang-format off
// These are all of the properties as of version 2022.2 of the Redfish Resource
// and Schema Guide whose Type is "string (URI)" and the name does not end in a
// case-insensitive form of "uri".  That version of the schema is associated
// with version 1.16.0 of the Redfish Specification.  Going forward, new URI
// properties should end in URI so this list should not need to be maintained as
// the spec is updated.  NOTE: These have been pre-sorted in order to be
// compatible with binary search
constexpr std::array nonUriProperties{
    "@Redfish.ActionInfo",
    // "@odata.context", // We can't fix /redfish/v1/$metadata URIs
    "@odata.id",
    // "Destination", // Only used by EventService and won't be a Redfish URI
    // "HostName", // Isn't actually a Redfish URI
    "Image",
    "MetricProperty",
    // "OriginOfCondition", // Is URI when in request, but is object in response
    "TaskMonitor",
    "target",  // normal string, but target URI for POST to invoke an action
};
// clang-format on

// Search the top collection array to determine if the passed URI is of a
// desired type
inline bool searchCollectionsArray(std::string_view uri,
                                   const SearchType searchType) {
  boost::system::result<boost::urls::url> parsedUrl =
      boost::urls::parse_relative_ref(uri);

  if (!parsedUrl) {
    BMCWEB_LOG_ERROR << "Failed to get target URI from " << uri;
    return false;
  }

  parsedUrl->normalize();
  boost::urls::segments_ref segments = parsedUrl->segments();
  if (!segments.is_absolute()) {
    return false;
  }

  // The passed URI must begin with "/redfish/v1", but we have to strip it
  // from the URI since topCollections does not include it in its URIs.
  if (segments.size() < 2) {
    return false;
  }
  if (segments.front() != "redfish") {
    return false;
  }
  segments.erase(segments.begin());
  if (segments.front() != "v1") {
    return false;
  }
  segments.erase(segments.begin());

  // Exclude the trailing "/" if it exists such as in "/redfish/v1/".
  if (!segments.empty() && segments.back().empty()) {
    segments.pop_back();
  }

  // If no segments then the passed URI was either "/redfish/v1" or
  // "/redfish/v1/".
  if (segments.empty()) {
    return (searchType == SearchType::ContainsSubordinate) ||
           (searchType == SearchType::CollOrCon);
  }
  std::string_view url = segments.buffer();
  const auto* it = std::ranges::lower_bound(topCollections, url);  // NOLINT
  if (it == topCollections.end()) {
    // parsedUrl is alphabetically after the last entry in the array so it
    // can't be a top collection or up tree from a top collection
    return false;
  }

  boost::urls::url collectionUrl(*it);
  boost::urls::segments_view collectionSegments = collectionUrl.segments();
  boost::urls::segments_view::iterator itCollection =
      collectionSegments.begin();
  const boost::urls::segments_view::const_iterator endCollection =
      collectionSegments.end();

  // Each segment in the passed URI should match the found collection
  for (const auto& segment : segments) {
    if (itCollection == endCollection) {
      // Leftover segments means the target is for an aggregation
      // supported resource
      return searchType == SearchType::Resource;
    }

    if (segment != (*itCollection)) {
      return false;
    }
    itCollection++;
  }

  // No remaining segments means the passed URI was a top level collection
  if (searchType == SearchType::Collection) {
    return itCollection == endCollection;
  }
  if (searchType == SearchType::ContainsSubordinate) {
    return itCollection != endCollection;
  }

  // Return this check instead of "true" in case other SearchTypes get added
  return searchType == SearchType::CollOrCon;
}

// Strip query params which are incompatible with aggregation.
// Note, this still doesn't work for collections that might return less than the
// complete collection by default, but hopefully those are rare/nonexistent in
// top collections.  bmcweb doesn't implement any of these.
inline void parameterRemove(crow::Request& localReq) {
  boost::urls::url& urlNew = localReq.mutableUrl();
  auto paramsIt = urlNew.params().begin();
  bool foundSkip = false;
  while (paramsIt != urlNew.params().end()) {
    const boost::urls::param& param = *paramsIt;

    // Plugins will not apply correctly to resources pulled in by offloading
    // $expand to a satellite BMC.  Don't forward $expand in that case.
    if constexpr (enablePlatform22) {
      if (param.key == "$expand") {
        BMCWEB_LOG_DEBUG << "Erasing $expand from forwarded request";
        paramsIt = urlNew.params().erase(paramsIt);
        continue;
      }
    }

    // By the spec, no other params should be provided with only. Don't
    // forward any params and let the aggregating BMC handle them.
    if (param.key == "only") {
      BMCWEB_LOG_DEBUG
          << "Erasing all params from request to top level collection";
      urlNew.params().clear();
      foundSkip = false;
      break;
    }

    if (param.key == "$skip") {
      foundSkip = true;
    }
    paramsIt++;
  }

  if (foundSkip) {
    // Remove $skip and any other param that is supposed to processed after
    // it.  Applying $skip twice would produce different results.
    // Forwarding just the non-$skip params would result in partially
    // processing the params in the wrong order.
    paramsIt = urlNew.params().begin();
    while (paramsIt != urlNew.params().end()) {
      const boost::urls::param& param = *paramsIt;
      // According to the Redfish spec, $filter is the only param that is
      // processed before $skip and is thus safe to be forwarded. All
      // others need to be removed
      if (param.key != "$filter") {
        BMCWEB_LOG_DEBUG << "Erasing \"" << param.key
                         << "\" param from request to top level collection";
        paramsIt = urlNew.params().erase(paramsIt);
        continue;
      }
      // Pass $filter parameter
      paramsIt++;
    }
  }
  localReq.target(urlNew.buffer());
}

// Determines if the passed property contains a URI.  Those property names
// either end with a case-insensitive version of "uri" or are specifically
// defined in the above array.
inline bool isPropertyUri(std::string_view propertyName) {
  return boost::iends_with(propertyName, "uri") ||
         std::binary_search(nonUriProperties.begin(), nonUriProperties.end(),
                            propertyName);
}

static inline void addPrefixToStringItem(std::string& strValue,
                                         std::string_view prefix) {
  // Make sure the value is a properly formatted URI
  auto parsed = boost::urls::parse_relative_ref(strValue);
  if (!parsed) {
    BMCWEB_LOG_CRITICAL << "Couldn't parse URI from resource " << strValue;
    return;
  }

  boost::urls::url_view thisUrl = *parsed;

  // We don't need to aggregate JsonSchemas due to potential issues such as
  // version mismatches between aggregator and satellite BMCs.  For now
  // assume that the aggregator has all the schemas and versions that the
  // aggregated server has.
  if (crow::utility::readUrlSegments(thisUrl, "redfish", "v1", "JsonSchemas",
                                     crow::utility::OrMorePaths())) {
    BMCWEB_LOG_DEBUG << "Skipping JsonSchemas URI prefix fixing";
    return;
  }

  // The first two segments should be "/redfish/v1".  We need to check that
  // before we can search topCollections
  if (!crow::utility::readUrlSegments(thisUrl, "redfish", "v1",
                                      crow::utility::OrMorePaths())) {
    return;
  }

  // Check array adding a segment each time until collection is identified
  // Add prefix to segment after the collection
  const boost::urls::segments_view urlSegments = thisUrl.segments();
  bool addedPrefix = false;
  boost::urls::url url("/");
  boost::urls::segments_view::iterator it = urlSegments.begin();
  const boost::urls::segments_view::const_iterator end = urlSegments.end();

  // Skip past the leading "/redfish/v1"
  it++;
  it++;
  for (; it != end; it++) {
    // Trailing "/" will result in an empty segment.  In that case we need
    // to return so we don't apply a prefix to top level collections such
    // as "/redfish/v1/Chassis/"
    if ((*it).empty()) {
      return;
    }

    if (std::binary_search(topCollections.begin(), topCollections.end(),
                           url.buffer())) {
      std::string collectionItem(prefix);
      collectionItem += "_" + (*it);
      url.segments().push_back(collectionItem);
      it++;
      addedPrefix = true;
      break;
    }

    url.segments().push_back(*it);
  }

  // Finish constructing the URL here (if needed) to avoid additional checks
  for (; it != end; it++) {
    url.segments().push_back(*it);
  }

  if (addedPrefix) {
    url.segments().insert(url.segments().begin(), {"redfish", "v1"});
    // Preserve the fragment from the original URL
    if (thisUrl.has_fragment()) {
      url.set_fragment(thisUrl.fragment());
    }
    strValue = url.buffer();
  }
}

static inline void addPrefixToItem(nlohmann::json& item,
                                   std::string_view prefix) {
  std::string* strValue = item.get_ptr<std::string*>();
  if (strValue == nullptr) {
    BMCWEB_LOG_CRITICAL << "Field wasn't a string????";
    return;
  }
  addPrefixToStringItem(*strValue, prefix);
  item = *strValue;
}

static inline int generateRandomInt() {
  std::random_device randomDevice;  // NOLINT
  std::mt19937 generator(randomDevice());
  std::uniform_int_distribution<> distribution(1, 9999);
  int randomNumber = distribution(generator);
  return randomNumber;
}

static inline void addAggregatedHeaders(crow::Response& asyncResp,
                                        const crow::Response& resp,
                                        std::string_view prefix) {
  if (!resp.getHeaderValue("Content-Type").empty()) {
    asyncResp.addHeader(boost::beast::http::field::content_type,
                        resp.getHeaderValue("Content-Type"));
  }
  if (!resp.getHeaderValue("Allow").empty()) {
    asyncResp.addHeader(boost::beast::http::field::allow,
                        resp.getHeaderValue("Allow"));
  }
  std::string_view header = resp.getHeaderValue("Location");
  if (!header.empty()) {
    std::string location(header);
    addPrefixToStringItem(location, prefix);
    asyncResp.addHeader(boost::beast::http::field::location, location);
  }
  if (!resp.getHeaderValue("Retry-After").empty()) {
    asyncResp.addHeader(boost::beast::http::field::retry_after,
                        resp.getHeaderValue("Retry-After"));
  }
  // TODO: we need special handling for Link Header Value
}

// Fix HTTP headers which appear in responses from Task resources among others
static inline void addPrefixToHeadersInResp(nlohmann::json& json,
                                            std::string_view prefix) {
  // The passed in "HttpHeaders" should be an array of headers
  nlohmann::json::array_t* array = json.get_ptr<nlohmann::json::array_t*>();
  if (array == nullptr) {
    BMCWEB_LOG_ERROR << "Field wasn't an array_t????";
    return;
  }

  for (nlohmann::json& item : *array) {
    // Each header is a single string with the form "<Field>: <Value>"
    std::string* strHeader = item.get_ptr<std::string*>();
    if (strHeader == nullptr) {
      BMCWEB_LOG_CRITICAL << "Field wasn't a string????";
      continue;
    }

    constexpr std::string_view location = "Location: ";
    if (strHeader->starts_with(location)) {
      std::string header = strHeader->substr(location.size());
      addPrefixToStringItem(header, prefix);
      *strHeader = std::string(location) + header;
    }
  }
}

// Search the json for all URIs and add the supplied prefix if the URI is for
// an aggregated resource.
static inline void addPrefixes(nlohmann::json& json, std::string_view prefix) {
  nlohmann::json::object_t* object = json.get_ptr<nlohmann::json::object_t*>();
  if (object != nullptr) {
    for (std::pair<const std::string, nlohmann::json>& item : *object) {
      if (isPropertyUri(item.first)) {
        addPrefixToItem(item.second, prefix);
        continue;
      }

      // "HttpHeaders" contains HTTP headers.  Among those we need to
      // attempt to fix the "Location" header
      if (item.first == "HttpHeaders") {
        addPrefixToHeadersInResp(item.second, prefix);
        continue;
      }

      // Recursively parse the rest of the json
      addPrefixes(item.second, prefix);
    }
    return;
  }
  nlohmann::json::array_t* array = json.get_ptr<nlohmann::json::array_t*>();
  if (array != nullptr) {
    for (nlohmann::json& item : *array) {
      addPrefixes(item, prefix);
    }
  }
}

inline std::unordered_map<std::string, std::string> rdePrefixMap(
    {{"/xyz/openbmc_project/rde_devices/1_1_1_1", "BCX5VT"},  // NOLINT
     {"/xyz/openbmc_project/rde_devices/1_1_2_1", "A61MJ0"},
     {"/xyz/openbmc_project/rde_devices/1_1_3_1", "K298LC"},
     {"/xyz/openbmc_project/rde_devices/1_1_4_1", "2HMMCS"}});

inline std::unordered_map<std::string, std::string> rdeServiceLabelMap(
    {{"BCX5VT", "DOWNLINK"},  // NOLINT
     {"A61MJ0", "DOWNLINK"},
     {"K298LC", "DOWNLINK"},
     {"2HMMCS", "PCIE0"}});

inline static bool generatePrefix(const std::string& objPath,
                                  std::string& prefix) {
  const auto& it = rdePrefixMap.find(objPath);
  if (it == rdePrefixMap.end()) {
    BMCWEB_LOG_DEBUG << "objPath does not exist in prefix map " << objPath
                     << "\n";
    return false;
  }
  prefix = it->second;
  return true;
}

static inline bool isMemberStartsWithKnownPrefix(
    const std::string& memberName) {
  BMCWEB_LOG_DEBUG << "isMemberStartsWithKnownPrefix";
  for (auto const& [path, prefix] : rdePrefixMap) {
    BMCWEB_LOG_DEBUG << "path " << path << " " << prefix;
    if (memberName.starts_with(prefix)) {
      BMCWEB_LOG_DEBUG << " Known prefix " << memberName;
      return true;
    }
  }
  return false;
}

inline boost::system::error_code aggregationRetryHandler(
    unsigned int respCode) {
  // Allow all response codes because we want to surface any satellite
  // issue to the client
  BMCWEB_LOG_DEBUG << "Received " << respCode << " response from satellite";
  return boost::system::errc::make_error_code(boost::system::errc::success);
}

inline crow::ConnectionPolicy getAggregationPolicy() {
  return {.maxRetryAttempts = 1,
          .requestByteLimit = aggregatorReadBodyLimit,
          .maxConnections = 20,
          .retryPolicyAction = "TerminateAfterRetries",
          .retryIntervalSecs = std::chrono::seconds(0),
          .invalidResp = aggregationRetryHandler};
}

class RedfishAggregator {
 private:
  crow::HttpClient client;

  RedfishAggregator()
      : client(
            std::make_shared<crow::ConnectionPolicy>(getAggregationPolicy())) {
    getSatelliteConfigs(constructorCallback);
  }

  // Dummy callback used by the Constructor so that it can report the number
  // of satellite configs when the class is first created
  static void constructorCallback(
      const boost::system::error_code& ec,
      const std::unordered_map<std::string, boost::urls::url>& satelliteInfo,
      const std::unordered_map<std::string, RdeSatelliteConfig>&
          rdeSatelliteInfo) {
    if (ec) {
      BMCWEB_LOG_ERROR << "Something went wrong while querying dbus!";
      return;
    }

    BMCWEB_LOG_DEBUG << "There were " << std::to_string(satelliteInfo.size())
                     << " satellite configs found at startup";
    BMCWEB_LOG_DEBUG << "There were " << std::to_string(rdeSatelliteInfo.size())
                     << " RDE Device configs found at startup";
  }

  // Search D-Bus objects for satellite config objects and add their
  // information if valid
  static void findSatelliteConfigs(
      const dbus::utility::ManagedObjectType& objects,
      std::unordered_map<std::string, boost::urls::url>& satelliteInfo,
      std::unordered_map<std::string, RdeSatelliteConfig>& rdeSatelliteInfo) {
    for (const auto& objectPath : objects) {
      for (const auto& interface : objectPath.second) {
        if (interface.first ==
            "xyz.openbmc_project.Configuration.SatelliteController") {
          BMCWEB_LOG_DEBUG << "Found Satellite Controller at "
                           << objectPath.first.str;

          if (!satelliteInfo.empty()) {
            BMCWEB_LOG_ERROR
                << "Redfish Aggregation only supports one satellite!";
            BMCWEB_LOG_DEBUG << "Clearing all satellite data";
            satelliteInfo.clear();
            return;
          }

          // For now assume there will only be one satellite config.
          // Assign it the name/prefix "5B247A"
          addSatelliteConfig("5B247A", interface.second, satelliteInfo);
        } else if (interface.first ==
                   "xyz.openbmc_project.Configuration.RdeSatelliteController") {
          BMCWEB_LOG_DEBUG << "Found RDE Satellite Controller at "
                           << objectPath.first.str;
          addRdeSatelliteConfig(interface.second, rdeSatelliteInfo);
        }
      }
    }
  }

  // Parse the properties of a satellite config object and add the
  // configuration if the properties are valid
  static void addSatelliteConfig(
      const std::string& name,
      const dbus::utility::DBusPropertiesMap& properties,
      std::unordered_map<std::string, boost::urls::url>& satelliteInfo) {
    boost::urls::url url;

    for (const auto& prop : properties) {
      if (prop.first == "Hostname") {
        const std::string* propVal = std::get_if<std::string>(&prop.second);
        if (propVal == nullptr) {
          BMCWEB_LOG_ERROR << "Invalid Hostname value";
          return;
        }
        url.set_host(*propVal);
      } else if (prop.first == "Port") {
        const uint64_t* propVal = std::get_if<uint64_t>(&prop.second);
        if (propVal == nullptr) {
          BMCWEB_LOG_ERROR << "Invalid Port value";
          return;
        }

        if (*propVal > std::numeric_limits<uint16_t>::max()) {
          BMCWEB_LOG_ERROR << "Port value out of range";
          return;
        }
        url.set_port(std::to_string(static_cast<uint16_t>(*propVal)));
      } else if (prop.first == "AuthType") {
        const std::string* propVal = std::get_if<std::string>(&prop.second);
        if (propVal == nullptr) {
          BMCWEB_LOG_ERROR << "Invalid AuthType value";
          return;
        }

        // For now assume authentication not required to communicate
        // with the satellite BMC
        if (*propVal != "None") {
          BMCWEB_LOG_ERROR << "Unsupported AuthType value: " << *propVal
                           << ", only \"none\" is supported";
          return;
        }
        url.set_scheme("http");
      }
    }  // Finished reading properties

    // Make sure all required config information was made available
    if (url.host().empty()) {
      BMCWEB_LOG_ERROR << "Satellite config " << name << " missing Host";
      return;
    }

    if (!url.has_port()) {
      BMCWEB_LOG_ERROR << "Satellite config " << name << " missing Port";
      return;
    }

    if (!url.has_scheme()) {
      BMCWEB_LOG_ERROR << "Satellite config " << name << " missing AuthType";
      return;
    }

    std::string resultString;
    auto result = satelliteInfo.insert_or_assign(name, std::move(url));
    if (result.second) {
      resultString = "Added new satellite config ";
    } else {
      resultString = "Updated existing satellite config ";
    }

    BMCWEB_LOG_DEBUG << resultString << name << " at "
                     << result.first->second.scheme() << "://"
                     << result.first->second.encoded_host_and_port();
  }

  // Parse the properties of a RDE Device config object and add the
  // configuration if the properties are valid
  static void addRdeSatelliteConfig(
      const dbus::utility::DBusPropertiesMap& properties,
      std::unordered_map<std::string, RdeSatelliteConfig>& rdeSatelliteInfo) {
    RdeSatelliteConfig rdeConfig;
    std::string name;
    for (const auto& prop : properties) {
      if (prop.first == "Name") {
        const std::string* propVal = std::get_if<std::string>(&prop.second);
        if (propVal == nullptr) {
          BMCWEB_LOG_ERROR << "Invalid Name value";
          return;
        }
        rdeConfig.name = *propVal;
      } else if (prop.first == "VID") {
        const std::string* propVal = std::get_if<std::string>(&prop.second);
        if (propVal == nullptr) {
          BMCWEB_LOG_ERROR << "Invalid VID value";
          return;
        }
        rdeConfig.vid = *propVal;
      } else if (prop.first == "UDEVID") {
        const std::string* propVal = std::get_if<std::string>(&prop.second);
        if (propVal == nullptr) {
          BMCWEB_LOG_ERROR << "Invalid UDEVID value";
          return;
        }
        rdeConfig.udevid = *propVal;
      } else if (prop.first == "USBPORT") {
        const std::string* propVal = std::get_if<std::string>(&prop.second);
        if (propVal == nullptr) {
          BMCWEB_LOG_ERROR << "Invalid USBPORT value";
          return;
        }
        rdeConfig.usbport = *propVal;
      }
    }  // Finished reading properties

    if (rdeConfig.udevid.empty()) {
      BMCWEB_LOG_ERROR << "Empty udevid";
      return;
    }
    rdeConfig.objectpath =
        "/xyz/openbmc_project/rde_devices/" + rdeConfig.udevid;

    // Set the prefix to a random string 'E0SB8D'
    // (TODO) Generate a unique random prefix for each RDE Device
    if constexpr (bmcwebEnableRdeDevice) {
      if (!generatePrefix(rdeConfig.objectpath, name)) {
        BMCWEB_LOG_ERROR << " Failed to get a prefix for "
                         << rdeConfig.objectpath;
        return;
      }
      BMCWEB_LOG_DEBUG << " Got prefix " << name;
    }
    std::string resultString;
    auto result = rdeSatelliteInfo.emplace(name, std::move(rdeConfig));
    if (result.second) {
      resultString = "Added new RDE Device config ";
    } else {
      resultString = "Updated existing RDE Device config ";
    }
  }

  enum AggregationType : std::uint8_t {
    Collection,
    ContainsSubordinate,
    Resource,
  };

  static void startAggregation(
      AggregationType aggType, const crow::Request& thisReq,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
    if (thisReq.method() != boost::beast::http::verb::get) {
      if (aggType == AggregationType::Collection) {
        BMCWEB_LOG_DEBUG
            << "Only aggregate GET requests to top level collections";
        return;
      }

      if (aggType == AggregationType::ContainsSubordinate) {
        BMCWEB_LOG_DEBUG << "Only aggregate GET requests when uptree of"
                         << " a top level collection";
        return;
      }
    }

    // Create a copy of thisReq so we we can still locally process the req
    std::error_code ec;
    auto localReq = std::make_shared<crow::Request>(thisReq.req, ec);
    if (ec) {
      BMCWEB_LOG_ERROR << "Failed to create copy of request";
      if (aggType == AggregationType::Resource) {
        messages::internalError(asyncResp->res);
      }
      return;
    }

    // Strip query params that don't work correctly if forwarded
    parameterRemove(*localReq);

    getSatelliteConfigs(
        std::bind_front(aggregateAndHandle, aggType, localReq, asyncResp));
  }

  static void findSatellite(
      const crow::Request& req,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const std::unordered_map<std::string, boost::urls::url>& satelliteInfo,
      const std::unordered_map<std::string, RdeSatelliteConfig>&
          rdeSatelliteInfo,
      std::string_view memberName) {
    bool validPrefix = false;
    // Determine if the resource ID begins with a known prefix
    for (const auto& satellite : satelliteInfo) {
      std::string targetPrefix = satellite.first;
      targetPrefix += "_";
      if (memberName.starts_with(targetPrefix)) {
        BMCWEB_LOG_DEBUG << "\"" << satellite.first << "\" is a known prefix";

        // Remove the known prefix from the request's URI and
        // then forward to the associated satellite BMC
        getInstance().forwardRequest(req, asyncResp, satellite.first,
                                     satelliteInfo);
        validPrefix = true;
      }
    }
    // Determine if the resource ID begins with a known prefix
    for (const auto& rdeSatellite : rdeSatelliteInfo) {
      std::string targetPrefix = rdeSatellite.first;
      targetPrefix += "_";
      if (memberName.starts_with(targetPrefix)) {
        BMCWEB_LOG_DEBUG << "\"" << rdeSatellite.first
                         << "\" is a known prefix";
        // Remove the known prefix from the request's URI and
        // then forward to RDE Daemon
        forwardRdeRequest(req, asyncResp, rdeSatellite.first, rdeSatelliteInfo);
        validPrefix = true;
      }
    }
    if (validPrefix) {
      return;
    }
    // We didn't recognize the prefix and need to return a 404
    std::string nameStr = req.url().segments().back();
    messages::resourceNotFound(asyncResp->res, "", nameStr);
  }

  // Intended to handle an incoming request based on if Redfish Aggregation
  // is enabled.  Forwards request to satellite BMC if it exists.
  static void aggregateAndHandle(
      AggregationType aggType, const std::shared_ptr<crow::Request>& sharedReq,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const boost::system::error_code& ec,
      const std::unordered_map<std::string, boost::urls::url>& satelliteInfo,
      const std::unordered_map<std::string, RdeSatelliteConfig>&
          rdeSatelliteInfo) {
    if (sharedReq == nullptr) {
      return;
    }
    // Something went wrong while querying dbus
    if (ec) {
      messages::internalError(asyncResp->res);
      return;
    }

    // No satellite or RDE configs means we don't need to keep attempting to
    // aggregate
    if (satelliteInfo.empty() && rdeSatelliteInfo.empty()) {
      // For collections or resources that can contain a subordinate
      // top level collection we'll also handle the request locally so we
      // don't need to write an error code
      if (aggType == AggregationType::Resource) {
        std::string nameStr = sharedReq->url().segments().back();
        messages::resourceNotFound(asyncResp->res, "", nameStr);
      }
      return;
    }

    const crow::Request& thisReq = *sharedReq;
    if constexpr (enablePlatform9) {
      BMCWEB_LOG_DEBUG << "Aggregation is enabled, begin processing of "
                       << thisReq.url();
    } else {
      BMCWEB_LOG_DEBUG << "Aggregation is enabled, begin processing of "
                       << thisReq.target();
    }

    // We previously determined the request is for a collection.  No need to
    // check again
    if (aggType == AggregationType::Collection) {
      BMCWEB_LOG_DEBUG << "Aggregating a collection";
      // We need to use a specific response handler and send the
      // request to all known satellites
      getInstance().forwardCollectionRequests(thisReq, asyncResp, satelliteInfo,
                                              rdeSatelliteInfo);
      return;
    }

    // We previously determined the request may contain a subordinate
    // collection.  No need to check again
    if (aggType == AggregationType::ContainsSubordinate) {
      BMCWEB_LOG_DEBUG << "Aggregating what may have a subordinate collection";
      // We need to use a specific response handler and send the
      // request to all known satellites
      getInstance().forwardContainsSubordinateRequests(thisReq, asyncResp,
                                                       satelliteInfo);
      return;
    }

    const boost::urls::segments_view urlSegments = thisReq.url().segments();
    boost::urls::url currentUrl("/");
    boost::urls::segments_view::iterator it = urlSegments.begin();
    const boost::urls::segments_view::const_iterator end = urlSegments.end();

    // Skip past the leading "/redfish/v1"
    it++;
    it++;
    for (; it != end; it++) {
      if (std::binary_search(topCollections.begin(), topCollections.end(),
                             currentUrl.buffer())) {
        // We've matched a resource collection so this current segment
        // must contain an aggregation prefix
        findSatellite(thisReq, asyncResp, satelliteInfo, rdeSatelliteInfo, *it);
        return;
      }

      currentUrl.segments().push_back(*it);
    }

    // We shouldn't reach this point since we should've hit one of the
    // previous exits
    messages::internalError(asyncResp->res);
  }

  // Attempt to forward a request to the satellite BMC associated with the
  // prefix.
  void forwardRequest(
      const crow::Request& thisReq,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const std::string& prefix,
      const std::unordered_map<std::string, boost::urls::url>& satelliteInfo) {
    const auto& sat = satelliteInfo.find(prefix);
    if (sat == satelliteInfo.end()) {
      // Realistically this shouldn't get called since we perform an
      // earlier check to make sure the prefix exists
      BMCWEB_LOG_ERROR << "Unrecognized satellite prefix \"" << prefix << "\"";
      return;
    }

    // We need to strip the prefix from the request's path
    std::string targetURI;
    if constexpr (enablePlatform9) {
      targetURI = std::string(thisReq.url().path());
    } else {
      targetURI = std::string(thisReq.target());
    }

    size_t pos = targetURI.find(prefix + "_");
    if (pos == std::string::npos) {
      // If this fails then something went wrong
      BMCWEB_LOG_ERROR << "Error removing prefix \"" << prefix
                       << "_\" from request URI";
      messages::internalError(asyncResp->res);
      return;
    }
    targetURI.erase(pos, prefix.size() + 1);

    std::function<void(crow::Response&)> cb =
        std::bind_front(processResponse, prefix, asyncResp);

    std::string data = thisReq.req.body();
    client.sendDataWithCallback(
        data, std::string(sat->second.host()), sat->second.port_number(),
        targetURI, false /*useSSL*/, thisReq.fields(), thisReq.method(), cb);
  }

  // Forward a request for a collection URI to each known satellite BMC
  void forwardCollectionRequests(
      const crow::Request& thisReq,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const std::unordered_map<std::string, boost::urls::url>& satelliteInfo,
      const std::unordered_map<std::string, RdeSatelliteConfig>&
          rdeSatelliteInfo) {
    for (const auto& sat : satelliteInfo) {
      std::function<void(crow::Response&)> cb =
          std::bind_front(processCollectionResponse, sat.first, asyncResp);

      std::string targetURI;
      if constexpr (enablePlatform9) {
        targetURI = std::string(thisReq.url().path());
      } else {
        targetURI = std::string(thisReq.target());
      }
      std::string data = thisReq.req.body();
      client.sendDataWithCallback(
          data, std::string(sat.second.host()), sat.second.port_number(),
          targetURI, false /*useSSL*/, thisReq.fields(), thisReq.method(), cb);
    }
    for (const auto& rsat : rdeSatelliteInfo) {
      uint8_t operationId = 1;
      std::string requestPayload;
      BMCWEB_LOG_DEBUG << " Collection Request: dbus call to RDE Daemon "
                       << " operationId " << operationId;
      std::string targetURI(thisReq.target());
      if (managedStore::RequestStatsStore::isRdeRateLimitEnabled() &&
          managedStore::RequestStatsStore::instance()
                  .getCurrentRdeRequestSkips() > 0) {
        BMCWEB_LOG_DEBUG << " Skipping the request " << targetURI;
        asyncResp->requestStatsContext->updateRdeSkips();
        managedStore::RequestStatsStore::instance()
            .updateCurrentRdeRequestSkips();
        return;
      }
      BMCWEB_LOG_DEBUG << "Collections objpath " << rsat.second.objectpath
                       << " targetURI " << targetURI << " udevid "
                       << rsat.second.udevid;
      asyncResp->res.startTimetrace(rsat.first);
      if (managedStore::RequestStatsStore::isRdeRateLimitEnabled()) {
        asyncResp->requestStatsContext->updateRdeReqs();
      }
      managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
          asyncResp->strand_,
          [&operationId, rsat, asyncResp](const boost::system::error_code ec,
                                          const std::string& jsonString) {
            if (ec) {
              BMCWEB_LOG_ERROR << "DBUS response error operationId "
                               << operationId << " , " << ec.value() << ", "
                               << ec.message();
              if (managedStore::RequestStatsStore::isRdeRateLimitEnabled()) {
                asyncResp->requestStatsContext->updateRdeDbusErrors();
                managedStore::RequestStatsStore::instance()
                    .updateCurrentRdeDbusErrors();
                if (managedStore::RequestStatsStore::instance()
                            .getCurrentRdeDbusErrors() >
                        managedStore::RequestStatsStore::rdeErrorThreshold() &&
                    managedStore::RequestStatsStore::instance()
                            .getCurrentRdeRequestSkips() <= 0) {
                  BMCWEB_LOG_ERROR << "RDE Rate Limit enabled";
                  asyncResp->requestStatsContext->updateRdeRateLimitToggles();
                  managedStore::RequestStatsStore::instance()
                      .setCurrentRdeRequestSkips(
                          managedStore::RequestStatsStore::rdeMaxSkips());
                }
              }
              return;
            }
            if (managedStore::RequestStatsStore::isRdeRateLimitEnabled()) {
              managedStore::RequestStatsStore::instance()
                  .setCurrentRdeDbusErrors(0);
              managedStore::RequestStatsStore::instance()
                  .setCurrentRdeRequestSkips(0);
            }
            processRdeCollectionResponse(rsat.first, asyncResp, jsonString);
          },
          "xyz.openbmc_project.rdeoperation", rsat.second.objectpath,
          "xyz.openbmc_project.RdeDevice", "execute_rde", generateRandomInt(),
          operationId, targetURI, rsat.second.udevid, requestPayload);
    }
  }

  // Forward request for a URI that is uptree of a top level collection to
  // each known satellite BMC
  void forwardContainsSubordinateRequests(
      const crow::Request& thisReq,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const std::unordered_map<std::string, boost::urls::url>& satelliteInfo) {
    for (const auto& sat : satelliteInfo) {
      std::function<void(crow::Response&)> cb = std::bind_front(
          processContainsSubordinateResponse, sat.first, asyncResp);

      std::string targetURI(thisReq.target());
      std::string data = thisReq.req.body();
      client.sendDataWithCallback(
          data, std::string(sat.second.host()), sat.second.port_number(),
          targetURI, false /*useSSL*/, thisReq.fields(), thisReq.method(), cb);
    }
  }

  // Attempt to forward a request to the RDE Daemon associated with the
  // prefix.
  static void forwardRdeRequest(
      const crow::Request& thisReq,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const std::string& prefix,
      const std::unordered_map<std::string, RdeSatelliteConfig>&
          rdeSatelliteInfo) {
    const auto& sat = rdeSatelliteInfo.find(prefix);
    if (sat == rdeSatelliteInfo.end()) {
      // Realistically this shouldn't get called since we perform an
      // earlier check to make sure the prefix exists
      BMCWEB_LOG_ERROR << "Unrecognized RDE Device prefix \"" << prefix << "\"";
      return;
    }

    // We need to strip the prefix from the request's path
    std::string targetURI(thisReq.target());
    if (managedStore::RequestStatsStore::isRdeRateLimitEnabled() &&
        managedStore::RequestStatsStore::instance()
                .getCurrentRdeRequestSkips() > 0) {
      BMCWEB_LOG_DEBUG << " Skipping the request " << targetURI;
      asyncResp->requestStatsContext->updateRdeSkips();
      managedStore::RequestStatsStore::instance()
          .updateCurrentRdeRequestSkips();
      return;
    }
    size_t pos = targetURI.find(prefix + "_");
    if (pos == std::string::npos) {
      // If this fails then something went wrong
      BMCWEB_LOG_ERROR << "Error removing prefix \"" << prefix
                       << "_\" from request URI";
      messages::internalError(asyncResp->res);
      return;
    }
    targetURI.erase(pos, prefix.size() + 1);

    uint8_t operationId = 1;
    std::string requestPayload;
    boost::beast::http::verb method = thisReq.method();
    if (thisReq.method() == boost::beast::http::verb::post) {
      operationId = 8;
      requestPayload = thisReq.body();
    } else if (thisReq.method() == boost::beast::http::verb::patch) {
      operationId = 4;
      requestPayload = thisReq.body();
    }
    BMCWEB_LOG_DEBUG
        << " Resource Request: dbus call to RDE Daemon operationId "
        << operationId;
    BMCWEB_LOG_DEBUG << "objpath " << sat->second.objectpath << " targetURI "
                     << targetURI << " udevid " << sat->second.udevid
                     << " method " << method;
    asyncResp->res.startTimetrace(prefix);
    if (managedStore::RequestStatsStore::isRdeRateLimitEnabled()) {
      asyncResp->requestStatsContext->updateRdeReqs();
    }
    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [&operationId, method, prefix, asyncResp](
            const boost::system::error_code ec, const std::string& jsonString) {
          if (ec) {
            BMCWEB_LOG_ERROR << "DBUS response error operationId "
                             << operationId << " , " << ec.value() << ", "
                             << ec.message();
            if (managedStore::RequestStatsStore::isRdeRateLimitEnabled()) {
              asyncResp->requestStatsContext->updateRdeDbusErrors();
              managedStore::RequestStatsStore::instance()
                  .updateCurrentRdeDbusErrors();

              if (managedStore::RequestStatsStore::instance()
                          .getCurrentRdeDbusErrors() >
                      managedStore::RequestStatsStore::rdeErrorThreshold() &&
                  managedStore::RequestStatsStore::instance()
                          .getCurrentRdeRequestSkips() <= 0) {
                BMCWEB_LOG_ERROR << "RDE Rate limiting enabled";
                asyncResp->requestStatsContext->updateRdeRateLimitToggles();
                managedStore::RequestStatsStore::instance()
                    .setCurrentRdeRequestSkips(
                        managedStore::RequestStatsStore::rdeMaxSkips());
              }
            }
            return;
          }
          if (managedStore::RequestStatsStore::isRdeRateLimitEnabled()) {
            managedStore::RequestStatsStore::instance().setCurrentRdeDbusErrors(
                0);
            managedStore::RequestStatsStore::instance()
                .setCurrentRdeRequestSkips(0);
          }
          processRdeResponse(prefix, method, asyncResp, jsonString);
        },
        "xyz.openbmc_project.rdeoperation", sat->second.objectpath,
        "xyz.openbmc_project.RdeDevice", "execute_rde", generateRandomInt(),
        operationId, targetURI, sat->second.udevid, requestPayload);
  }
  // Processes the response returned by a RDE Device and loads its
  // contents into asyncResp
  static void processRdeResponse(
      std::string_view prefix, boost::beast::http::verb method,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const std::string& respString) {
    nlohmann::json jsonVal = nlohmann::json::parse(respString, nullptr, false);
    if (jsonVal.is_discarded()) {
      BMCWEB_LOG_ERROR << "Error parsing RDE Device response as JSON "
                       << respString;
      messages::operationFailed(asyncResp->res);
      return;
    }

    BMCWEB_LOG_DEBUG << "Successfully parsed RDE Device response";

    if (method == boost::beast::http::verb::post) {
      if (jsonVal["Status"] == "Completed") {
        asyncResp->res.result(200);
      } else {
        messages::operationFailed(asyncResp->res);
      }
      return;
    }
    // TODO: For collections we  want to add the satellite responses to
    // our response rather than just straight overwriting them if our
    // local handling was successful (i.e. would return a 200).
    addPrefixes(jsonVal, prefix);

    if constexpr (bmcwebEnableRdeDevice) {
      if (jsonVal.contains(
              "/Location/PartLocation/ServiceLabel"_json_pointer)) {
        BMCWEB_LOG_DEBUG << " @odata.type " << jsonVal["@odata.type"];
        if (jsonVal["Model"] == platform6Chassis1 ||
            jsonVal["Model"] == platform6Chassis2) {
          BMCWEB_LOG_DEBUG << "Setting up service label "
                           << rdeServiceLabelMap[std::string{prefix}]
                           << " for prefix " << prefix;
          jsonVal["Location"]["PartLocation"]["ServiceLabel"] =
              rdeServiceLabelMap[std::string{prefix}];
        }
      }
      auto it = jsonVal.find("Id");
      if (it != jsonVal.end() && it->is_string()) {
        std::string* id_ptr = it->get_ptr<std::string*>();
        if (id_ptr != nullptr) {
          id_ptr->insert(0, std::string(prefix) + "_");
        }
      }
    }

    asyncResp->res.result(200);
    asyncResp->res.jsonValue = std::move(jsonVal);
    asyncResp->res.endTimetrace(std::string(prefix));

    BMCWEB_LOG_DEBUG << "Finished writing asyncResp";
  }

  // Processes the collection response returned by a RDE Device and merges
  // its "@odata.id" values
  static void processRdeCollectionResponse(
      const std::string& prefix,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      const std::string& respString) {
    nlohmann::json jsonVal = nlohmann::json::parse(respString, nullptr, false);
    if (jsonVal.is_discarded()) {
      BMCWEB_LOG_ERROR << "Error parsing RDEd response as JSON " << respString;

      // Notify the user if doing so won't overwrite a valid response
      if ((asyncResp->res.resultInt() != 200) &&
          (asyncResp->res.resultInt() != 502)) {
        messages::operationFailed(asyncResp->res);
      }
      return;
    }

    BMCWEB_LOG_DEBUG << "Successfully parsed RDEd response";

    // Now we need to add the prefix to the URIs contained in the
    // response.
    addPrefixes(jsonVal, prefix);

    BMCWEB_LOG_DEBUG << "Added prefix to parsed RDE Device response";

    // If this resource collection does not exist on the aggregating bmc
    // and has not already been added from processing the response from
    // a different satellite then we need to completely overwrite
    // asyncResp
    if (asyncResp->res.resultInt() != 200) {
      // We only want to aggregate collections that contain a
      // "Members" array
      if ((!jsonVal.contains("Members")) && (!jsonVal["Members"].is_array())) {
        BMCWEB_LOG_DEBUG << "Skipping aggregating unsupported resource";
        return;
      }

      BMCWEB_LOG_DEBUG << "Collection does not exist, overwriting asyncResp";
      asyncResp->res.jsonValue = std::move(jsonVal);

      BMCWEB_LOG_DEBUG << "Finished overwriting asyncResp";
    } else {
      // We only want to aggregate collections that contain a
      // "Members" array
      if ((!asyncResp->res.jsonValue.contains("Members")) &&
          (!asyncResp->res.jsonValue["Members"].is_array())) {
        BMCWEB_LOG_DEBUG << "Skipping aggregating unsupported resource";
        return;
      }

      BMCWEB_LOG_DEBUG << "Adding aggregated resources from \"" << prefix
                       << "\" to collection";

      // TODO: This is a potential race condition with multiple
      // satellites and the aggregating bmc attempting to write to
      // update this array.  May need to cascade calls to the next
      // satellite at the end of this function.
      auto& members = asyncResp->res.jsonValue["Members"];
      auto& satMembers = jsonVal["Members"];
      for (auto& satMem : satMembers) {
        members.push_back(std::move(satMem));
      }
      asyncResp->res.jsonValue["Members@odata.count"] = members.size();

      // TODO: Do we need to sort() after updating the array?
    }
    asyncResp->res.endTimetrace(prefix);
  }  // End processRdeCollectionResponse()

 public:
  RedfishAggregator(const RedfishAggregator&) = delete;
  RedfishAggregator& operator=(const RedfishAggregator&) = delete;
  RedfishAggregator(RedfishAggregator&&) = delete;
  RedfishAggregator& operator=(RedfishAggregator&&) = delete;
  ~RedfishAggregator() = default;

  static RedfishAggregator& getInstance() {
    static RedfishAggregator handler;
    return handler;
  }

  // Polls D-Bus to get all available satellite config information
  // Expects a handler which interacts with the returned configs
  static void getSatelliteConfigs(
      std::function<
          void(const boost::system::error_code&,
               const std::unordered_map<std::string, boost::urls::url>&,
               const std::unordered_map<std::string, RdeSatelliteConfig>&)>
          handler) {
    BMCWEB_LOG_DEBUG << "Gathering satellite configs";

    managedStore::ManagedObjectStoreContext context(nullptr);
    managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
        "xyz.openbmc_project.EntityManager", {"/xyz/openbmc_project/inventory"},
        context,
        [handler{std::move(handler)}](
            const boost::system::error_code& ec,
            const dbus::utility::ManagedObjectType& objects) {
          std::unordered_map<std::string, boost::urls::url> satelliteInfo;
          std::unordered_map<std::string, RdeSatelliteConfig> rdeSatelliteInfo;
          if (ec) {
            BMCWEB_LOG_ERROR << "DBUS response error " << ec.value() << ", "
                             << ec.message();
            handler(ec, satelliteInfo, rdeSatelliteInfo);
            return;
          }

          // Maps a chosen alias representing a satellite BMC to a url
          // containing the information required to create a http
          // connection to the satellite
          findSatelliteConfigs(objects, satelliteInfo, rdeSatelliteInfo);

          if (!satelliteInfo.empty()) {
            BMCWEB_LOG_DEBUG << "Redfish Aggregation enabled with "
                             << std::to_string(satelliteInfo.size())
                             << " satellite BMCs";
          } else if (!rdeSatelliteInfo.empty()) {
            BMCWEB_LOG_DEBUG << "Redfish Aggregation enabled with "
                             << std::to_string(rdeSatelliteInfo.size())
                             << " RDE Device";
          } else {
            BMCWEB_LOG_DEBUG << "No satellite BMCs detected.  Redfish "
                                "Aggregation not enabled";
          }
          handler(ec, satelliteInfo, rdeSatelliteInfo);
        });
  }

  // Processes the response returned by a satellite BMC and loads its
  // contents into asyncResp
  static void processResponse(
      std::string_view prefix,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      crow::Response& resp) {
    // 429 and 502 mean we didn't actually send the request so don't
    // overwrite the response headers in that case
    if ((resp.result() == boost::beast::http::status::too_many_requests) ||
        (resp.result() == boost::beast::http::status::bad_gateway)) {
      asyncResp->res.result(resp.result());
      return;
    }

    // We want to attempt prefix fixing regardless of response code
    // The resp will not have a json component
    // We need to create a json from resp's stringResponse
    std::string_view contentType = resp.getHeaderValue("Content-Type");
    if (boost::iequals(contentType, "application/json") ||
        boost::iequals(contentType, "application/json; charset=utf-8")) {
      nlohmann::json jsonVal =
          nlohmann::json::parse(resp.body(), nullptr, false);
      if (jsonVal.is_discarded()) {
        BMCWEB_LOG_ERROR << "Error parsing satellite response as JSON";
        messages::operationFailed(asyncResp->res);
        return;
      }

      BMCWEB_LOG_DEBUG << "Successfully parsed satellite response";

      addPrefixes(jsonVal, prefix);

      if constexpr (enablePlatform9) {
        // Hardcode relation to aggregating BMC
        if ((jsonVal.contains("@odata.id")) &&
            (jsonVal["@odata.id"].is_string())) {
          std::string targetURI(jsonVal["@odata.id"]);
          std::string aggRootURI(prefix);
          aggRootURI = "/redfish/v1/Chassis/" + aggRootURI + "_" +
                       std::string(platform9Chassis5);
          if (targetURI == aggRootURI) {
            jsonVal["Links"]["ContainedBy"] = {
                {"@odata.id",
                 "/redfish/v1/Chassis/" + std::string(platform9Chassis4)}};
          }
        }
        // End hardcoded workaround
      }

      BMCWEB_LOG_DEBUG << "Added prefix to parsed satellite response";

      asyncResp->res.result(resp.result());
      asyncResp->res.jsonValue = std::move(jsonVal);

      BMCWEB_LOG_DEBUG << "Finished writing asyncResp";
    } else {
      // We allow any Content-Type that is not "application/json" now
      asyncResp->res.result(resp.result());
      asyncResp->res.write(resp.body());
    }
    addAggregatedHeaders(asyncResp->res, resp, prefix);
  }

  // Processes the collection response returned by a satellite BMC and merges
  // its "@odata.id" values
  static void processCollectionResponse(
      const std::string& prefix,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      crow::Response& resp) {
    // 429 and 502 mean we didn't actually send the request so don't
    // overwrite the response headers in that case
    if ((resp.result() == boost::beast::http::status::too_many_requests) ||
        (resp.result() == boost::beast::http::status::bad_gateway)) {
      return;
    }

    if (resp.resultInt() != 200) {
      BMCWEB_LOG_DEBUG
          << "Collection resource does not exist in satellite BMC \"" << prefix
          << "\"";
      // Return the error if we haven't had any successes
      if (asyncResp->res.resultInt() != 200) {
        asyncResp->res.result(resp.result());
        asyncResp->res.write(resp.body());
      }
      return;
    }

    // The resp will not have a json component
    // We need to create a json from resp's stringResponse
    std::string_view contentType = resp.getHeaderValue("Content-Type");
    if (boost::iequals(contentType, "application/json") ||
        boost::iequals(contentType, "application/json; charset=utf-8")) {
      nlohmann::json jsonVal =
          nlohmann::json::parse(resp.body(), nullptr, false);
      if (jsonVal.is_discarded()) {
        BMCWEB_LOG_ERROR << "Error parsing satellite response as JSON";

        // Notify the user if doing so won't overwrite a valid response
        if (asyncResp->res.resultInt() != 200) {
          messages::operationFailed(asyncResp->res);
        }
        return;
      }

      BMCWEB_LOG_DEBUG << "Successfully parsed satellite response";

      // Now we need to add the prefix to the URIs contained in the
      // response.
      addPrefixes(jsonVal, prefix);

      BMCWEB_LOG_DEBUG << "Added prefix to parsed satellite response";

      // If this resource collection does not exist on the aggregating bmc
      // and has not already been added from processing the response from
      // a different satellite then we need to completely overwrite
      // asyncResp
      if (asyncResp->res.resultInt() != 200) {
        BMCWEB_LOG_DEBUG << "Collection does not exist, overwriting asyncResp";
        asyncResp->res.result(resp.result());
        asyncResp->res.jsonValue = std::move(jsonVal);
        asyncResp->res.addHeader("Content-Type", "application/json");

        BMCWEB_LOG_DEBUG << "Finished overwriting asyncResp";
      } else {
        BMCWEB_LOG_DEBUG << "Adding aggregated resources from \"" << prefix
                         << "\" to collection";

        // TODO: This is a potential race condition with multiple
        // satellites and the aggregating bmc attempting to write to
        // update this array.  May need to cascade calls to the next
        // satellite at the end of this function.
        // This is presumably not a concern when there is only a single
        // satellite since the aggregating bmc should have completed
        // before the response is received from the satellite.

        auto& members = asyncResp->res.jsonValue["Members"];
        if (!members.is_array()) {
          // Satellite response is being processed before top level
          // collection request has been locally handled so we need
          // to create Members array
          BMCWEB_LOG_DEBUG << "Created new Members array";
          members = nlohmann::json::array();
        }
        auto& satMembers = jsonVal["Members"];
        for (auto& satMem : satMembers) {
          members.push_back(std::move(satMem));
        }
        asyncResp->res.jsonValue["Members@odata.count"] = members.size();

        // TODO: Do we need to sort() after updating the array?
      }
    } else {
      BMCWEB_LOG_ERROR << "Received unparsable response from \"" << prefix
                       << "\"";
      // We received a response that was not a json.
      // Notify the user only if we did not receive any valid responses
      // and if the resource collection does not already exist on the
      // aggregating BMC
      if (asyncResp->res.resultInt() != 200) {
        messages::operationFailed(asyncResp->res);
      }
    }
  }  // End processCollectionResponse()

  // Processes the response returned by a satellite BMC and merges any
  // properties whose "@odata.id" value is the URI or either a top level
  // collection or is uptree from a top level collection
  static void processContainsSubordinateResponse(
      const std::string& prefix,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
      crow::Response& resp) {
    // 429 and 502 mean we didn't actually send the request so don't
    // overwrite the response headers in that case
    if ((resp.result() == boost::beast::http::status::too_many_requests) ||
        (resp.result() == boost::beast::http::status::bad_gateway)) {
      return;
    }

    if (resp.resultInt() != 200) {
      BMCWEB_LOG_DEBUG << "Resource uptree from Collection does not exist in "
                       << "satellite BMC \"" << prefix << "\"";
      // Return the error if we haven't had any successes
      if (asyncResp->res.resultInt() != 200) {
        asyncResp->res.result(resp.result());
        asyncResp->res.write(resp.body());
      }
      return;
    }

    // The resp will not have a json component
    // We need to create a json from resp's stringResponse
    std::string_view contentType = resp.getHeaderValue("Content-Type");
    if (boost::iequals(contentType, "application/json") ||
        boost::iequals(contentType, "application/json; charset=utf-8")) {
      bool addedLinks = false;
      nlohmann::json jsonVal =
          nlohmann::json::parse(resp.body(), nullptr, false);
      if (jsonVal.is_discarded()) {
        BMCWEB_LOG_ERROR << "Error parsing satellite response as JSON";

        // Notify the user if doing so won't overwrite a valid response
        if (asyncResp->res.resultInt() != 200) {
          messages::operationFailed(asyncResp->res);
        }
        return;
      }

      BMCWEB_LOG_DEBUG << "Successfully parsed satellite response";

      // Parse response and add properties missing from the AsyncResp
      // Valid properties will be of the form <property>.@odata.id and
      // @odata.id is a <URI>.  In other words, the json should contain
      // multiple properties such that
      // {"<property>":{"@odata.id": "<URI>"}}
      nlohmann::json::object_t* object =
          jsonVal.get_ptr<nlohmann::json::object_t*>();
      if (object == nullptr) {
        BMCWEB_LOG_ERROR << "Parsed JSON was not an object?";
        return;
      }

      for (std::pair<const std::string, nlohmann::json>& prop : *object) {
        if (!prop.second.contains("@odata.id")) {
          continue;
        }

        std::string* strValue =
            prop.second["@odata.id"].get_ptr<std::string*>();
        if (strValue == nullptr) {
          BMCWEB_LOG_CRITICAL << "Field wasn't a string????";
          continue;
        }
        if (!searchCollectionsArray(*strValue, SearchType::CollOrCon)) {
          continue;
        }

        addedLinks = true;
        if (!asyncResp->res.jsonValue.contains(prop.first)) {
          // Only add the property if it did not already exist
          BMCWEB_LOG_DEBUG << "Adding link for " << *strValue << " from BMC "
                           << prefix;
          asyncResp->res.jsonValue[prop.first]["@odata.id"] = *strValue;
          continue;
        }
      }

      // If we added links to a previously unsuccessful (non-200) response
      // then we need to make sure the response contains the bare minimum
      // amount of additional information that we'd expect to have been
      // populated.
      if (addedLinks && (asyncResp->res.resultInt() != 200)) {
        // This resource didn't locally exist or an error
        // occurred while generating the response.  Remove any
        // error messages and update the error code.
        asyncResp->res.jsonValue.erase(asyncResp->res.jsonValue.find("error"));
        asyncResp->res.result(resp.result());

        const auto& it1 = object->find("@odata.id");
        if (it1 != object->end()) {
          asyncResp->res.jsonValue["@odata.id"] = (it1->second);
        }
        const auto& it2 = object->find("@odata.type");
        if (it2 != object->end()) {
          asyncResp->res.jsonValue["@odata.type"] = (it2->second);
        }
        const auto& it3 = object->find("Id");
        if (it3 != object->end()) {
          asyncResp->res.jsonValue["Id"] = (it3->second);
        }
        const auto& it4 = object->find("Name");
        if (it4 != object->end()) {
          asyncResp->res.jsonValue["Name"] = (it4->second);
        }
      }
    } else {
      BMCWEB_LOG_ERROR << "Received unparsable response from \"" << prefix
                       << "\"";
      // We received as response that was not a json
      // Notify the user only if we did not receive any valid responses,
      // and if the resource does not already exist on the aggregating BMC
      if (asyncResp->res.resultInt() != 200) {
        messages::operationFailed(asyncResp->res);
      }
    }
  }

  // Entry point to Redfish Aggregation
  // Returns Result stating whether or not we still need to locally handle the
  // request
  static Result beginAggregation(
      const crow::Request& thisReq,
      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
    using crow::utility::OrMorePaths;
    using crow::utility::readUrlSegments;
    const boost::urls::url_view url = thisReq.url();

    // We don't need to aggregate JsonSchemas due to potential issues such
    // as version mismatches between aggregator and satellite BMCs.  For
    // now assume that the aggregator has all the schemas and versions that
    // the aggregated server has.
    if (crow::utility::readUrlSegments(url, "redfish", "v1", "JsonSchemas",
                                       crow::utility::OrMorePaths())) {
      return Result::LocalHandle;
    }

    // The first two segments should be "/redfish/v1".  We need to check
    // that before we can search topCollections
    if (!crow::utility::readUrlSegments(url, "redfish", "v1",
                                        crow::utility::OrMorePaths())) {
      return Result::LocalHandle;
    }

    // Parse the URI to see if it begins with a known top level collection
    // such as:
    // /redfish/v1/Chassis
    // /redfish/v1/UpdateService/FirmwareInventory
    const boost::urls::segments_view urlSegments = url.segments();
    boost::urls::url currentUrl("/");
    boost::urls::segments_view::iterator it = urlSegments.begin();
    const boost::urls::segments_view::const_iterator end = urlSegments.end();

    // Skip past the leading "/redfish/v1"
    it++;
    it++;
    for (; it != end; it++) {
      const std::string& collectionItem = *it;
      if (std::binary_search(topCollections.begin(), topCollections.end(),
                             currentUrl.buffer())) {
        // We've matched a resource collection so this current segment
        // might contain an aggregation prefix
        // TODO: This needs to be rethought when we can support multiple
        // satellites due to
        // /redfish/v1/AggregationService/AggregationSources/5B247A
        // being a local resource describing the satellite
        if (collectionItem.starts_with("5B247A_") ||
            isMemberStartsWithKnownPrefix(collectionItem)) {
          BMCWEB_LOG_DEBUG << "Need to forward a request";

          // Extract the prefix from the request's URI, retrieve the
          // associated satellite config information, and then forward
          // the request to that satellite.
          startAggregation(AggregationType::Resource, thisReq, asyncResp);
          return Result::NoLocalHandle;
        }

        // Handle collection URI with a trailing backslash
        // e.g. /redfish/v1/Chassis/
        it++;
        if ((it == end) && collectionItem.empty()) {
          startAggregation(AggregationType::Collection, thisReq, asyncResp);
        }

        // We didn't recognize the prefix or it's a collection with a
        // trailing "/".  In both cases we still want to locally handle
        // the request
        return Result::LocalHandle;
      }

      currentUrl.segments().push_back(collectionItem);
    }

    // If we made it here then currentUrl could contain a top level
    // collection URI without a trailing "/", e.g. /redfish/v1/Chassis
    if (std::binary_search(topCollections.begin(), topCollections.end(),
                           currentUrl.buffer())) {
      startAggregation(AggregationType::Collection, thisReq, asyncResp);
      return Result::LocalHandle;
    }

    // If nothing else then the request could be for a resource which has a
    // top level collection as a subordinate
    if (searchCollectionsArray(url.buffer(), SearchType::ContainsSubordinate)) {
      startAggregation(AggregationType::ContainsSubordinate, thisReq,
                       asyncResp);
      return Result::LocalHandle;
    }

    BMCWEB_LOG_DEBUG << "Aggregation not required";
    return Result::LocalHandle;
  }
};

}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_REDFISH_AGGREGATOR_H_
