#pragma once

#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "managed_store.hpp"
#include "utility.hpp"

#include <array>
#include <string_view>
#include <unordered_map>

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

namespace redfish
{

namespace fan_utils
{

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

inline void fillFanProperties(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& objectPath,
    const dbus::utility::DBusPropertiesMap& properties,
    const std::shared_ptr<std::unordered_map<std::string, std::string>>&
        fanSensorToInventoryPath)
{
    for (const auto& [propKey, propVariant] : properties)
    {
        if (propKey == "TachSensor")
        {
            const std::string* tachSensor =
                std::get_if<std::string>(&propVariant);
            if (tachSensor == nullptr)
            {
                messages::internalError(asyncResp->res);
                return;
            }
            (*fanSensorToInventoryPath)[*tachSensor] = objectPath;
        }
        else if (propKey == "PWMSensor")
        {
            const std::string* pwmSensor =
                std::get_if<std::string>(&propVariant);
            if (pwmSensor == nullptr)
            {
                messages::internalError(asyncResp->res);
                return;
            }
            (*fanSensorToInventoryPath)[*pwmSensor] = objectPath;
        }
    }
}

template <typename Callback>
inline void getFanInventory(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::shared_ptr<std::unordered_map<std::string, std::string>>&
        fanSensorToInventoryPath,
    Callback callback)
{
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, fanInterfaces, requestContext,
        [asyncResp, fanSensorToInventoryPath, requestContext,
         callback{callback}](
            const boost::system::error_code ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error";
            messages::internalError(asyncResp->res);
            return;
        }

        if (subtree.empty())
        {
            callback();
            return;
        }

        auto fanConfigurationsQueried = std::make_shared<int>(subtree.size());
        for (const auto& [objectPath, serviceMap] : subtree)
        {
            for (const auto& [service, interfaces] : serviceMap)
            {
                for (const auto& interface : interfaces)
                {
                    if (interface != fanInterfaces[0])
                    {
                        continue;
                    }
                    managedStore::GetManagedObjectStore()->getAllProperties(
                        service, objectPath, interface, requestContext,
                        [asyncResp, fanSensorToInventoryPath, objectPath,
                         callback, fanConfigurationsQueried](
                            const boost::system::error_code& ec,
                            const dbus::utility::DBusPropertiesMap&
                                properties) {
                        if (ec)
                        {
                            BMCWEB_LOG_DEBUG << "DBUS response error " << ec;
                            messages::internalError(asyncResp->res);
                            return;
                        }

                        fillFanProperties(asyncResp, objectPath, properties,
                                          fanSensorToInventoryPath);

                        if (*fanConfigurationsQueried <= 0)
                        {
                            BMCWEB_LOG_ERROR << "Unaccounted fan configuration";
                            messages::internalError(asyncResp->res);
                            return;
                        }

                        if (*fanConfigurationsQueried == 1)
                        {
                            callback();
                        }
                        --(*fanConfigurationsQueried);
                    });
                }
            }
        }
    });
}

inline void AddThermalSubsystemLink(
    const sdbusplus::message::object_path& fanInventoryPath,
    nlohmann::json& sensorJson)
{
    nlohmann::json::object_t obj;
    obj["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", fanInventoryPath.parent_path().filename(),
        "ThermalSubsystem", "Fans", fanInventoryPath.filename());
    sensorJson["RelatedItem"] = nlohmann::json::array_t{std::move(obj)};
}

inline void AddRelatedItemForFanSensor(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& sensorName)
{
    auto fanSensorToInventoryPath =
        std::make_shared<std::unordered_map<std::string, std::string>>();
    getFanInventory(asyncResp, fanSensorToInventoryPath,
                    [asyncResp, sensorName, fanSensorToInventoryPath]() {
        auto findFanObjectPath = fanSensorToInventoryPath->find(sensorName);
        if (findFanObjectPath != fanSensorToInventoryPath->end())
        {
            sdbusplus::message::object_path fanInventoryPath(
                findFanObjectPath->second);
            AddThermalSubsystemLink(fanInventoryPath, asyncResp->res.jsonValue);
        }
    });
}

} // namespace fan_utils
} // namespace redfish
