#pragma once

#include "app.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/chassis_utils.hpp"
#include "utils/json_utils.hpp"
#include "utils/location_utils.hpp"

#include <boost/system/error_code.hpp>
#include <boost/url/format.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/message/types.hpp>

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

#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
