#ifndef THIRD_PARTY_GBMCWEB_INCLUDE_GOOGLE_GOOGLE_SERVICE_ROOT_H_
#define THIRD_PARTY_GBMCWEB_INCLUDE_GOOGLE_GOOGLE_SERVICE_ROOT_H_

#include <array>
#include <cstdint>
#include <cstring>
#include <filesystem>  // NOLINT
#include <functional>
#include <memory>
#include <optional>
#include <regex>  // NOLINT
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "absl/functional/any_invocable.h"
#include "absl/status/statusor.h"
#include "boost/system/error_code.hpp"  // NOLINT
#include "app.hpp"
#include "http_request.hpp"
#include "logging.hpp"
#include "utility.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "query.hpp"
#include "chassis_utils.hpp"
#include "collection.hpp"
#include "dbus_utils.hpp"
#include "hex_utils.hpp"
#include "json_utils.hpp"
#include "location_utils.hpp"
#include <nlohmann/json.hpp>
#include "tlbmc/credentials/credential_manager.h"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/message/native_types.hpp"
#include "sdbusplus/unpack_properties.hpp"
#include <openssl/evp.h>
#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp"  // NOLINT
#endif

namespace crow {
namespace google_api {

inline void handleGoogleV1Get(
    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"] =
      "#GoogleServiceRoot.v1_0_0.GoogleServiceRoot";
  asyncResp->res.jsonValue["@odata.id"] = "/google/v1";
  asyncResp->res.jsonValue["Id"] = "Google Rest RootService";
  asyncResp->res.jsonValue["Name"] = "Google Service Root";
  asyncResp->res.jsonValue["Version"] = "1.0.0";
  asyncResp->res.jsonValue["RootOfTrustCollection"]["@odata.id"] =
      "/google/v1/RootOfTrustCollection";
  asyncResp->res.jsonValue["NVMe"]["@odata.id"] = "/google/v1/NVMe";
}

inline void handleRootOfTrustCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.id"] = "/google/v1/RootOfTrustCollection";
  asyncResp->res.jsonValue["@odata.type"] =
      "#RootOfTrustCollection.RootOfTrustCollection";
  const std::array<std::string_view, 1> interfaces{
      "xyz.openbmc_project.Control.Hoth"};
  redfish::collection_util::getCollectionMembers(
      asyncResp, boost::urls::url("/google/v1/RootOfTrustCollection"),
      interfaces, "/xyz/openbmc_project");
}

struct PcrQuoteParams {
  std::string pcrSelectionBase64;
  std::string nonceHex;
};

// Helper struct to identify a resolved D-Bus object interface
struct ResolvedEntity {
  std::string id;
  std::string service;
  std::string object;
  std::string interface;
};

template <typename CommandT, typename HandlerFunc>
inline void hothGetSubtreeCallback(
    const CommandT& command,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& rotId, const HandlerFunc& entityHandler,
    const boost::system::error_code& ec,
    const dbus::utility::MapperGetSubTreeResponse& subtree) {
  if (ec) {
    redfish::messages::internalError(asyncResp->res);
    return;
  }
  for (const auto& [path, services] : subtree) {
    sdbusplus::message::object_path objPath(path);
    if (objPath.filename() != rotId || services.empty()) {
      continue;
    }

    ResolvedEntity resolvedEntity = {
        .id = rotId,
        .service = services[0].first,
        .object = path,
        .interface = "xyz.openbmc_project.Control.Hoth"};
    entityHandler(command, asyncResp, resolvedEntity);
    return;
  }

  // Couldn't find an object with that name.  return an error
  redfish::messages::resourceNotFound(asyncResp->res, "RootOfTrust", rotId);
}

template <typename CommandT, typename HandlerFunc>
inline void resolveRoT(const CommandT& command,
                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::string& rotId, HandlerFunc entityHandler) {
  constexpr std::array<std::string_view, 1> hothIfaces = {
      "xyz.openbmc_project.Control.Hoth"};
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTree(
      "/xyz/openbmc_project", 0, hothIfaces, requestContext,
      [command, asyncResp, rotId, entityHandler = std::move(entityHandler)](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreeResponse& subtree) {
        hothGetSubtreeCallback(command, asyncResp, rotId, entityHandler, ec,
                               subtree);
      });
}

inline void populateRootOfTrustState(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const dbus::utility::DBusPropertiesMap& properties) {
  const uint32_t* bootloaderUpdateFailureCode = nullptr;
  const uint32_t* firmwareUpdateFailedMinor = nullptr;
  const uint32_t* firmwareUpdateFailureCode = nullptr;
  const uint32_t* payloadConfirmFailureCode = nullptr;
  const uint32_t* payloadUpdateFailureCode = nullptr;
  const uint32_t* resetFlags = nullptr;
  const uint32_t* roInfoStrikes = nullptr;
  const uint32_t* rwInfoStrikes = nullptr;
  const uint64_t* upTime = nullptr;
  const bool* hasPersistentPanicInfo = nullptr;

  const bool* hasValidAuthRecord = nullptr;
  const uint64_t* authRecordCapabilities = nullptr;
  const bool* secureBootEnforced = nullptr;

  const uint32_t* keyRotationVersion = nullptr;
  const uint16_t* keyRotationImageFamily = nullptr;
  const uint16_t* keyRotationImageFamilyVariant = nullptr;
  const uint32_t* keyRotationValidationMethod = nullptr;
  const uint32_t* keyRotationValidationKeyData = nullptr;
  const uint32_t* keyRotationValidationHashData = nullptr;

  const bool success = sdbusplus::unpackPropertiesNoThrow(
      redfish::dbus_utils::UnpackErrorPrinter(), properties,
      "BootloaderUpdateFailureCode", bootloaderUpdateFailureCode,
      "FirmwareUpdateFailedMinor", firmwareUpdateFailedMinor,
      "FirmwareUpdateFailureCode", firmwareUpdateFailureCode,
      "PayloadConfirmFailureCode", payloadConfirmFailureCode,
      "PayloadUpdateFailureCode", payloadUpdateFailureCode, "ResetFlags",
      resetFlags, "RoInfoStrikes", roInfoStrikes, "RwInfoStrikes",
      rwInfoStrikes, "UpTime", upTime, "HasPersistentPanicInfo",
      hasPersistentPanicInfo, "HasValidAuthRecord", hasValidAuthRecord,
      "AuthRecordCapabilities", authRecordCapabilities, "SecureBootEnforced",
      secureBootEnforced, "KeyRotationVersion", keyRotationVersion,
      "KeyRotationImageFamily", keyRotationImageFamily,
      "KeyRotationImageFamilyVariant", keyRotationImageFamilyVariant,
      "KeyRotationValidationMethod", keyRotationValidationMethod,
      "KeyRotationValidationKeyData", keyRotationValidationKeyData,
      "KeyRotationValidationHashData", keyRotationValidationHashData);

  if (!success) {
    BMCWEB_LOG_ERROR << "Failed to populate RootOfTrustState";
    redfish::messages::internalError(asyncResp->res);
    return;
  }

  if (bootloaderUpdateFailureCode != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["BootloaderUpdateFailureCode"] =
        *bootloaderUpdateFailureCode;
  }
  if (firmwareUpdateFailedMinor != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["FirmwareUpdateFailedMinor"] =
        *firmwareUpdateFailedMinor;
  }
  if (firmwareUpdateFailureCode != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["FirmwareUpdateFailureCode"] =
        *firmwareUpdateFailureCode;
  }
  if (resetFlags != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["ResetFlags"] = *resetFlags;
  }
  if (roInfoStrikes != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["RoInfoStrikes"] = *roInfoStrikes;
  }
  if (rwInfoStrikes != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["RwInfoStrikes"] = *rwInfoStrikes;
  }
  if (upTime != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["UpTime"] = *upTime;
  }
  if (hasPersistentPanicInfo != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["HasPersistentPanicInfo"] =
        *hasPersistentPanicInfo;
  }

  if (payloadConfirmFailureCode != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["Payload"]["ConfirmFailureCode"] =
        *payloadConfirmFailureCode;
  }
  if (payloadUpdateFailureCode != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["Payload"]["UpdateFailureCode"] =
        *payloadUpdateFailureCode;
  }
  if (hasValidAuthRecord != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["Authorization"]["Valid"] =
        *hasValidAuthRecord;
  }
  if (authRecordCapabilities != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["Authorization"]["Capabilities"] =
        *authRecordCapabilities;
  }
  if (secureBootEnforced != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["SecureBootEnforced"] =
        *secureBootEnforced;
  }
  if (keyRotationVersion != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["KeyRotation"]["Version"] =
        *keyRotationVersion;
  }
  if (keyRotationImageFamily != nullptr) {
    asyncResp->res.jsonValue["Status"]["Oem"]["KeyRotation"]["ImageFamily"] =
        *keyRotationImageFamily;
  }
  if (keyRotationImageFamilyVariant != nullptr) {
    asyncResp->res
        .jsonValue["Status"]["Oem"]["KeyRotation"]["ImageFamilyVariant"] =
        *keyRotationImageFamilyVariant;
  }
  if (keyRotationValidationMethod != nullptr) {
    asyncResp->res
        .jsonValue["Status"]["Oem"]["KeyRotation"]["ValidationMethod"] =
        *keyRotationValidationMethod;
  }
  if (keyRotationValidationKeyData != nullptr) {
    asyncResp->res
        .jsonValue["Status"]["Oem"]["KeyRotation"]["ValidationKeyData"] =
        *keyRotationValidationKeyData;
  }
  if (keyRotationValidationHashData != nullptr) {
    asyncResp->res
        .jsonValue["Status"]["Oem"]["KeyRotation"]["ValidationHashData"] =
        *keyRotationValidationHashData;
  }
}

inline void populateRootOfTrustEntity(
    const std::string& /*unused*/,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const ResolvedEntity& resolvedEntity) {
  asyncResp->res.jsonValue["@odata.type"] = "#RootOfTrust.v1_0_0.RootOfTrust";
  asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
      "google", "v1", "RootOfTrustCollection", resolvedEntity.id);

  asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
  asyncResp->res.jsonValue["Id"] = resolvedEntity.id;
  // Need to fix this later to a stabler property.
  asyncResp->res.jsonValue["Name"] = resolvedEntity.id;
  asyncResp->res.jsonValue["Description"] = "Google Root Of Trust";

#ifdef BMCWEB_ENABLE_ALLOW_ARBITRARY_COMMAND_TO_ROT
  asyncResp->res.jsonValue["Actions"]["#RootOfTrust.SendCommand"]["target"] =
      "/google/v1/RootOfTrustCollection/" + resolvedEntity.id +
      "/Actions/RootOfTrust.SendCommand";
#endif

  asyncResp->res
      .jsonValue["Actions"]["#RootOfTrust.GenerateSignedCSR"]["target"] =
      "/google/v1/RootOfTrustCollection/" + resolvedEntity.id +
      "/Actions/RootOfTrust.GenerateSignedCSR";

  asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
      resolvedEntity.id;
  asyncResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
      "Embedded";

  // Only link to RW firmware inventory.
  //
  // For USB-Hoth, FirmwareInventory URI is "hoth_${hothId}_rw".
  // For non-USB Hoth, FirmwareInventory URI is "hoth_rw".
  std::string hothFirmware = resolvedEntity.id == "Hoth"
                                 ? "hoth_rw"
                                 : "hoth_" + resolvedEntity.id + "_rw";
  asyncResp->res.jsonValue["Links"]["ActiveSoftwareImage"]["@odata.id"] =
      "/redfish/v1/UpdateService/FirmwareInventory/" + hothFirmware;

  // Temporary hack to get the Hoth firmware family as "Model", by stripping
  // the USB suffix from hothId.
  //
  // Non-USB Hoth has resolvedEntity.id="Hoth" as model name.
  //
  // Once we have SoftwareInventory 1.9.0 supported everywhere, the firmware
  // family should reside there and the model here should be the chip's part
  // number.
  static std::regex hothIdSuffixRe("_[0-9_]+$");
  asyncResp->res.jsonValue["Model"] =
      std::regex_replace(resolvedEntity.id, hothIdSuffixRe, "");

  // Get Hoth properties from Dbus.
  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      resolvedEntity.service, resolvedEntity.object,
      "xyz.openbmc_project.Control.Hoth.State", context,
      [asyncResp](const boost::system::error_code ec2,
                  const dbus::utility::DBusPropertiesMap& properties) {
        if (ec2) {
          BMCWEB_LOG_DEBUG << "DBUS response error " << ec2;
          return;
        }
        populateRootOfTrustState(asyncResp, properties);
      });

  // Get Chassis Link for Devpath from DBus
  managedStore::ManagedObjectStoreContext context2(asyncResp);
  managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
      sdbusplus::message::object_path(resolvedEntity.object) / "contained_by",
      sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
      redfish::chassis_utils::chassisInterfaces, context2,
      [asyncResp](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreePathsResponse& chassisPaths) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
          return;
        }

        if (!chassisPaths.empty()) {
          asyncResp->res.jsonValue["RelatedItem"] = nlohmann::json::array();
        }
        for (const auto& str : chassisPaths) {
          std::filesystem::path chassisPath(str);
          nlohmann::json::object_t relatedChassis;
          relatedChassis["@odata.id"] = crow::utility::urlFromPieces(
              "redfish", "v1", "Chassis", chassisPath.filename().c_str());
          asyncResp->res.jsonValue["RelatedItem"].emplace_back(relatedChassis);
        }
      });

  // Fill PartLocationContext
  redfish::location_util::getPartLocationContext(
      asyncResp, "/Location"_json_pointer,
      resolvedEntity.object + "/contained_by");

  // Get PCR values from securityd
  managedStore::GetManagedObjectStore()->PostDbusCallWithObjectPath(
      asyncResp->strand_,
      absl::AnyInvocable<void(const boost::system::error_code&,
                              const std::string&)>(
          [asyncResp](const boost::system::error_code& ec,
                      const std::string& pcrValuesJson) {
            if (ec) {
              BMCWEB_LOG_ERROR << "Failed to read PCR values: " << ec.message();
              return;
            }
            nlohmann::json measurementsArray =
                nlohmann::json::parse(pcrValuesJson, nullptr, false);
            if (measurementsArray.is_discarded()) {
              BMCWEB_LOG_ERROR << "Failed to parse PCR JSON from D-Bus";
              return;
            }
            asyncResp->res.jsonValue["TPM"]["MeasurementSet"]["Measurements"] =
                std::move(measurementsArray);
          }),
      "xyz.openbmc_project.securityd.TpmAttestationService",
      "/xyz/openbmc_project/securityd/tpm_attestation_service",
      "xyz.openbmc_project.securityd.TpmAttestationService", "ReadPcrValues",
      sdbusplus::message::object_path(resolvedEntity.object));
}

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

inline void invocationCallback(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const boost::system::error_code& ec,
    const std::vector<uint8_t>& responseBytes) {
  if (ec) {
    BMCWEB_LOG_ERROR << "RootOfTrust.Actions.SendCommand failed: "
                     << ec.message();
    redfish::messages::internalError(asyncResp->res);
    return;
  }

  asyncResp->res.jsonValue["CommandResponse"] = bytesToHexString(responseBytes);
}

inline void invokeRoTCommand(
    const std::string& command,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const ResolvedEntity& resolvedEntity) {
  std::vector<uint8_t> bytes = hexStringToBytes(command);
  if (bytes.empty()) {
    BMCWEB_LOG_DEBUG << "Invalid command: " << command;
    redfish::messages::actionParameterValueTypeError(command, "Command",
                                                     "SendCommand");
    return;
  }

  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp{asyncResp}](const boost::system::error_code& ec,
                             const std::vector<uint8_t>& responseBytes) {
        invocationCallback(asyncResp, ec, responseBytes);
      },
      resolvedEntity.service, resolvedEntity.object, resolvedEntity.interface,
      "SendHostCommand", bytes);
}

inline void getSignedMeasurementsInvocationCallback(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const boost::system::error_code& ec, const std::string& responseString) {
  if (ec) {
    BMCWEB_LOG_ERROR << "RootOfTrust.Actions.TPMGetSignedMeasurements failed: "
                     << ec.message();
    redfish::messages::internalError(asyncResp->res);
    return;
  }

  asyncResp->res.jsonValue["SignedMeasurements"] = responseString;
}

inline void invokePcrQuoteSecuritydCommand(
    const PcrQuoteParams& command,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const ResolvedEntity& resolvedEntity) {
  managedStore::GetManagedObjectStore()
      ->PostDbusCallWithObjectPathAndTwoStrings(
          asyncResp->strand_,
          absl::AnyInvocable<void(const boost::system::error_code&,
                                  const std::string&)>(
              [asyncResp{asyncResp}](const boost::system::error_code& ec,
                                     const std::string& responseString) {
                getSignedMeasurementsInvocationCallback(asyncResp, ec,
                                                        responseString);
              }),
          "xyz.openbmc_project.securityd.TpmAttestationService",
          "/xyz/openbmc_project/securityd/tpm_attestation_service",
          "xyz.openbmc_project.securityd.TpmAttestationService", "GetPcrQuote",
          sdbusplus::message::object_path(resolvedEntity.object),
          command.pcrSelectionBase64, command.nonceHex);
}

inline void getEkCertChainInvocationCallback(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const boost::system::error_code& ec, const std::string& responseString) {
  if (ec) {
    BMCWEB_LOG_ERROR << "RootOfTrust.Certificates failed: " << ec.message();
    redfish::messages::internalError(asyncResp->res);
    return;
  }

  asyncResp->res.jsonValue["@odata.type"] = "#Certificate.v1_0_0.Certificate";
  asyncResp->res.jsonValue["CertUsageTypes"] =
      nlohmann::json::array({"Device"});
  asyncResp->res.jsonValue["CertificateType"] = "DICE_FEK";
  asyncResp->res.jsonValue["CertString"] = responseString;
}

inline void invokeGetEkCertChainSecuritydCommand(
    const std::string& /*unused*/,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const ResolvedEntity& resolvedEntity) {
  managedStore::GetManagedObjectStore()->PostDbusCallWithObjectPath(
      asyncResp->strand_,
      absl::AnyInvocable<void(const boost::system::error_code&,
                              const std::string&)>(
          [asyncResp{asyncResp}](const boost::system::error_code& ec,
                                 const std::string& responseString) {
            getEkCertChainInvocationCallback(asyncResp, ec, responseString);
          }),
      "xyz.openbmc_project.securityd.TpmAttestationService",
      "/xyz/openbmc_project/securityd/tpm_attestation_service",
      "xyz.openbmc_project.securityd.TpmAttestationService", "GetEkCertChain",
      sdbusplus::message::object_path(resolvedEntity.object));
}

struct GenerateSignedCsrCommand {
  std::string certURI;
  std::string nonce;
  std::string pcrSelection;
  std::string csr;
};

inline void invokeGenerateSignedCSRSecuritydCommand(
    const GenerateSignedCsrCommand& command,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const ResolvedEntity& resolvedEntity) {
  (void)resolvedEntity;
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, certURI = command.certURI](
          const boost::system::error_code& ec, const std::string& csr_string,
          const std::string& certify_creation_attest,
          const std::string& fek_signature, const std::string& creation_data,
          const std::string& public_key, const std::string& csr_signature) {
        if (ec) {
          BMCWEB_LOG_ERROR << "RootOfTrust.Actions.GenerateSignedCSR failed: "
                           << ec.message();
          redfish::messages::internalError(asyncResp->res);
          return;
        }
        asyncResp->res.jsonValue["CSRString"] = csr_string;
        asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
            certURI;
        asyncResp->res.jsonValue["TpmEndorsement"]["CertifyCreationAttest"] =
            certify_creation_attest;
        asyncResp->res.jsonValue["TpmEndorsement"]["FekSignature"] =
            fek_signature;
        asyncResp->res.jsonValue["TpmEndorsement"]["CreationData"] =
            creation_data;
        asyncResp->res.jsonValue["TpmEndorsement"]["PublicKey"] = public_key;
        asyncResp->res.jsonValue["TpmEndorsement"]["CSRSignature"] =
            csr_signature;
      },
      "xyz.openbmc_project.securityd.TpmAttestationService",
      "/xyz/openbmc_project/securityd/tpm_attestation_service",
      "xyz.openbmc_project.securityd.TpmAttestationService", "SignCSR",
      command.nonce, command.pcrSelection, command.csr);
}

inline std::shared_ptr<milotic_tlbmc::CredentialManager>&
getCredentialManager() {
  static std::shared_ptr<milotic_tlbmc::CredentialManager> credentialManager;
  return credentialManager;
}

inline void setupCredentialManager(
    std::shared_ptr<milotic_tlbmc::CredentialManager> credentialManager) {
  getCredentialManager() = std::move(credentialManager);
}

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

  // This RPC is routed to securityd so only Hoth is supported.
  if (rotId != "Hoth" && rotId != "bmc_rot") {
    redfish::messages::actionParameterNotSupported(
        asyncResp->res, "GenerateSignedCSR", "RootOfTrust");
    return;
  }

  std::string city;
  std::string commonName;
  std::string country;
  std::string organization;
  std::string organizationalUnit;
  std::string state;
  std::optional<std::vector<std::string>> optAlternativeNames;
  nlohmann::json certificateCollection;
  std::string nonce;
  std::string pcrSelection;

  if (!redfish::json_util::readJsonAction(
          request, asyncResp->res, "AlternativeNames", optAlternativeNames,
          "CertificateCollection", certificateCollection, "City", city,
          "CommonName", commonName, "Country", country, "Nonce", nonce,
          "Organization", organization, "OrganizationalUnit",
          organizationalUnit, "PCRSelection", pcrSelection, "State", state)) {
    return;
  }

  std::string certURI;
  if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
                                    "@odata.id", certURI)) {
    return;
  }

  if (certURI != "/redfish/v1/Managers/bmc/Certificates" &&
      certURI !=
          "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates") {
    redfish::messages::actionParameterNotSupported(
        asyncResp->res, "CertificateCollection", "GenerateSignedCSR");
    return;
  }

  milotic_tlbmc::CredentialManager::CsrParams csrParams{
      .country = country,
      .state = state,
      .city = city,
      .organization = organization,
      .organizational_unit = organizationalUnit,
      .common_name = commonName,
      .alternative_names =
          optAlternativeNames.value_or(std::vector<std::string>()),
  };

  std::shared_ptr<milotic_tlbmc::CredentialManager> credentialManager =
      getCredentialManager();
  if (credentialManager == nullptr) {
    BMCWEB_LOG_ERROR << "CredentialManager is not initialized.";
    redfish::messages::internalError(asyncResp->res);
    return;
  }

  absl::StatusOr<std::string> csr = credentialManager->GenerateCsr(csrParams);
  if (!csr.ok()) {
    BMCWEB_LOG_ERROR << "Failed to generate CSR: " << csr.status();
    redfish::messages::internalError(asyncResp->res);
    return;
  }

  GenerateSignedCsrCommand command{
      .certURI = std::move(certURI),
      .nonce = std::move(nonce),
      .pcrSelection = std::move(pcrSelection),
      .csr = std::move(*csr),
  };

  resolveRoT(command, asyncResp, rotId,
             invokeGenerateSignedCSRSecuritydCommand);
}

#ifdef BMCWEB_ENABLE_ALLOW_ARBITRARY_COMMAND_TO_ROT
inline void handleRoTSendCommandPost(
    App& app, const crow::Request& request,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& rotId) {
  if (!redfish::setUpRedfishRoute(app, request, asyncResp)) {
    return;
  }
  std::string command;
  if (!redfish::json_util::readJsonAction(request, asyncResp->res, "Command",
                                          command)) {
    BMCWEB_LOG_DEBUG << "Missing property Command.";
    redfish::messages::actionParameterMissing(asyncResp->res, "SendCommand",
                                              "Command");
    return;
  }

  resolveRoT(command, asyncResp, rotId, invokeRoTCommand);
}
#endif

inline std::optional<std::string> processAndHashNonce(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    std::string_view hexNonce) {
  std::vector<uint8_t> decodedNonce = hexStringToBytes(std::string(hexNonce));
  if (decodedNonce.empty() && !hexNonce.empty()) {
    BMCWEB_LOG_DEBUG << "Failed to hex decode provided Nonce.";
    redfish::messages::actionParameterValueFormatError(
        asyncResp->res, hexNonce, "TPMGetSignedMeasurements",
        "Failed to hex decode provided Nonce.");
    return std::nullopt;
  }

  struct UserData {
    uint8_t magic[4] = {0x54, 0x50, 0x4D, 0x32};
    uint8_t version[2] = {0x00, 0x00};
    uint8_t reserved[2] = {0x00, 0x00};
    uint8_t caller_nonce[32] = {};
  } __attribute__((packed));

  UserData userData = {};
  if (decodedNonce.size() > sizeof(userData.caller_nonce)) {
    BMCWEB_LOG_DEBUG << "Caller nonce is longer than expected.";
    redfish::messages::actionParameterValueError(
        asyncResp->res, "TPMGetSignedMeasurements",
        "Caller nonce is longer than expected.");
    return std::nullopt;
  }
  std::memcpy(userData.caller_nonce, decodedNonce.data(), decodedNonce.size());

  EVP_MD_CTX* context = EVP_MD_CTX_new();
  if (context == nullptr) {
    BMCWEB_LOG_DEBUG << "Failed to create EVP_MD_CTX.";
    redfish::messages::internalError(asyncResp->res);
    return std::nullopt;
  }

  unsigned char hashResult[EVP_MAX_MD_SIZE];
  unsigned int lengthOfHash = 0;
  if (EVP_DigestInit_ex(context, EVP_sha256(), nullptr) != 1 ||
      EVP_DigestUpdate(context, &userData, sizeof(userData)) != 1 ||
      EVP_DigestFinal_ex(context, hashResult, &lengthOfHash) != 1) {
    EVP_MD_CTX_free(context);
    BMCWEB_LOG_DEBUG << "Failed to hash PCR quote nonce.";
    redfish::messages::internalError(asyncResp->res);
    return std::nullopt;
  }
  EVP_MD_CTX_free(context);

  std::vector<uint8_t> hashBytes(hashResult, hashResult + lengthOfHash);
  return bytesToHexString(hashBytes);
}

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

  std::optional<std::string> nonce;
  std::optional<std::string> pcrSelection;
  if (!redfish::json_util::readJsonAction(request, asyncResp->res, "Nonce",
                                          nonce, "PCRSelection",
                                          pcrSelection)) {
    BMCWEB_LOG_DEBUG << "Failed to parse json action.";
    return;
  }

  if (!nonce) {
    BMCWEB_LOG_DEBUG << "Missing property Nonce.";
    redfish::messages::actionParameterMissing(
        asyncResp->res, "TPMGetSignedMeasurements", "Nonce");
    return;
  }
  if (!pcrSelection) {
    BMCWEB_LOG_DEBUG << "Missing property PCRSelection.";
    redfish::messages::actionParameterMissing(
        asyncResp->res, "TPMGetSignedMeasurements", "PCRSelection");
    return;
  }
  std::optional<std::string> processedNonce =
      processAndHashNonce(asyncResp, *nonce);
  if (!processedNonce) {
    BMCWEB_LOG_DEBUG << "Failed to decode or hash the client nonce.";
    return;
  }

  PcrQuoteParams quoteParams;
  quoteParams.nonceHex = std::move(*processedNonce);
  quoteParams.pcrSelectionBase64 = *pcrSelection;

  resolveRoT(quoteParams, asyncResp, rotId, invokePcrQuoteSecuritydCommand);
}

inline void handleRootOfTrustCertificatesGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& rotId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
      "google", "v1", "RootOfTrustCollection", rotId, "Certificates");
  asyncResp->res.jsonValue["Id"] = "Certificates";
  asyncResp->res.jsonValue["Name"] = "Root Of Trust Certificates";

  std::string emptyCommand;
  resolveRoT(emptyCommand, asyncResp, rotId,
             invokeGetEkCertChainSecuritydCommand);
}

inline void requestRoutes(App& app) {
  BMCWEB_ROUTE(app, "/google/v1/")
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleGoogleV1Get, std::ref(app)));

  BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/")
      .privileges({{"ConfigureManager"}})
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleRootOfTrustCollectionGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/<str>/")
      .privileges({{"ConfigureManager"}})
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleRootOfTrustGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/google/v1/RootOfTrustCollection/<str>/Certificates/")
      .privileges({{"ConfigureManager"}})
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleRootOfTrustCertificatesGet, std::ref(app)));

#ifdef BMCWEB_ENABLE_ALLOW_ARBITRARY_COMMAND_TO_ROT
  BMCWEB_ROUTE(app,
               "/google/v1/RootOfTrustCollection/<str>/Actions/"
               "RootOfTrust.SendCommand/")
      .privileges({{"ConfigureManager"}})
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleRoTSendCommandPost, std::ref(app)));
#endif

  BMCWEB_ROUTE(app,
               "/google/v1/RootOfTrustCollection/<str>/Actions/"
               "RootOfTrust.GenerateSignedCSR/")
      .privileges({{"ConfigureManager"}})
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleGenerateSignedCSRPost, std::ref(app)));

  BMCWEB_ROUTE(app,
               "/google/v1/RootOfTrustCollection/<str>/Actions/"
               "RootOfTrust.TPMGetSignedMeasurements/")
      .privileges({{"ConfigureManager"}})
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleGetSignedMeasurementsPost, std::ref(app)));
}
}  // namespace google_api
}  // namespace crow

#endif  // THIRD_PARTY_GBMCWEB_INCLUDE_GOOGLE_GOOGLE_SERVICE_ROOT_H_
