#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_FAN_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_FAN_H_

#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <string_view>

#include "boost/system/error_code.hpp"  // NOLINT
#include "boost/url/format.hpp"  // NOLINT
#include "app.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "chassis_utils.hpp"
#include "json_utils.hpp"
#include "location_utils.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/asio/property.hpp"
#include "sdbusplus/message/types.hpp"

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

namespace redfish {

constexpr std::array<std::string_view, 1> fanInterfaces = {
    "xyz.openbmc_project.Configuration.Fan"};
constexpr std::array<std::string_view, 1> sensorInterfaces = {
    "xyz.openbmc_project.Sensor.Value"};

inline void updateFanList(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId,
    const dbus::utility::MapperGetSubTreePathsResponse& fanPaths) {
  nlohmann::json& fanList = asyncResp->res.jsonValue["Members"];
  for (const std::string& fanPath : fanPaths) {
    if (fanPath.empty()) {
      BMCWEB_LOG_DEBUG << "Error getting D-Bus object!";
      messages::internalError(asyncResp->res);
      return;
    }

    std::string fanName = sdbusplus::message::object_path(fanPath).filename();

    std::string chassisName;

    // 5 below comes from
    // /xyz/openbmc_project/inventory/system/chassis/chassisName/fanName
    //   0      1             2         3         4         5      6
    if (!dbus::utility::getNthStringFromPath(fanPath, 5, chassisName) ||
        fanName.empty()) {
      BMCWEB_LOG_ERROR << "Got invalid path " << fanPath;
      messages::invalidObject(
          asyncResp->res,
          crow::utility::urlFromPieces("xyz", "openbmc_project", "inventory",
                                       "system", fanPath));
      continue;
    }

    if (chassisName != chassisId) {
      BMCWEB_LOG_ERROR << "The fan obtained at this time "
                          "does not belong to this chassis ";
      continue;
    }

    nlohmann::json item = nlohmann::json::object();
    item["@odata.id"] = boost::urls::format(
        "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans/{}", chassisId, fanName);

    fanList.emplace_back(std::move(item));
  }
  asyncResp->res.jsonValue["Members@odata.count"] = fanList.size();
}

inline void getFanPaths(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::optional<std::string>& validChassisPath,
    const std::function<void(const dbus::utility::MapperGetSubTreePathsResponse&
                                 fanPaths)>& callback) {
  sdbusplus::message::object_path endpointPath{*validChassisPath};
  endpointPath /= "cooled_by";

  // TODO(tomtung): enable this after setting up associations.
  //  dbus::utility::getAssociatedSubTreePaths(
  //    endpointPath,
  //    sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
  //    fanInterfaces,
  //    [asyncResp, callback](
  //        const boost::system::error_code& ec,
  //        const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths)
  //        {
  //    if (ec)
  //    {
  //        if (ec.value() != EBADR)
  //        {
  //            BMCWEB_LOG_ERROR
  //                << "DBUS response error for getAssociatedSubTreePaths "
  //                << ec.value();
  //            messages::internalError(asyncResp->res);
  //        }
  //        return;
  //    }
  //    callback(subtreePaths);
  //    });

  managedStore::ManagedObjectStoreContext context(asyncResp);
  dbus_utils::getSubTreePaths(
      "/xyz/openbmc_project/inventory", 0, fanInterfaces, context,
      [asyncResp, callback](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "DBUS response error";
          messages::internalError(asyncResp->res);
          return;
        }
        callback(subtreePaths);
      });
}

inline void doFanCollection(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId,
    const std::optional<std::string>& validChassisPath) {
  if (!validChassisPath) {
    BMCWEB_LOG_ERROR << "Not a valid chassis ID" << chassisId;
    messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
    return;
  }

  BMCWEB_LOG_DEBUG << "Get fan list associated to chassis = " << chassisId;
  asyncResp->res.addHeader(boost::beast::http::field::link,
                           "</redfish/v1/JsonSchemas/FanCollection/"
                           "FanCollection.json>; rel=describedby");
  asyncResp->res.jsonValue["@odata.type"] = "#FanCollection.FanCollection";
  asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
      "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans", chassisId);
  asyncResp->res.jsonValue["Name"] = "Fan Collection";
  asyncResp->res.jsonValue["Description"] =
      "The collection of Fan resource instances " + chassisId;
  asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
  asyncResp->res.jsonValue["Members@odata.count"] = 0;

  getFanPaths(asyncResp, validChassisPath,
              std::bind_front(updateFanList, asyncResp, chassisId));
}

inline void getFanSensorValue(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& sensorName,
    const std::string& sensorType) {
  constexpr std::array<std::string_view, 4> supportedSensorTypes = {
      "fan_tach", "fan_pwm", "secondary_fan_tach", "secondary_fan_pwm"};
  if (std::find(supportedSensorTypes.begin(), supportedSensorTypes.end(),
                sensorType) == supportedSensorTypes.end()) {
    BMCWEB_LOG_DEBUG << "Unsupported sensor type";
    messages::internalError(asyncResp->res);
    return;
  }
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  auto getFanSensorsHandler =
      [asyncResp, chassisId, sensorName, sensorType, requestContext](
          const boost::system::error_code ec,
          const std::vector<std::pair<
              std::string,
              std::vector<std::pair<std::string, std::vector<std::string>>>>>&
              sensorsubtree) {
        if (ec) {
          BMCWEB_LOG_DEBUG << "D-Bus response error on GetSubTree " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        for (const auto& [objectPath, serviceNames] : sensorsubtree) {
          if (serviceNames.size() > 1) {
            BMCWEB_LOG_DEBUG << "Skipping over ambiguous sensor served by "
                                "multiple services: "
                             << objectPath;
            continue;
          }
          if (objectPath.empty() || serviceNames.size() != 1) {
            BMCWEB_LOG_DEBUG << "Error getting Fan D-Bus object!";
            messages::internalError(asyncResp->res);
            return;
          }
          sdbusplus::message::object_path path(objectPath);
          const std::string& leaf = path.filename();
          if (leaf.empty()) {
            continue;
          }
          if (leaf != sensorName) {
            continue;
          }

          // There is no reason to populate PartLocationContext only for
          // fan_pwm but it happens so that both fan_pwm and fan_tach
          // sensors are associated with the same chassis through entity
          // manager config today so we arbitraty picked fan_pwm to find
          // the associated chassis.
          if (sensorType == "fan_pwm") {
            // Get PartLocationContext
            location_util::getPartLocationContext(
                asyncResp, "/Location"_json_pointer, path.str + "/chassis");
          }

          const std::string& connectionName = serviceNames[0].first;
          const std::string& tempPath = objectPath;
          auto getAssociationHandler =
              [asyncResp, tempPath, connectionName, chassisId, sensorName,
               sensorType,
               requestContext](const boost::system::error_code ec2,
                               const std::vector<std::string>& resp) {
                BMCWEB_LOG_DEBUG << "Getting chassis association for sensor "
                                 << sensorName;
                if (ec2) {
                  BMCWEB_LOG_DEBUG
                      << "Error getting chassis association for the sensor!";
                  messages::internalError(asyncResp->res);
                  return;
                }
                if (resp.size() != 1) {
                  BMCWEB_LOG_DEBUG
                      << "The number of associated chassis should be 1";
                  messages::internalError(asyncResp->res);
                  return;
                }
                sdbusplus::message::object_path path2(resp[0]);
                std::string leaf2 = path2.filename();
                if (leaf2 != chassisId) {
                  BMCWEB_LOG_DEBUG
                      << "The sensor doesn't belong to the chassis "
                      << chassisId;
                  messages::internalError(asyncResp->res);
                  return;
                }
                auto getFanPropertyHandler =
                    [asyncResp, chassisId, sensorName, sensorType](
                        const boost::system::error_code ec3,
                        const double& resp2) {
                      if (ec3) {
                        BMCWEB_LOG_DEBUG
                            << "Error getting sensor value for sensor:"
                            << sensorName;
                        messages::internalError(asyncResp->res);
                        return;
                      }
                      if (sensorType == "fan_pwm" ||
                          sensorType == "secondary_fan_pwm") {
                        const std::string jsonKey =
                            (sensorType == "fan_pwm") ? "SpeedPercent"
                                                      : "SecondarySpeedPercent";
                        asyncResp->res.jsonValue[jsonKey]["DataSourceUri"] =
                            std::string("/redfish/v1/Chassis/")
                                .append(chassisId)
                                .append("/Sensors/")
                                .append("fanpwm_" + sensorName)
                                .append("/");
                        asyncResp->res.jsonValue[jsonKey]["Reading"] = resp2;
                      } else if (sensorType == "fan_tach") {
                        asyncResp->res.jsonValue["SpeedPercent"]["SpeedRPM"] =
                            resp2;
                      } else if (sensorType == "secondary_fan_tach") {
                        asyncResp->res
                            .jsonValue["SecondarySpeedPercent"]["SpeedRPM"] =
                            resp2;
                      }
                    };
                dbus_utils::getProperty<double>(
                    connectionName, tempPath,
                    "xyz.openbmc_project.Sensor.Value", "Value", requestContext,
                    getFanPropertyHandler);
              };
          dbus_utils::getProperty<std::vector<std::string>>(
              "xyz.openbmc_project.ObjectMapper", tempPath + "/chassis",
              "xyz.openbmc_project.Association", "endpoints", requestContext,
              getAssociationHandler);
        }
      };
  managedStore::GetManagedObjectStore()->getSubTree(
      "/xyz/openbmc_project/sensors", 0, sensorInterfaces, requestContext,
      getFanSensorsHandler);
}

inline void fillFanProperties(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const boost::system::error_code ec,
    const dbus::utility::DBusPropertiesMap& properties,
    const std::string& chassisId) {
  if (ec) {
    BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
    messages::internalError(asyncResp->res);
    return;
  }
  for (const auto& [propKey, propVariant] : properties) {
    if (propKey == "HotPluggable") {
      const bool* hotPluggable = std::get_if<bool>(&propVariant);
      if (hotPluggable == nullptr) {
        messages::internalError(asyncResp->res);
        return;
      }
      asyncResp->res.jsonValue["HotPluggable"] = *hotPluggable;
    } else if (propKey == "LocationType") {
      const std::string* locationType = std::get_if<std::string>(&propVariant);
      if (locationType == nullptr) {
        messages::internalError(asyncResp->res);
        return;
      }
      asyncResp->res.jsonValue["Location"]["PartLocation"]["LocationType"] =
          *locationType;
    } else if (propKey == "ServiceLabel") {
      const std::string* serviceLabel = std::get_if<std::string>(&propVariant);
      if (serviceLabel == nullptr) {
        messages::internalError(asyncResp->res);
        return;
      }
      asyncResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
          *serviceLabel;
    } else if (propKey == "TachSensor") {
      const std::string* tachSensor = std::get_if<std::string>(&propVariant);
      if (tachSensor == nullptr) {
        messages::internalError(asyncResp->res);
        return;
      }
      getFanSensorValue(asyncResp, chassisId, *tachSensor, "fan_tach");
    } else if (propKey == "PWMSensor") {
      const std::string* pwmSensor = std::get_if<std::string>(&propVariant);
      if (pwmSensor == nullptr) {
        messages::internalError(asyncResp->res);
        return;
      }
      getFanSensorValue(asyncResp, chassisId, *pwmSensor, "fan_pwm");
    } else if (propKey == "SecondaryTachSensor") {
      const std::string* tachSensor = std::get_if<std::string>(&propVariant);
      if (tachSensor == nullptr) {
        messages::internalError(asyncResp->res);
        return;
      }
      getFanSensorValue(asyncResp, chassisId, *tachSensor,
                        "secondary_fan_tach");
    } else if (propKey == "SecondaryPWMSensor") {
      const std::string* pwmSensor = std::get_if<std::string>(&propVariant);
      if (pwmSensor == nullptr) {
        messages::internalError(asyncResp->res);
        return;
      }
      getFanSensorValue(asyncResp, chassisId, *pwmSensor, "secondary_fan_pwm");
    }
  }
}

inline void addFanProperties(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& fanObjectPath, const std::string& service,
    const std::string& chassisId) {
  BMCWEB_LOG_DEBUG << "Get Properties for Fan " << fanObjectPath;
  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      service, fanObjectPath, "xyz.openbmc_project.Configuration.Fan", context,
      [asyncResp, chassisId](
          const boost::system::error_code ec,
          const dbus::utility::DBusPropertiesMap& properties) {
        fillFanProperties(asyncResp, ec, properties, chassisId);
      });
}

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

  redfish::chassis_utils::getValidChassisPath(
      asyncResp, chassisId,
      [asyncResp,
       chassisId](const std::optional<std::string>& validChassisPath) {
        if (!validChassisPath) {
          messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
          return;
        }
        asyncResp->res.addHeader(boost::beast::http::field::link,
                                 "</redfish/v1/JsonSchemas/FanCollection/"
                                 "FanCollection.json>; rel=describedby");
      });
}

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

  redfish::chassis_utils::getValidChassisPath(
      asyncResp, chassisId,
      std::bind_front(doFanCollection, asyncResp, chassisId));
}

inline void requestRoutesFanCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/")
      .privileges(redfish::privileges::headFanCollection)
      .methods(boost::beast::http::verb::head)(
          std::bind_front(handleFanCollectionHead, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/")
      .privileges(redfish::privileges::getFanCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleFanCollectionGet, std::ref(app)));
}

inline bool checkChassisId(const std::string& fanPath,
                           const std::string& chassisId) {
  return fanPath.find("/" + chassisId + "/") != std::string::npos;
}

inline bool checkFanId(const std::string& fanPath, const std::string& fanId) {
  std::string fanName = sdbusplus::message::object_path(fanPath).filename();

  return !(fanName.empty() || fanName != fanId);
}

static inline void handleFanPath(
    const std::string& chassisId, const std::string& fanId,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const dbus::utility::MapperGetSubTreePathsResponse& fanPaths,
    const std::function<void(const std::string& fanPath,
                             const std::string& service)>& callback) {
  for (const auto& fanPath : fanPaths) {
    if (!checkChassisId(fanPath, chassisId) || !checkFanId(fanPath, fanId)) {
      continue;
    }

    managedStore::ManagedObjectStoreContext context(asyncResp);
    dbus_utils::getDbusObject(
        fanPath, fanInterfaces, context,
        [fanPath, asyncResp, callback](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetObject& object) {
          if (ec || object.empty()) {
            BMCWEB_LOG_ERROR << "DBUS response error on getDbusObject "
                             << ec.value();
            messages::internalError(asyncResp->res);
            return;
          }
          callback(fanPath, object.begin()->first);
        });

    return;
  }
  BMCWEB_LOG_WARNING << "Fan not found " << fanId;
  messages::resourceNotFound(asyncResp->res, "Fan", fanId);
}

inline void getValidFanPath(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& validChassisPath, const std::string& chassisId,
    const std::string& fanId,
    const std::function<void(const std::string& fanPath,
                             const std::string& service)>& callback) {
  getFanPaths(
      asyncResp, validChassisPath,
      [chassisId, fanId, asyncResp,
       callback](const dbus::utility::MapperGetSubTreePathsResponse& fanPaths) {
        handleFanPath(chassisId, fanId, asyncResp, fanPaths, callback);
      });
}

inline void addFanCommonProperties(crow::Response& resp,
                                   const std::string& chassisId,
                                   const std::string& fanId) {
  resp.addHeader(boost::beast::http::field::link,
                 "</redfish/v1/JsonSchemas/Fan/Fan.json>; rel=describedby");
  resp.jsonValue["@odata.type"] = "#Fan.v1_3_0.Fan";
  resp.jsonValue["Name"] = fanId;
  resp.jsonValue["Id"] = fanId;
  resp.jsonValue["@odata.id"] = boost::urls::format(
      "/redfish/v1/Chassis/{}/ThermalSubsystem/Fans/{}", chassisId, fanId);
  resp.jsonValue["Status"]["State"] = "Enabled";
  resp.jsonValue["Status"]["Health"] = "OK";
}

inline void getFanHealth(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::string& fanPath,
                         const std::string& service) {
  managedStore::ManagedObjectStoreContext context(asyncResp);
  dbus_utils::getProperty<bool>(
      service, fanPath, "xyz.openbmc_project.State.Decorator.OperationalStatus",
      "Functional", context,
      [asyncResp](const boost::system::error_code& ec, const bool value) {
        if (ec) {
          if (ec.value() != EBADR) {
            BMCWEB_LOG_ERROR << "DBUS response error for Health " << ec.value();
            messages::internalError(asyncResp->res);
          }
          return;
        }

        if (!value) {
          asyncResp->res.jsonValue["Status"]["Health"] = "Critical";
        }
      });
}

inline void getFanState(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& fanPath,
                        const std::string& service) {
  managedStore::ManagedObjectStoreContext context(asyncResp);
  dbus_utils::getProperty<bool>(
      service, fanPath, "xyz.openbmc_project.Inventory.Item", "Present",
      context,
      [asyncResp](const boost::system::error_code& ec, const bool value) {
        if (ec) {
          if (ec.value() != EBADR) {
            BMCWEB_LOG_ERROR << "DBUS response error for State " << ec.value();
            messages::internalError(asyncResp->res);
          }
          return;
        }

        if (!value) {
          asyncResp->res.jsonValue["Status"]["State"] = "Absent";
        }
      });
}

inline void getFanAsset(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& fanPath,
                        const std::string& service) {
  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      service, fanPath, "xyz.openbmc_project.Inventory.Decorator.Asset",
      context,
      [fanPath, asyncResp{asyncResp}](
          const boost::system::error_code& ec,
          const dbus::utility::DBusPropertiesMap& assetList) {
        if (ec) {
          if (ec.value() != EBADR) {
            BMCWEB_LOG_ERROR << "DBUS response error for Properties"
                             << ec.value();
            messages::internalError(asyncResp->res);
          }
          return;
        }
        const std::string* manufacturer = nullptr;
        const std::string* model = nullptr;
        const std::string* partNumber = nullptr;
        const std::string* serialNumber = nullptr;
        const std::string* sparePartNumber = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), assetList, "Manufacturer",
            manufacturer, "Model", model, "PartNumber", partNumber,
            "SerialNumber", serialNumber, "SparePartNumber", sparePartNumber);
        if (!success) {
          messages::internalError(asyncResp->res);
          return;
        }
        if (manufacturer != nullptr) {
          asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
        }
        if (model != nullptr) {
          asyncResp->res.jsonValue["Model"] = *model;
        }
        if (partNumber != nullptr) {
          asyncResp->res.jsonValue["PartNumber"] = *partNumber;
        }
        if (serialNumber != nullptr) {
          asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
        }
        if (sparePartNumber != nullptr && !sparePartNumber->empty()) {
          asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
        }
      });
}

inline void getFanLocation(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                           const std::string& fanPath,
                           const std::string& service) {
  managedStore::ManagedObjectStoreContext context(aResp);
  dbus_utils::getProperty<std::string>(
      service, fanPath, "xyz.openbmc_project.Inventory.Decorator.LocationCode",
      "LocationCode", context,
      [aResp](const boost::system::error_code& ec,
              const std::string& property) {
        if (ec) {
          if (ec.value() != EBADR) {
            BMCWEB_LOG_ERROR << "DBUS response error for Location"
                             << ec.value();
            messages::internalError(aResp->res);
          }
          return;
        }
        aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
            property;
      });
}

inline void afterGetValidFanPath(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& fanId,
    const std::string& fanPath, const std::string& service) {
  addFanCommonProperties(asyncResp->res, chassisId, fanId);
  getFanState(asyncResp, fanPath, service);
  getFanHealth(asyncResp, fanPath, service);
  getFanAsset(asyncResp, fanPath, service);
  getFanLocation(asyncResp, fanPath, service);
  addFanProperties(asyncResp, fanPath, service, chassisId);
}

inline void doFanGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                     const std::string& chassisId, const std::string& fanId,
                     const std::optional<std::string>& validChassisPath) {
  if (!validChassisPath) {
    BMCWEB_LOG_ERROR << "Not a valid chassis ID" << chassisId;
    messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
    return;
  }

  getValidFanPath(
      asyncResp, *validChassisPath, chassisId, fanId,
      std::bind_front(afterGetValidFanPath, asyncResp, chassisId, fanId));
}

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

  redfish::chassis_utils::getValidChassisPath(
      asyncResp, chassisId,
      [asyncResp, chassisId,
       fanId](const std::optional<std::string>& validChassisPath) {
        if (!validChassisPath) {
          messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
          return;
        }
        getValidFanPath(
            asyncResp, *validChassisPath, chassisId, fanId,
            [asyncResp](const std::string&, const std::string&) {
              asyncResp->res.addHeader(
                  boost::beast::http::field::link,
                  "</redfish/v1/JsonSchemas/Fan/Fan.json>; rel=describedby");
            });
      });
}

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

  redfish::chassis_utils::getValidChassisPath(
      asyncResp, chassisId,
      std::bind_front(doFanGet, asyncResp, chassisId, fanId));
}

inline void requestRoutesFan(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/<str>/")
      .privileges(redfish::privileges::headFan)
      .methods(boost::beast::http::verb::head)(
          std::bind_front(handleFanHead, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/ThermalSubsystem/Fans/<str>/")
      .privileges(redfish::privileges::getFan)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleFanGet, std::ref(app)));
}

}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_FAN_H_
