#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_COMPONENT_INTEGRITY_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_COMPONENT_INTEGRITY_H_

/*
// Copyright (c) 2024 Google
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include <algorithm>
#include <array>
#include <ctime>
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <regex>  // NOLINT
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

#include "boost/container/flat_map.hpp"  // NOLINT
#include "boost/system/error_code.hpp"  // NOLINT
#include "boost/url/format.hpp"  // NOLINT
#include "app.hpp"
#include "http_request.hpp"
#include "logging.hpp"
#include "parsing.hpp"
#include "utility.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "chassis_utils.hpp"
#include "collection.hpp"
#include "dbus_utils.hpp"
#include "json_utils.hpp"
#include "system_utils.hpp"
#include <nlohmann/json.hpp>
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/message/native_types.hpp"
#include "sdbusplus/unpack_properties.hpp"

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

namespace redfish {
// Interfaces which imply a D-Bus object represents a ComponentIntegrity
constexpr std::array<std::string_view, 3> componentIntegrityInterfaces = {
    "xyz.openbmc_project.Attestation.ComponentIntegrity",
    "xyz.openbmc_project.Attestation.MeasurementSet",
    "xyz.openbmc_project.Attestation.IdentityAuthentication"};
constexpr std::array<std::string_view, 1> networkAdapterInterfaces = {
    "xyz.openbmc_project.Inventory.Item.NetworkAdapter"};
constexpr std::array<std::string_view, 3> processorsInterfaces = {
    "xyz.openbmc_project.Inventory.Item.Cpu",
    "xyz.openbmc_project.Inventory.Item.Accelerator",
    "xyz.openbmc_project.Configuration.Processor"};

constexpr char const* spdmSecurityTechnologyType =
    "xyz.openbmc_project.Attestation.ComponentIntegrity.SecurityTechnologyType."
    "SPDM";
constexpr char const* tpmSecurityTechnologyType =
    "xyz.openbmc_project.Attestation.ComponentIntegrity.SecurityTechnologyType."
    "TPM";
constexpr char const* oemSecurityTechnologyType =
    "xyz.openbmc_project.Attestation.ComponentIntegrity.SecurityTechnologyType."
    "OEM";
constexpr char const* successVerificationStatus =
    "xyz.openbmc_project.Attestation.IdentityAuthentication.VerificationStatus."
    "Success";
constexpr char const* attestationComponentIntegrityIntf =
    "xyz.openbmc_project.Attestation.ComponentIntegrity";
constexpr char const* attestationIntegrityAuthIntf =
    "xyz.openbmc_project.Attestation.IdentityAuthentication";
constexpr char const* attestationMeasurementSetIntf =
    "xyz.openbmc_project.Attestation.MeasurementSet";

inline std::string getTrustedComponent(const std::string& dbusPath) {
  std::string chassis;
  std::string component;

  // Map D-Bus object path to the Redfish URI
  // Example targetComponentURI
  //     "/xyz/openbmc_project/Chassis/chassis01/TrustedComponent/tc01"
  // which should maps to
  //     "/redfish/v1/Chassis/chassis01/TrustedComponent/tc01"

  // These regexes derived on the rules here:
  // https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
  static const std::regex validPath(
      "/xyz/openbmc_project/Chassis/([A-Za-z0-9_]+)/TrustedComponents/"
      "([A-Za-z0-9_]+)");
  std::smatch matches;

  if (regex_match(dbusPath, matches, validPath)) {
    chassis = matches[1];
    component = matches[2];
  } else {
    BMCWEB_LOG_ERROR << "Can't parse TrustedComponent object path:" << dbusPath;
    return "";
  }

  boost::urls::url uri = crow::utility::urlFromPieces(
      "redfish", "v1", "Chassis", chassis, "TrustedComponents", component);
  std::string trustedComponent(uri.c_str());

  return trustedComponent;
}

inline std::optional<nlohmann::json> getChassisCert(
    const std::string& dbusPath) {
  nlohmann::json::object_t certObj;
  std::string chassis;
  std::string cert;

  // Map D-Bus object to Redfish URI
  // Example chassis cert object path:
  //     "/xyz/openbmc_project/certs/chassis/chassis01/cert01"
  // which should maps to:
  //     "/redfish/v1/Chassis/chassis01/Certificates/cert01"

  // These regexes derived on the rules here:
  // https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
  static const std::regex validPath(
      "/xyz/openbmc_project/certs/chassis/([A-Za-z0-9_]+)/([A-Za-z0-9_]+)");
  std::smatch matches;

  if (regex_match(dbusPath, matches, validPath)) {
    chassis = matches[1];
    cert = matches[2];
  } else {
    BMCWEB_LOG_ERROR << "Can't parse DBus certificate object path:" << dbusPath;
    return std::nullopt;
  }

  certObj["@odata.id"] = crow::utility::urlFromPieces(
      "redfish", "v1", "Chassis", chassis, "Certificates", cert);

  return {std::move(certObj)};
}

inline void getProtectedComponentsInfo(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& currentObjPath, const boost::system::error_code& ec,
    const dbus::utility::MapperEndPoints& protectedComponentObjPaths) {
  if (ec) {
    if (ec.value() != EBADR) {
      BMCWEB_LOG_ERROR << "DBUS response error " << ec;
      messages::internalError(asyncResp->res);
    }
    return;
  }

  if (protectedComponentObjPaths.empty()) {
    return;
  }

  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  for (const auto& objpath : protectedComponentObjPaths) {
    sdbusplus::message::object_path protectedComponentObjPath(objpath);
    const std::string objName = protectedComponentObjPath.filename();
    if (objName.empty()) {
      BMCWEB_LOG_WARNING << "Malformed protected component object path "
                         << protectedComponentObjPath.str << " for "
                         << currentObjPath;
      continue;
    }
    managedStore::GetManagedObjectStore()->getDbusObject(
        objpath, {}, requestContext,
        [asyncResp, protectedComponentObjPath, currentObjPath, requestContext,
         objName](const boost::system::error_code& ec2,
                  const dbus::utility::MapperGetObject& object) {
          if (ec2) {
            BMCWEB_LOG_ERROR << "DBUS response error";
            messages::internalError(asyncResp->res);
            return;
          }

          nlohmann::json& jValue =
              asyncResp->res.jsonValue["Links"]["ComponentsProtected"];

          if (!jValue.is_array()) {
            // Create the array if it was empty
            jValue = nlohmann::json::array();
          }

          // Link can be Chassis or Board, Processor, and NetworkAdapters
          // handle Chassis or Board case
          if (redfish::dbus_utils::findInterfacesInServiceMap(
                  object, redfish::chassis_utils::chassisInterfaces)) {
            nlohmann::json link;
            link["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Chassis", objName);
            jValue.push_back(std::move(link));
            return;
          }

          // handle NetworkAdaptors: parent resource can only be Chassis.
          if (redfish::dbus_utils::findInterfacesInServiceMap(
                  object, networkAdapterInterfaces)) {
            const std::string parentObj =
                protectedComponentObjPath.parent_path().filename();
            if (parentObj.empty()) {
              BMCWEB_LOG_WARNING << "Malformed protectedComponent object path "
                                 << protectedComponentObjPath.str << " for "
                                 << currentObjPath;
              return;
            }

            nlohmann::json link;
            link["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Chassis", parentObj, "NetworkAdapters",
                objName);
            jValue.push_back(std::move(link));
            return;
          }

          if (redfish::dbus_utils::findInterfacesInServiceMap(
                  object, processorsInterfaces)) {
            std::string parentPath =
                protectedComponentObjPath.parent_path().str;
            std::string parentObj =
                protectedComponentObjPath.parent_path().filename();
            // e.g.,
            // /xyz/openbmc_project/inventory/system/board/BoardName/system1/chassis/motherboard/cpu0
            // filter out chassis|motherboard in object path.
            while (parentObj == "motherboard" || parentObj == "chassis") {
              sdbusplus::message::object_path tempObjPath(parentPath);
              parentPath = tempObjPath.parent_path().str;
              parentObj = tempObjPath.parent_path().filename();
            }
            if (parentObj.empty()) {
              BMCWEB_LOG_WARNING << "Malformed protectedComponentObjPath "
                                 << protectedComponentObjPath.str << " for "
                                 << currentObjPath;
              return;
            }
            managedStore::GetManagedObjectStore()->getDbusObject(
                parentPath, {}, requestContext,
                [asyncResp, objName, parentObj](
                    const boost::system::error_code& ec2,
                    const dbus::utility::MapperGetObject& object) {
                  if (ec2) {
                    BMCWEB_LOG_ERROR << "DBUS response error";
                    messages::internalError(asyncResp->res);
                    return;
                  }

                  nlohmann::json& jValue =
                      asyncResp->res.jsonValue["Links"]["ComponentsProtected"];
                  if (!jValue.is_array()) {
                    // Create the array if it was empty
                    jValue = nlohmann::json::array();
                  }

                  // handle Processor: parent resource has to be Systems as
                  // OpenBMC only search for Processor under Systems though
                  // Redfish SPEC allows Processors to be modeled under Chassis
                  // starting from DSP2046_2022.3.pdf.
                  std::string parentResourceType;
                  std::string parentResourceName;
                  if (redfish::dbus_utils::findInterfacesInServiceMap(
                          object, redfish::chassis_utils::chassisInterfaces)) {
                    parentResourceType = "Systems";
                    parentResourceName = "system";
                  } else if (redfish::dbus_utils::findInterfacesInServiceMap(
                                 object,
                                 redfish::system_utils::systemInterfaces)) {
                    parentResourceType = "Systems";
                    parentResourceName = parentObj;
                  } else {
                    BMCWEB_LOG_ERROR << "Parent resource type not "
                                        "supported for Processor resource";
                    messages::internalError(asyncResp->res);
                    return;
                  }

                  nlohmann::json link;
                  link["@odata.id"] = crow::utility::urlFromPieces(
                      "redfish", "v1", parentResourceType, parentResourceName,
                      "Processors", objName);
                  jValue.push_back(std::move(link));
                  return;
                });

            return;
          }  // end of Processor interfaces handling

          // Unsupported resource type
          BMCWEB_LOG_ERROR << "Unsupported ComponentsProtected resource for "
                           << protectedComponentObjPath.str;
          messages::internalError(asyncResp->res);
          return;
        });
  }
}

/**
 * @brief Fill out ComponentIntegrity related info by
 * requesting data from the given D-Bus object.
 *
 * @param[in,out]   aResp       Async HTTP response.
 * @param[in]       service     D-Bus service to query.
 * @param[in]       objPath     D-Bus object to query.
 */
inline void getComponentIntegrityData(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& service,
    const std::string& objPath) {
  BMCWEB_LOG_DEBUG << "Get ComponentIntegrity Data";
  managedStore::ManagedObjectStoreContext context(aResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      service, objPath, attestationComponentIntegrityIntf, context,
      [objPath, aResp{aResp}, context](
          const boost::system::error_code& ec,
          const std::vector<std::pair<
              std::string, dbus::utility::DbusVariantType>>& properties) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "DBUS response error";
          messages::internalError(aResp->res);
          return;
        }

        const bool* enabled = nullptr;
        const std::string* type = nullptr;
        const std::string* typeVersion = nullptr;
        const std::uint64_t* lastUpdated = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), properties, "Enabled", enabled,
            "Type", type, "TypeVersion", typeVersion, "LastUpdated",
            lastUpdated);

        if (!success) {
          messages::internalError(aResp->res);
          return;
        }

        if (enabled != nullptr) {
          if (*enabled) {
            aResp->res.jsonValue["ComponentIntegrityEnabled"] = true;
          } else {
            aResp->res.jsonValue["ComponentIntegrityEnabled"] = false;
          }
        } else {
          messages::internalError(aResp->res);
          return;
        }

        if ((type != nullptr) && !type->empty()) {
          if (*type == spdmSecurityTechnologyType) {
            aResp->res.jsonValue["ComponentIntegrityType"] = "SPDM";
            aResp->res.jsonValue["Description"] =
                "SPDM-capable RoT physically attached to a device.";
          } else if (*type == tpmSecurityTechnologyType) {
            aResp->res.jsonValue["ComponentIntegrityType"] = "TPM";
            aResp->res.jsonValue["Description"] =
                "TPM physically attached to a device.";
          } else if (*type == oemSecurityTechnologyType) {
            aResp->res.jsonValue["ComponentIntegrityType"] = "OEM";
            aResp->res.jsonValue["Description"] =
                "OEM-specific RoT physically attached to a device.";
          } else {
            messages::internalError(aResp->res);
            return;
          }
        }

        if ((typeVersion != nullptr) && !typeVersion->empty()) {
          aResp->res.jsonValue["ComponentIntegrityTypeVersion"] = *typeVersion;
        }

        if ((lastUpdated != nullptr) && *lastUpdated != 0) {
          time_t ts = static_cast<time_t>(*lastUpdated);
          struct tm tminfo_r;
          const struct tm* tminfo = localtime_r(&ts, &tminfo_r);

          /**
           * The date of component update in ISO 8601 format as
           * YYYYMMDDThhmmssZ. Where 'T' is a literal character to separate
           * date fields from time and 'Z' is a literal character to indicate
           * UTC.
           */
          char iso8601[40];  // NOLINT
          std::strftime(static_cast<char*>(iso8601), sizeof(iso8601),
                        "%Y%m%dT%H%M%SZ", tminfo);
          aResp->res.jsonValue["LastUpdated"] =
              std::string(static_cast<char*>(iso8601));
        }

        // Get trusted components info from associations.
        std::string targetComponentPath = objPath + "/reporting";
        dbus_utils::getAssociationEndPoints(
            targetComponentPath, context,
            [aResp](const boost::system::error_code& e,
                    const dbus::utility::MapperEndPoints&
                        nodeTrustedComponentList) {
              if (e) {
                if (e.value() != EBADR) {
                  messages::internalError(aResp->res);
                  return;
                }
                // No resource found.
                return;
              }

              // One ComponentIntegrity object should be associated with one
              // TrustedComponent object
              if (nodeTrustedComponentList.size() == 1) {
                const std::string& componentURI =
                    nodeTrustedComponentList.at(0);

                std::string targetComponentURI =
                    getTrustedComponent(componentURI);

                if (!targetComponentURI.empty()) {
                  aResp->res.jsonValue["TargetComponentURI"] =
                      targetComponentURI;
                } else {
                  BMCWEB_LOG_ERROR << "Can't parse TargetComponentURI : "
                                   << componentURI;
                  messages::internalError(aResp->res);
                  return;
                }
              } else {
                BMCWEB_LOG_ERROR
                    << "Unexpected TargetComponent #objs (expecting 1): "
                    << nodeTrustedComponentList.size();
                messages::internalError(aResp->res);
                return;
              }
            });

        // Get protected components info from associations.
        std::string protectedComponentPath = objPath + "/authenticating";
        dbus_utils::getAssociationEndPoints(
            protectedComponentPath, context,
            std::bind_front(getProtectedComponentsInfo, aResp, objPath));
      });
}

/**
 * @brief Fill out {ComponentIntegrityId}#/SPDM/IdentityAuthentication
 * related info by requesting data from the given D-Bus object.
 *
 * @param[in,out]   aResp       Async HTTP response.
 * @param[in]       service     D-Bus service to query.
 * @param[in]       objPath     D-Bus object to query.
 */
inline void getSPDMAuthenticationData(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp, const std::string& service,
    const std::string& objPath) {
  BMCWEB_LOG_DEBUG
      << "Get {ComponentIntegrityId}#/SPDM/IdentyAuthentication Data";
  managedStore::ManagedObjectStoreContext context(aResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      service, objPath, attestationIntegrityAuthIntf, context,
      [objPath, aResp{aResp}, context](
          const boost::system::error_code& ec,
          const std::vector<std::pair<
              std::string, dbus::utility::DbusVariantType>>& properties) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error!";
          messages::internalError(aResp->res);
          return;
        }

        const std::string* respStatus = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), properties,
            "ResponderVerificationStatus", respStatus);

        if (!success) {
          messages::internalError(aResp->res);
          return;
        }

        if (respStatus != nullptr && !respStatus->empty()) {
          if (*respStatus == successVerificationStatus) {
            aResp->res
                .jsonValue["SPDM"]["IdentityAuthentication"]
                          ["ResponderAuthentication"]["VerificationStatus"] =
                "Success";
          } else {
            aResp->res
                .jsonValue["SPDM"]["IdentityAuthentication"]
                          ["ResponderAuthentication"]["VerificationStatus"] =
                "Failed";
          }
        }

        // Get associated certs objects.
        std::string reqCertPath = objPath + "/requester_identified_by";
        dbus_utils::getAssociationEndPoints(
            reqCertPath, context,
            [aResp](const boost::system::error_code& e,
                    const dbus::utility::MapperEndPoints& nodeReqCertList) {
              if (e) {
                if (e.value() != EBADR) {
                  messages::internalError(aResp->res);
                  return;
                }
                // No resource found.
                return;
              }

              nlohmann::json& json = aResp->res.jsonValue;

              // One ComponentIntegrity object should be associated with one
              // requester certificate object or none
              if (nodeReqCertList.empty()) {
                return;
              }

              if (nodeReqCertList.size() > 1) {
                BMCWEB_LOG_ERROR << "More than one requester cert provided!";
                messages::internalError(aResp->res);
                return;
              }

              // There is one valid cert, handle it
              const std::string& certPath = nodeReqCertList.at(0);

              std::optional<nlohmann::json> reqCertObj =
                  getChassisCert(certPath);

              if (reqCertObj != std::nullopt) {
                json["SPDM"]["IdentityAuthentication"]
                    ["RequesterAuthentication"]["ProvidedCertificate"] =
                        *reqCertObj;
              } else {
                // Requester Cert is not required, no need to report error.
                BMCWEB_LOG_DEBUG << "Unable to parse requester certPath: "
                                 << certPath;
              }
            });

        // Get associated response certs objects.
        std::string respCertPath = objPath + "/responder_identified_by";
        dbus_utils::getAssociationEndPoints(
            respCertPath, context,
            [aResp](const boost::system::error_code& e,
                    const dbus::utility::MapperEndPoints& nodeRespCertList) {
              if (e) {
                if (e.value() != EBADR) {
                  messages::internalError(aResp->res);
                  return;
                }
                // No resource found.
                return;
              }

              nlohmann::json& json = aResp->res.jsonValue;

              // One ComponentIntegrity object should be associated with one
              // responder certificate object
              if (nodeRespCertList.size() != 1) {
                BMCWEB_LOG_ERROR
                    << "Unexpected Responder Cert #objs (expecting 1): "
                    << nodeRespCertList.size();
                messages::internalError(aResp->res);
                return;
              }

              const std::string& certPath = nodeRespCertList.at(0);

              std::optional<nlohmann::json> respCertObj =
                  getChassisCert(certPath);

              if (respCertObj != std::nullopt) {
                json["SPDM"]["IdentityAuthentication"]
                    ["ResponderAuthentication"]["ComponentCertificate"] =
                        *respCertObj;
              } else {
                BMCWEB_LOG_ERROR << "Unable to parse responder certPath: "
                                 << certPath;
                messages::internalError(aResp->res);
                return;
              }
            });
      });
}

inline void getComponentData(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& objectPath,
    const dbus::utility::MapperServiceMap& serviceMap) {
  for (const auto& [serviceName, interfaceList] : serviceMap) {
    for (const auto& interface : interfaceList) {
      if (interface == attestationComponentIntegrityIntf) {
        getComponentIntegrityData(aResp, serviceName, objectPath);
      } else if (interface == attestationIntegrityAuthIntf) {
        getSPDMAuthenticationData(aResp, serviceName, objectPath);
      }
    }
  }
}

inline void addSPDMGetSignedMeasurementsLinks(nlohmann::json& getMeasurement,
                                              const std::string& componentId) {
  getMeasurement["target"] = crow::utility::urlFromPieces(
      "redfish", "v1", "ComponentIntegrity", componentId, "Actions",
      "ComponentIntegrity.SPDMGetSignedMeasurements");
  getMeasurement["@Redfish.ActionInfo"] = crow::utility::urlFromPieces(
      "redfish", "v1", "ComponentIntegrity", componentId,
      "SPDMGetSignedMeasurementsActionInfo");
}

/**
 * Find the D-Bus object representing the requested ComponentIntegrity,
 * and call the handler with the results. If matching object is not
 * found, add 404 error to response and don't call the handler.
 *
 * @param[in,out]   resp            Async HTTP response.
 * @param[in]       processorId     Redfish Processor Id.
 * @param[in]       handler         Callback to continue processing request upon
 *                                  successfully finding object.
 */
template <typename Handler>
inline void getComponentObject(const std::shared_ptr<bmcweb::AsyncResp>& resp,
                               const std::string& componentId,
                               Handler&& handler) {
  BMCWEB_LOG_DEBUG << "Get available system component integrity resources.";

  // GetSubTree on all interfaces which provide info about a
  // component_integrity.
  managedStore::ManagedObjectStoreContext context(resp);
  managedStore::GetManagedObjectStore()->getSubTree(
      "/xyz/openbmc_project/ComponentIntegrity/", 0,
      componentIntegrityInterfaces, context,
      [resp, componentId, handler](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::internalError(resp->res);
          return;
        }
        for (const auto& [objectPath, serviceMap] : subtree) {
          // Ignore any objects which don't end with our desired
          // componentintegrity name
          if (!objectPath.ends_with(componentId)) {
            continue;
          }

          bool found = false;
          // Filter out objects that don't have the
          // ComponentIntegrity-specific interfaces to make sure we can return
          // 404 on non-ComponentIntegrity
          for (const auto& [serviceName, interfaceList] : serviceMap) {
            if (std::find_first_of(interfaceList.begin(), interfaceList.end(),
                                   componentIntegrityInterfaces.begin(),
                                   componentIntegrityInterfaces.end()) !=
                interfaceList.end()) {
              found = true;
              break;
            }
          }

          if (!found) {
            continue;
          }

          // Matching component found
          resp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
              "redfish", "v1", "ComponentIntegrity", componentId);

          resp->res.jsonValue["Name"] = "Component Integrity";
          resp->res.jsonValue["Id"] = componentId;
          resp->res.jsonValue["SPDM"]["Requester"]["@odata.id"] =
              crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc");

          addSPDMGetSignedMeasurementsLinks(
              resp->res
                  .jsonValue["Actions"]
                            ["#ComponentIntegrity.SPDMGetSignedMeasurements"],
              componentId);

          handler(objectPath, serviceMap);
          return;
        }
        messages::resourceNotFound(resp->res, "ComponentIntegrity",
                                   componentId);
      });
}

inline void handleComponentIntegrityCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.type"] =
      "#ComponentIntegrityCollection.ComponentIntegrityCollection";
  asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/ComponentIntegrity";
  asyncResp->res.jsonValue["Name"] = "Component Integrity Collection";
  asyncResp->res.jsonValue["Description"] = "Collection of Component Integrity";

  collection_util::getCollectionMembers(
      asyncResp, boost::urls::url("/redfish/v1/ComponentIntegrity"),
      componentIntegrityInterfaces, "/xyz/openbmc_project/ComponentIntegrity");
}

inline void handleComponentIntegrityGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& componentId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.addHeader(boost::beast::http::field::link,
                           "</redfish/v1/JsonSchemas/ComponentIntegrity/"
                           "ComponentIntegrity.json>; rel=describedby");
  asyncResp->res.jsonValue["@odata.type"] =
      "#ComponentIntegrity.v1_2_0.ComponentIntegrity";

  getComponentObject(asyncResp, componentId,
                     std::bind_front(getComponentData, asyncResp));
}

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

  asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_3_0.ActionInfo";
  asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
      "redfish", "v1", "ComponentIntegrity", componentId,
      "SPDMGetSignedMeasurementsActionInfo");

  asyncResp->res.jsonValue["Name"] = "SPDMGetSignedMeasurements Action Info";
  asyncResp->res.jsonValue["Id"] = "SPDMGetSignedMeasurementsActionInfo";

  nlohmann::json::array_t parameters;
  nlohmann::json::object_t indices;
  nlohmann::json::object_t nonce;
  nlohmann::json::object_t slotId;

  indices["Name"] = "MeasurementIndices";
  indices["Required"] = false;
  indices["DataType"] = "NumberArray";

  nonce["Name"] = "Nonce";
  nonce["Required"] = false;
  nonce["DataType"] = "String";

  slotId["Name"] = "SlotId";
  slotId["Required"] = false;
  slotId["DataType"] = "Number";

  parameters.emplace_back(std::move(indices));
  parameters.emplace_back(std::move(nonce));
  parameters.emplace_back(std::move(slotId));
  asyncResp->res.jsonValue["Parameters"] = std::move(parameters);
}

inline void handleComponentIntegritySPDMGetSignedMeasurementsActionPost(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& componentId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  BMCWEB_LOG_DEBUG << "Post ComponentIntegrity SPDMGetSignedMeasurements.";

  // GetSubTree on interfaces which provide info about certificate.
  constexpr std::array<std::string_view, 1> interfaces = {
      attestationMeasurementSetIntf};

  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTree(
      "/xyz/openbmc_project/ComponentIntegrity/", 0, interfaces, context,
      [asyncResp, req, componentId](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        std::string ciPath =
            std::string("/xyz/openbmc_project/ComponentIntegrity/") +
            componentId;

        nlohmann::json reqJson;
        JsonParseResult ret = parseRequestAsJson(req, reqJson);
        if (ret != JsonParseResult::Success) {
          // We did not receive JSON request, proceed as it is RAW data
          BMCWEB_LOG_ERROR << "Parse json request failed!";
          messages::internalError(asyncResp->res);
          return;
        }

        // All fields below are optional by DMTF DSP2046_2022.3.pdf
        // default nonce empty, libspdm will generate one.
        std::optional<std::string> optNonce = "";
        // default 0 indicates using slot 0.
        std::optional<size_t> optSlotId = 0;
        // default 255(0xff) indicates requesting all measurement blocks.
        std::optional<std::vector<size_t>> optMeasurementIndices =
            std::vector<size_t>{255};

        // readJsonPatch will move on when some fields are missing, we only
        // use default value for missing fields.
        if (!json_util::readJsonPatch(
                req, asyncResp->res, "SlotId", optSlotId, "MeasurementIndices",
                optMeasurementIndices, "Nonce", optNonce)) {
          BMCWEB_LOG_DEBUG << "Using default only for missing params!";
        }

        for (const auto& [objectPath, serviceMap] : subtree) {
          // Ignore any objects which don't match component integrity
          if (objectPath.find(ciPath) == std::string::npos) {
            continue;
          }

          // Should only match one service and one object
          for (const auto& [serviceName, interfaceList] : serviceMap) {
            // SPDMGetSignedMeasurements Response
            managedStore::GetManagedObjectStore()
                ->PostDbusCallToIoContextThreadSafe(
                    asyncResp->strand_,
                    [asyncResp](const boost::system::error_code& e,
                                const sdbusplus::message::object_path& certPath,
                                const std::string& hashAlg,
                                const std::string& pubkey,
                                const std::string& signedMeasurements,
                                const std::string& signAlg,
                                const std::string& version) {
                      if (e) {
                        BMCWEB_LOG_ERROR << "DBUS response error: "
                                         << e.message();
                        messages::internalError(asyncResp->res);
                        return;
                      }

                      asyncResp->res.jsonValue["@odata.type"] =
                          "#ComponentIntegrity.v1_0_0."
                          "SPDMGetSignedMeasurementsResponse";
                      asyncResp->res.jsonValue["Version"] = version;
                      asyncResp->res.jsonValue["HashingAlgorithm"] = hashAlg;
                      asyncResp->res.jsonValue["SigningAlgorithm"] = signAlg;
                      asyncResp->res.jsonValue["SignedMeasurements"] =
                          signedMeasurements;
                      asyncResp->res.jsonValue["PublicKey"] = pubkey;

                      // handle Device Certificate
                      std::optional<nlohmann::json> certObj =
                          getChassisCert(certPath);

                      if (certObj != std::nullopt) {
                        asyncResp->res.jsonValue["Certificate"] = *certObj;
                      } else {
                        BMCWEB_LOG_ERROR << "Unable to parse certPath: "
                                         << std::string(certPath);
                        messages::internalError(asyncResp->res);
                        return;
                      }
                    },
                    serviceName, ciPath,
                    "xyz.openbmc_project.Attestation.MeasurementSet",
                    "SPDMGetSignedMeasurements", *optMeasurementIndices,
                    *optNonce, *optSlotId);
          }
        }
      });
}

inline void requestRoutesComponentIntegrityCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/ComponentIntegrity/")
      .privileges(redfish::privileges::getComponentIntegrityCollection)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleComponentIntegrityCollectionGet, std::ref(app)));
}

inline void requestRoutesComponentIntegrity(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/ComponentIntegrity/<str>/")
      .privileges(redfish::privileges::getComponentIntegrity)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleComponentIntegrityGet, std::ref(app)));
}

inline void requestRoutesComponentIntegritySPDMGetSignedMeasurementsActionInfo(
    App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/ComponentIntegrity/<str>/"
               "SPDMGetSignedMeasurementsActionInfo")
      .privileges(redfish::privileges::getActionInfo)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleSPDMGetSignedMeasurementsActionInfoGet, std::ref(app)));
}

inline void requestRoutesComponentIntegritySPDMGetSignedMeasurementsAction(
    App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/ComponentIntegrity/<str>/Actions/"
               "ComponentIntegrity.SPDMGetSignedMeasurements/")
      .privileges(redfish::privileges::getComponentIntegrity)
      .methods(boost::beast::http::verb::post)(std::bind_front(
          handleComponentIntegritySPDMGetSignedMeasurementsActionPost,
          std::ref(app)));
}

}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_COMPONENT_INTEGRITY_H_
