#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_CHASSIS_UTILS_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_CHASSIS_UTILS_H_

#include <array>
#include <string_view>
#include <utility>
#include <memory>
#include <string>
#include <optional>
#include <vector>
#include <algorithm>

#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "logging.hpp"
#include "error_messages.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/message/native_types.hpp"

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

namespace redfish {

namespace chassis_utils {

constexpr std::array<std::string_view, 2> chassisInterfaces = {
    "xyz.openbmc_project.Inventory.Item.Board",
    "xyz.openbmc_project.Inventory.Item.Chassis"};

/**
 * @brief Retrieves valid chassis path
 * @param asyncResp   Pointer to object holding response data
 * @param callback  Callback for next step to get valid chassis path
 */
template <typename Callback>
void getValidChassisPath(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::string& chassisId, Callback&& callback) {
  BMCWEB_LOG_DEBUG << "checkChassisId enter";

  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  // Get the Chassis Collection
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      "/xyz/openbmc_project/inventory", 0, chassisInterfaces, requestContext,
      [callback{std::forward<Callback>(callback)}, asyncResp, chassisId](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreePathsResponse&
              chassisPaths) mutable {
        BMCWEB_LOG_DEBUG << "getValidChassisPath respHandler enter";
        if (ec) {
          BMCWEB_LOG_ERROR << "getValidChassisPath respHandler DBUS error: "
                           << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        std::optional<std::string> chassisPath;
        for (const std::string& chassis : chassisPaths) {
          sdbusplus::message::object_path path(chassis);
          std::string chassisName = path.filename();
          if (chassisName.empty()) {
            BMCWEB_LOG_ERROR << "Failed to find '/' in " << chassis;
            continue;
          }
          if (chassisName == chassisId) {
            chassisPath = chassis;
            break;
          }
        }
        callback(chassisPath);
      });
  BMCWEB_LOG_DEBUG << "checkChassisId exit";
}

/**
 * @brief Get subtree for associated endpoint with chassis interfaces.
 * @param asyncResp         Pointer to object holding response data
 * @param associationPath   Path used to associate with chassis endpoints
 * @param callback          Callback to process subtree response
 */
template <typename Callback>
inline void getAssociatedChassisSubtree(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& associationPath, Callback&& callback) {
  sdbusplus::message::object_path association(associationPath);
  sdbusplus::message::object_path root("/xyz/openbmc_project/inventory");
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getAssociatedSubTree(
      association, root, 0, chassisInterfaces, requestContext,
      [asyncResp, associationPath, callback{std::forward<Callback>(callback)}](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec) {
          BMCWEB_LOG_ERROR << "Failed to get chassis associations for "
                           << associationPath << " ec: " << ec.message();
          messages::internalError(asyncResp->res);
          return;
        }
        callback(asyncResp, subtree);
      });
}

/**
 * @brief Recursively get upstream Chassis object path to find root chassis.
 *
 * @param[in,out]   visitedPaths   Set of chassis object paths queried.
 * @param[in,out]   asyncResp      Pointer to object holding response data
 * @param[in]       subtreePaths   Subtree associated with chassis endpoint
 * @param           callback       Callback to invoke with root chassis object
 * path.
 */
template <typename Callback>
inline void getRootChassisPath(
    std::vector<std::string> visitedPaths,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths,
    Callback&& callback) {
  // Base case as we recurse to get upstream chassis association.
  if (subtreePaths.empty()) {
    const std::string& rootChassisPath = visitedPaths.back();
    BMCWEB_LOG_DEBUG << "Root chassis path found " << rootChassisPath;
    callback(rootChassisPath);
    return;
  }

  if (subtreePaths.size() > 1) {
    BMCWEB_LOG_ERROR << "Found multiple upstream chassis.";
    messages::internalError(asyncResp->res);
    return;
  }

  // Upstream chassis.
  const std::string& chassisPath = subtreePaths[0];
  if (find(visitedPaths.begin(), visitedPaths.end(), chassisPath) !=
      visitedPaths.end()) {
    BMCWEB_LOG_ERROR << "Loop detected in upstream chassis associations.";
    messages::internalError(asyncResp->res);
    return;
  }

  visitedPaths.push_back(chassisPath);

  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  sdbusplus::message::object_path association(chassisPath + "/contained_by");
  sdbusplus::message::object_path root("/xyz/openbmc_project/inventory");
  managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
      association, root, 0, chassisInterfaces, requestContext,
      [requestContext, visitedPaths, asyncResp, association,
       callback{std::forward<Callback>(callback)}](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "Can't get chassis associations for "
                           << association.str << " ec: " << ec.message();
          messages::internalError(asyncResp->res);
          return;
        }

        getRootChassisPath(visitedPaths, asyncResp, subtreePaths, callback);
      });
}

}  // namespace chassis_utils
}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_INCLUDE_UTILS_CHASSIS_UTILS_H_
