#pragma once

#include "bmcweb_config.h"

#include "aggregation_utils.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "http_client.hpp"
#include "http_connection.hpp"
#include "managed_store.hpp"
#include "request_stats.hpp"

#include <boost/algorithm/string/predicate.hpp>

#include <array>
#include <cstdint>
#include <random>

#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);
    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"});
        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;
    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;
            }

            // Recusively 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}];
                }
            }
        }

        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
