#pragma once

#include "bmcweb_config.h"

#include "dbus_utility.hpp"
#include "managed_store_types.hpp"
#include "query.hpp"
#include "utils/dbus_utils.hpp"

#include <app.hpp>
#include <async_resp.hpp>
#include <dbus_utility.hpp>
#include <error_messages.hpp>
#include <nlohmann/json.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/message/native_types.hpp>
#include <utils/collection.hpp>
#include <utils/json_utils.hpp>
#include <utils/storage_utils.hpp>

#include <functional>
#include <vector>

#include "managed_store.hpp"

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

namespace crow
{
namespace google_api
{

using NVMeControllerHandlerCb = std::function<void(
    const boost::system::error_code ec, const std::string& storagePath,
    const std::vector<std::string>& controllerList)>;

using boost::asio::posix::stream_descriptor;

static std::shared_ptr<boost::asio::io_context> fdIOContext; // NOLINT

static void
    fetchFile(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
              const std::shared_ptr<stream_descriptor>& fileConn,
              const std::shared_ptr<std::array<char, 1024>>& readBuffer =
                  std::make_shared<std::array<char, 1024>>(),
              const std::shared_ptr<std::string>& output =
                  std::make_shared<std::string>())
{
    if (!fileConn)
    {
        BMCWEB_LOG_ERROR << "Fetch File Context is not setup properly";
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    fileConn->async_read_some(boost::asio::buffer(*readBuffer),
                              [asyncResp, fileConn, readBuffer,
                               output](const boost::system::error_code& ec,
                                       const std::size_t& bytesTransferred) {
        if (ec == boost::asio::error::eof)
        {
            asyncResp->res.stringResponse->clear();
            asyncResp->res.addHeader(boost::beast::http::field::content_type,
                                     "application/octet-stream");
            asyncResp->res.body() = std::move(*output);
            fileConn->close();
            return;
        }
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Failed to async_read_some" << ec.message();
            redfish::messages::internalError(asyncResp->res);
            return;
        }
        *output += std::string(readBuffer->begin(),
                               readBuffer->begin() + bytesTransferred);
        fetchFile(asyncResp, fileConn, readBuffer, output);
    });
}

inline void populateCustomNVMeControllerLink(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& storageId,
    const sdbusplus::message::object_path& controllerPath)
{
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.StorageController"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
        controllerPath / customNVMeAssociation,
        sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
        interfaces, requestContext,
        [asyncResp, systemName, storageId,
         controllerPath](const boost::system::error_code& ec,
                         const dbus::utility::MapperGetSubTreePathsResponse&
                             customNVMeList) {
        if (ec && ec.value() != EBADR)
        {
            BMCWEB_LOG_ERROR << "Failed to get " << customNVMe
                             << "Controllers for controller "
                             << controllerPath.str;
            redfish::messages::internalError(asyncResp->res);
            return;
        }

        if (customNVMeList.size() > 1)
        {
            BMCWEB_LOG_ERROR << "More than 1 " << customNVMe
                             << "Controller for controller "
                             << controllerPath.str;
            redfish::messages::internalError(asyncResp->res);
            return;
        }

        if (customNVMeList.empty())
        {
            return;
        }

        const sdbusplus::message::object_path path{customNVMeList[0]};

        redfish::storage_utils::findStorageForController(
            asyncResp, storageId, path,
            [asyncResp, systemName,
             path](const std::optional<sdbusplus::message::object_path>&
                       canonStoragePath) {
            if (canonStoragePath)
            {
                const std::string canonStorageId = canonStoragePath->filename();
                const std::string id = path.filename();
                asyncResp->res.jsonValue[std::string(customNVMe) + "Controller"]
                                        ["@odata.id"] =
                    crow::utility::urlFromPieces(
                        "redfish", "v1", "Systems", systemName, "Storage",
                        canonStorageId, "Controllers", id);
            }
        });
    });
}

inline void checkPrimary(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const sdbusplus::message::object_path& controllerPath)
{
    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.StorageController"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);

    managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
        controllerPath / "primary",
        sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
        interfaces, requestContext,
        [asyncResp,
         controllerPath](const boost::system::error_code& ec,
                         const dbus::utility::MapperGetSubTreePathsResponse&
                             controllerList) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "getAssociatedSubTreePaths for path "
                             << controllerPath.str << " failed with code "
                             << ec;
            redfish::messages::internalError(asyncResp->res);
            return;
        }

        asyncResp->res.jsonValue["ControllerType"] =
            controllerList.empty() ? "Primary" : "Secondary";
    });
}

inline void populateNVMeController(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& nvmeId,
    const std::string& controllerId, const std::string& controllerPath)
{
    constexpr std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.NVMe.NVMeAdmin"};
    managedStore::ManagedObjectStoreContext context(asyncResp);
    managedStore::GetManagedObjectStore()->getDbusObject(
        controllerPath, interfaces, context,
        [asyncResp, systemName, nvmeId, controllerId,
         controllerPath](const boost::system::error_code ec,
                         const dbus::utility::MapperGetObject& objects) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "GetObject for path " << controllerPath
                             << " failed with code " << ec;
            redfish::messages::internalError(asyncResp->res);
            return;
        }

        if (objects.size() != 1)
        {
            redfish::messages::internalError(asyncResp->res);
            BMCWEB_LOG_ERROR << "Service supporting " << controllerPath
                             << " is not equal to 1";
            return;
        }

        asyncResp->res.jsonValue["@odata.type"] =
            "#NVMeController.v1_0_0.NVMeController";
        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
            "google", "v1", "NVMe", nvmeId, "Controllers", controllerId);
        asyncResp->res.jsonValue["Name"] = "Google NVMe Controller";

        // NVMe actions
        asyncResp->res
            .jsonValue["Actions"]["#NVMeController.AdminNonDataCmd"]["target"] =
            crow::utility::urlFromPieces("google", "v1", "NVMe", nvmeId,
                                         "Controllers", controllerId, "Actions",
                                         "NVMeController.AdminNonDataCmd");
        asyncResp->res
            .jsonValue["Actions"]["#NVMeController.GetLogPage"]["target"] =
            crow::utility::urlFromPieces("google", "v1", "NVMe", nvmeId,
                                         "Controllers", controllerId, "Actions",
                                         "NVMeController.GetLogPage");
        asyncResp->res
            .jsonValue["Actions"]["#NVMeController.Identify"]["target"] =
            crow::utility::urlFromPieces("google", "v1", "NVMe", nvmeId,
                                         "Controllers", controllerId, "Actions",
                                         "NVMeController.Identify");
        asyncResp->res.jsonValue["Links"]["NVMe"]["@odata.id"] =
            crow::utility::urlFromPieces("google", "v1", "NVMe", nvmeId);
        asyncResp->res.jsonValue["StorageController"]["@odata.id"] =
            crow::utility::urlFromPieces("redfish", "v1", "Systems", systemName,
                                         "Storage", nvmeId, "Controllers",
                                         controllerId);
        if (enableCustomNVMe)
        {
            asyncResp->res.jsonValue["Actions"]["#NVMeController." +
                                                std::string(customNVMe) +
                                                "Identify"]["target"] =
            crow::utility::urlFromPieces(
                "google", "v1", "NVMe", nvmeId, "Controllers", controllerId,
                "Actions",
                "NVMeController." + std::string(customNVMe) + "Identify");
            populateCustomNVMeControllerLink(asyncResp, systemName, nvmeId,
                                             controllerPath);
            checkPrimary(asyncResp, controllerPath);
        }
    });
}

inline void
    setupNVMeController(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& systemName,
                        const std::string& nvmeId,
                        const std::string& controllerId,
                        const std::vector<std::string>& controllerList)
{
    if (controllerList.empty())
    {
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    for (const auto& controller : controllerList)
    {
        if (sdbusplus::message::object_path(controller).filename() !=
            controllerId)
        {
            continue;
        }
        populateNVMeController(asyncResp, systemName, nvmeId, controllerId, controller);
        return;
    }

    redfish::messages::internalError(asyncResp->res);
}

inline void populateNVMeControllerCollection(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& nvme, const boost::system::error_code ec,
    const nlohmann::json::json_pointer& jsonPtr,
    const std::vector<std::string>& controllerList)
{
    if (ec == boost::system::errc::io_error || controllerList.empty())
    {
        auto controllers = nlohmann::json::object();
        controllers["Name"] = "Google NVMe Controller Collection";
        controllers["@odata.id"] = crow::utility::urlFromPieces(
            "google", "v1", "NVMe", nvme, "Controllers");
        controllers["Members"] = nlohmann::json::array();
        controllers["Members@odata.count"] = 0;
        asyncResp->res.jsonValue[jsonPtr] = std::move(controllers);
        return;
    }

    if (ec)
    {
        BMCWEB_LOG_DEBUG << "DBUS response error " << ec.value();
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    auto controllers = nlohmann::json::object();
    controllers["Name"] = "Google NVMe Controller Collection";
    controllers["@odata.id"] = crow::utility::urlFromPieces(
        "google", "v1", "NVMe", nvme, "Controllers");
    nlohmann::json members = nlohmann::json::array();
    for (const std::string& controller : controllerList)
    {
        std::string name =
            sdbusplus::message::object_path(controller).filename();
        if (name.empty())
        {
            continue;
        }
        nlohmann::json::object_t member;
        member["@odata.id"] = crow::utility::urlFromPieces(
            "google", "v1", "NVMe", nvme, "Controllers", name);
        members.push_back(std::move(member));
    }
    controllers["Members@odata.count"] = members.size();
    controllers["Members"] = std::move(members);
    asyncResp->res.jsonValue[jsonPtr] = std::move(controllers);
}

inline void
    processDriveResource(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::optional<std::string>& nvme,
                         std::function<void(const std::string&)>&& cb)
{
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    constexpr std::array<std::string_view, 1> interfaces{
        "xyz.openbmc_project.Inventory.Item.Drive"};
    managedStore::GetManagedObjectStore()->getSubTree(
        "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
        [asyncResp, nvme, requestContext,
         cb{std::forward<std::function<void(const std::string&)>>(cb)}](
            const boost::system::error_code ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_INFO << "DBUS error: no matched iface for Drive: "
                            << ec.message();
            redfish::messages::internalError(asyncResp->res);
            return;
        }

        for (const auto& [path, services] : subtree)
        {
            if (nvme.has_value() &&
                sdbusplus::message::object_path(path).filename() != *nvme)
            {
                continue;
            }

            for (const auto& [service, interfaces] : services)
            {
                for (const std::string& interface : interfaces)
                {
                    if (interface != "xyz.openbmc_project.Inventory.Item.Drive")
                    {
                        continue;
                    }

                    redfish::dbus_utils::getProperty<std::string>(
                        service, path, interface, "Protocol", requestContext,
                        [path{path}, cb](const boost::system::error_code ec2,
                                         const std::string& driveProtocol) {
                        if (ec2)
                        {
                            return;
                        }

                        if (driveProtocol !=
                            "xyz.openbmc_project.Inventory.Item.Drive.DriveProtocol.NVMe")
                        {
                            return;
                        }

                        cb(path);
                        });

                    // If expecting valid NVMe, return after finding the first
                    // NVMe.
                    if (nvme.has_value())
                    {
                        return;
                    }
                }
            }
        }
        // Expecting valid NVMe
        if (nvme.has_value())
        {
            redfish::messages::internalError(asyncResp->res);
        }
    });
}

inline void handleGoogleNvmeController(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& nvme, NVMeControllerHandlerCb&& cb)
{
    processDriveResource(
        asyncResp, nvme,
        [asyncResp, cb{std::forward<NVMeControllerHandlerCb>(cb)}](
            const std::string& path) mutable {
        managedStore::ManagedObjectStoreContext requestContext(asyncResp);
        redfish::dbus_utils::getProperty<std::vector<std::string>>(
            "xyz.openbmc_project.ObjectMapper", path + "/storage_controller",
            "xyz.openbmc_project.Association", "endpoints", requestContext,
            [cb{std::move(cb)},
             path](const boost::system::error_code ec,
                   const std::vector<std::string>& controllerList) {
            cb(ec, path, controllerList);
        });
    });
}

inline void populateNVMe(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::string& path, const std::string& nvmeId)
{
    asyncResp->res.jsonValue["@odata.type"] = "#NVMe.v1_0_0.NVMe";
    asyncResp->res.jsonValue["@odata.id"] =
        crow::utility::urlFromPieces("google", "v1", "NVMe", nvmeId);
    asyncResp->res.jsonValue["Name"] = nvmeId;

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    redfish::dbus_utils::getProperty<std::vector<std::string>>(
        "xyz.openbmc_project.ObjectMapper", path + "/storage",
        "xyz.openbmc_project.Association", "endpoints", requestContext,
        [asyncResp, nvmeId,
         requestContext](const boost::system::error_code ec,
                         const std::vector<std::string>& storageList) {
        if (ec || storageList.empty())
        {
            BMCWEB_LOG_DEBUG
                << "Failed to find storage that is associated with " << nvmeId;
            return;
        }
        if (storageList.size() > 1)
        {
            BMCWEB_LOG_DEBUG << nvmeId
                             << " is associated with mutliple storages";
            return;
        }

        sdbusplus::message::object_path storagePath(storageList[0]);
        std::string storageId = storagePath.filename();
        if (storageId.empty())
        {
            BMCWEB_LOG_ERROR << "filename() is empty in " << storagePath.str;
            return;
        }
        redfish::storage_utils::getSystemPathFromStorage(
            asyncResp, storagePath,
            [asyncResp, storageId](std::optional<std::string_view> systemPath) {
            std::string systemName =
                systemPath ? std::filesystem::path(*systemPath).filename()
                           : "system";
            asyncResp->res.jsonValue["Links"]["Storage"]["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Systems",
                                             systemName, "Storage", storageId);
        });
    });

    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.NVMe.NVMeAdmin"};
    managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
        path + "/storage_controller",
        sdbusplus::message::object_path("/xyz/openbmc_project/inventory"), 0,
        interfaces, requestContext,
        [asyncResp, nvmeId](const boost::system::error_code& ec,
                            const dbus::utility::MapperGetSubTreePathsResponse&
                                controllerList) {
        populateNVMeControllerCollection(asyncResp, nvmeId, ec,
                                         "/Controllers"_json_pointer, controllerList);
    });
}

inline void
    handleGoogleNvme(App& app, const crow::Request& req,
                     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                     const std::string& nvme)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    processDriveResource(asyncResp, nvme,
                         [asyncResp, nvme](const std::string& path) {
        populateNVMe(asyncResp, path, nvme);
    });
}

inline void handleGoogleNvmeControllerCollection(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& nvme)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }
    processDriveResource(asyncResp, nvme,
                         [asyncResp, nvme](const std::string& path) {
        constexpr std::array<std::string_view, 1> interfaces = {
            "xyz.openbmc_project.NVMe.NVMeAdmin"};
        managedStore::ManagedObjectStoreContext requestContext(asyncResp);
        managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
            path + "/storage_controller",
            sdbusplus::message::object_path("/xyz/openbmc_project/inventory"),
            0, interfaces, requestContext,
            [asyncResp,
             nvme](const boost::system::error_code& ec,
                   const dbus::utility::MapperGetSubTreePathsResponse&
                       controllerList) {
            populateNVMeControllerCollection(asyncResp, nvme, ec,
                                             ""_json_pointer, controllerList);
        });
    });
}

inline void handleGoogleNvmeCollection(
    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"] =
        "#NVMeCollection.v1_0_0.NVMeCollection";
    asyncResp->res.jsonValue["@odata.id"] = "/google/v1/NVMe";
    asyncResp->res.jsonValue["Name"] = "Google NVMe Collection";

    asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
    asyncResp->res.jsonValue["Members@odata.count"] = 0;

    processDriveResource(asyncResp, std::nullopt,
                         [asyncResp](const std::string& path) {
        std::string id = sdbusplus::message::object_path(path).filename();
        if (id.empty())
        {
            return;
        }

        nlohmann::json& members = asyncResp->res.jsonValue["Members"];
        nlohmann::json::object_t member;
        member["@odata.id"] =
            crow::utility::urlFromPieces("google", "v1", "NVMe", id);
        members.push_back(std::move(member));
        asyncResp->res.jsonValue["Members@odata.count"] = members.size();
    });
}

inline void getIdentity(
    uint8_t cns, uint16_t cntid, uint32_t nsid,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& controllerId, const boost::system::error_code ec,
    const std::vector<std::string>& controllerList,
    const std::string& adminInterface = "xyz.openbmc_project.NVMe.NVMeAdmin")
{
    if (ec || controllerList.empty())
    {
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    std::string controllerPath;
    for (const std::string& controller : controllerList)
    {
        if (sdbusplus::message::object_path(controller).filename() ==
            controllerId)
        {
            controllerPath = controller;
            break;
        }
    }

    if (controllerPath.empty())
    {
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    managedStore::ManagedObjectStoreContext context(asyncResp);
    const std::string_view adminInterfaceView = adminInterface;
    std::span<const std::string_view> interfaces(&adminInterfaceView, 1);
    managedStore::GetManagedObjectStore()->getDbusObject(
        controllerPath, interfaces, context,
        [asyncResp, cns, cntid, nsid, controllerPath,
         adminInterface](const boost::system::error_code ec2,
                         const dbus::utility::MapperGetObject& objects) {
        if (ec2)
        {
            BMCWEB_LOG_ERROR << "GetObject for path " << controllerPath
                             << " failed with code " << ec2;
            return;
        }

        if (objects.size() != 1)
        {
            redfish::messages::internalError(asyncResp->res);
            BMCWEB_LOG_ERROR << "Service supporting " << controllerPath
                             << " is not equal to 1";
            return;
        }

        managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
            asyncResp->strand_,
            [asyncResp, objects,
             controllerPath](const boost::system::error_code ec3,
                             const sdbusplus::message::unix_fd& fd) {
            if (ec3)
            {
                BMCWEB_LOG_ERROR << "Failed to call NVMe Identity: "
                                 << ec3.message();
                redfish::messages::internalError(asyncResp->res);
                return;
            }

            int dupFd = dup(fd.fd);
            fetchFile(asyncResp,
                      std::make_shared<stream_descriptor>(*fdIOContext, dupFd));
            },
            objects[0].first, controllerPath, adminInterface, "Identify", cns,
            nsid, cntid);
    });
}

inline void handleGoogleNvmeControllerCustomNVMeIdentifyAction(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& nvmeId, const std::string& controllerId)
{
    uint8_t cns = 0;    // Controller or Namespace Structure
    uint16_t cntid = 0; // Controller Identifier
    uint32_t nsid = 0;  // Namespace Identifier

    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    if (!redfish::json_util::readJsonAction(req, asyncResp->res, "CNS", cns,
                                            "CNTID", cntid, "NSID", nsid))
    {
        redfish::messages::actionParameterMissing(
            asyncResp->res, "ControllerNamespace", "ControllerNamespaceId");
        return;
    }
    handleGoogleNvmeController(
        asyncResp, nvmeId,
        [cns, cntid, nsid, asyncResp,
         controllerId](const boost::system::error_code ec,
                       const std::string& /* storagePath */,
                       const std::vector<std::string>& controllerList) {
        getIdentity(
            cns, cntid, nsid, asyncResp, controllerId, ec, controllerList,
            "xyz.openbmc_project.NVMe." + std::string(customNVMe) + "Admin");
    });
}

inline void handleGoogleNvmeControllerIdentifyAction(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& nvmeId, const std::string& controllerId)
{
    uint8_t cns = 0;    // Controller or Namespace Structure
    uint16_t cntid = 0; // Controller Identifier
    uint32_t nsid = 0;  // Namespace Identifier

    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    if (!redfish::json_util::readJsonAction(req, asyncResp->res, "CNS", cns,
                                            "CNTID", cntid, "NSID", nsid))
    {
        redfish::messages::actionParameterMissing(
            asyncResp->res, "ControllerNamespace", "ControllerNamespaceId");
        return;
    }
    handleGoogleNvmeController(
        asyncResp, nvmeId,
        [cns, cntid, nsid, asyncResp,
         controllerId](const boost::system::error_code ec,
                       const std::string& /* storagePath */,
                       const std::vector<std::string>& controllerList) {
        getIdentity(cns, cntid, nsid, asyncResp, controllerId, ec,
                    controllerList);
    });
}

inline void adminNonDataCmd([[maybe_unused]] uint8_t opcode,[[maybe_unused]] uint32_t cdw1,[[maybe_unused]] uint32_t cdw2,
                            [[maybe_unused]] uint32_t cdw3,[[maybe_unused]] uint32_t cdw10,[[maybe_unused]] uint32_t cdw11,
                            [[maybe_unused]] uint32_t cdw12,[[maybe_unused]] uint32_t cdw13,[[maybe_unused]] uint32_t cdw14,
                            [[maybe_unused]] uint32_t cdw15,
                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                            const std::string& controllerId,
                            const boost::system::error_code ec,
                            const std::vector<std::string>& controllerList)
{
    if (ec || controllerList.empty())
    {
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    std::string controllerPath;
    for (const std::string& controller : controllerList)
    {
        if (sdbusplus::message::object_path(controller).filename() ==
            controllerId)
        {
            controllerPath = controller;
            break;
        }
    }

    if (controllerPath.empty())
    {
        BMCWEB_LOG_ERROR << "failed to find DBus controller path for "
                         << controllerId;
        redfish::messages::internalError(asyncResp->res);
        return;
    }

// The PostDbusCallToIoContextThreadSafe is NOT unitestable. MOCK_METHOD dosent work with this many params.
// If we want to unit test this funciton, we probably will have to change dbus.
#ifndef UNIT_TEST_BUILD

    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.NVMe.Passthru"};

    managedStore::ManagedObjectStoreContext context(asyncResp);
    managedStore::GetManagedObjectStore()->getDbusObject(
        controllerPath, interfaces, context,
        [asyncResp, opcode, cdw1, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14,
         cdw15, controllerPath](const boost::system::error_code ec2,
                                const dbus::utility::MapperGetObject& objects) {
        if (ec2)
        {
            BMCWEB_LOG_ERROR << "GetObject for path " << controllerPath
                             << " failed with code " << ec2;
            return;
        }

        if (objects.size() != 1)
        {
            redfish::messages::internalError(asyncResp->res);
            BMCWEB_LOG_ERROR << "Service supporting " << controllerPath
                             << " is not equal to 1";
            return;
        }

        const std::string& service {objects[0].first};

        managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
            asyncResp->strand_,
            [asyncResp](
                const boost::system::error_code ec3,
                const sdbusplus::message_t& msg,
                const std::tuple<uint32_t, uint32_t, uint32_t>& response) {
            const ::sd_bus_error* sd_err = msg.get_error();
            if (sd_err != nullptr)
            {
                redfish::messages::generalError(asyncResp->res);
                if (sd_err->message != nullptr)
                {
                    BMCWEB_LOG_ERROR << "Error: " << sd_err->name << " message "
                                     << sd_err->message;
                    asyncResp->res.jsonValue["error"]["message"] =
                        sd_err->message;
                }
                return;
            }

            if (ec3)
            {
                BMCWEB_LOG_ERROR << "AdminNonDataCmd dbus error " << ec3;
                redfish::messages::internalError(asyncResp->res);
                return;
            }

            // Success
            asyncResp->res.jsonValue["MIStatus"] = std::get<0>(response);
            asyncResp->res.jsonValue["AdminStatus"] = std::get<1>(response);
            asyncResp->res.jsonValue["CompletionDW0"] = std::get<2>(response);
        },
            service, controllerPath, "xyz.openbmc_project.NVMe.Passthru",
            "AdminNonDataCmd", opcode, cdw1, cdw2, cdw3, cdw10, cdw11, cdw12,
            cdw13, cdw14, cdw15);
    });
#endif
}

inline void getLogPage(
    uint8_t lid, // Log Page Identifier, Command Dword 10 bits[07:00]
    uint32_t nsid,
    uint8_t lsp,  // Log Specific Field,  Command Dword 10 bits[14:08]
    uint16_t lsi, // Log Specific Identifier, Command Dword 11 bits[31:16]
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& controllerId, const boost::system::error_code ec,
    const std::vector<std::string>& controllerList)
{
    if (ec || controllerList.empty())
    {
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    std::string controllerPath;
    for (const std::string& controller : controllerList)
    {
        if (sdbusplus::message::object_path(controller).filename() ==
            controllerId)
        {
            controllerPath = controller;
            break;
        }
    }

    if (controllerPath.empty())
    {
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    constexpr std::array<std::string_view, 1> interfaces = {
        "xyz.openbmc_project.NVMe.NVMeAdmin"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getDbusObject(
        controllerPath, interfaces, requestContext,
        [asyncResp, lid, nsid, lsp, lsi,
         controllerPath](const boost::system::error_code ec2,
                         const dbus::utility::MapperGetObject& objects) {
        if (ec2)
        {
            BMCWEB_LOG_ERROR << "GetObject for path " << controllerPath
                             << " failed with code " << ec2;
            return;
        }

        if (objects.size() != 1)
        {
            BMCWEB_LOG_ERROR << "Service supporting " << controllerPath
                             << " is not equal to 1";
            redfish::messages::internalError(asyncResp->res);
            return;
        }

        managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
            asyncResp->strand_,
            [asyncResp, objects,
             controllerPath](const boost::system::error_code ec3,
                             const sdbusplus::message::unix_fd& fd) {
            if (ec3)
            {
                BMCWEB_LOG_INFO << "Failed to call NVMe Log " << ec3.message();
                redfish::messages::internalError(asyncResp->res);
                return;
            }

            int dupFd = dup(fd.fd);
            fetchFile(asyncResp,
                      std::make_shared<stream_descriptor>(*fdIOContext, dupFd));
            },
            objects[0].first, controllerPath,
            "xyz.openbmc_project.NVMe.NVMeAdmin", "GetLogPage", lid, nsid, lsp,
            lsi);
    });
}

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

    uint8_t lid = 0; // Log Page Identifier, Command Dword 10 bits[07:00]
    uint32_t nsid = 0;
    uint8_t lsp = 0;  // Log Specific Field,  Command Dword 10 bits[14:08]
    uint16_t lsi = 0; // Log Specific Identifier, Command Dword 11 bits[31:16]

    if (!redfish::json_util::readJsonAction(req, asyncResp->res, "LID", lid,
                                            "NSID", nsid, "LSP", lsp, "LSI",
                                            lsi))
    {
        redfish::messages::actionParameterMissing(asyncResp->res,
                                                  "LogSpecificId", "LogId");
        return;
    }

    handleGoogleNvmeController(
        asyncResp, nvmeId,
        [lid, nsid, lsp, lsi, asyncResp,
         controllerId](const boost::system::error_code ec,
                       const std::string& /* storagePath */,
                       const std::vector<std::string>& controllerList) {
        getLogPage(lid, nsid, lsp, lsi, asyncResp, controllerId, ec,
                   controllerList);
    });
}

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

    // Only opcode is mandatory
    uint8_t opcode = 0;
    std::optional<uint32_t> cdw1;
    std::optional<uint32_t> cdw2;
    std::optional<uint32_t> cdw3;
    std::optional<uint32_t> cdw10;
    std::optional<uint32_t> cdw11;
    std::optional<uint32_t> cdw12;
    std::optional<uint32_t> cdw13;
    std::optional<uint32_t> cdw14;
    std::optional<uint32_t> cdw15;

    if (!redfish::json_util::readJsonAction(
            req, asyncResp->res, "opcode", opcode, "cdw1", cdw1, "cdw2", cdw2,
            "cdw3", cdw3, "cdw10", cdw10, "cdw11", cdw11, "cdw12", cdw12,
            "cdw13", cdw13, "cdw14", cdw14, "cdw15", cdw15))
    {
        redfish::messages::actionParameterMissing(
            asyncResp->res, "NVMeController.AdminNonDataCmd", "opcode");
        return;
    }

    handleGoogleNvmeController(
        asyncResp, nvmeId,
        [opcode, cdw1{cdw1.value_or(0)}, cdw2{cdw2.value_or(0)},
         cdw3{cdw3.value_or(0)}, cdw10{cdw10.value_or(0)},
         cdw11{cdw11.value_or(0)}, cdw12{cdw12.value_or(0)},
         cdw13{cdw13.value_or(0)}, cdw14{cdw14.value_or(0)},
         cdw15{cdw15.value_or(0)}, asyncResp,
         controllerId](const boost::system::error_code ec,
                       const std::string& /* storagePath */,
                       const std::vector<std::string>& controllerList) {
        adminNonDataCmd(opcode, cdw1, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13,
                        cdw14, cdw15, asyncResp, controllerId, ec,
                        controllerList);
    });
}

inline void setupGoogleNVMeFdFetchIOContext(
    const std::shared_ptr<boost::asio::io_context>& ioc)
{
    fdIOContext = ioc;
}

inline void requestGoogleNVMeControllerActionCustomNVMeIdentify(App& app)
{
    BMCWEB_ROUTE(
        app, "/google/v1/NVMe/<str>/Controllers/<str>/Actions/NVMeController." +
                 std::string(customNVMe) + "Identify")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::post)(std::bind_front(
            handleGoogleNvmeControllerCustomNVMeIdentifyAction, std::ref(app)));
}

inline void requestGoogleNVMeControllerActionIdentify(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/google/v1/NVMe/<str>/Controllers/<str>/Actions/NVMeController.Identify")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::post)(std::bind_front(
            handleGoogleNvmeControllerIdentifyAction, std::ref(app)));
}

inline void requestGoogleNVMeControllerActionLog(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/google/v1/NVMe/<str>/Controllers/<str>/Actions/NVMeController.GetLogPage")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::post)(std::bind_front(
            handleGoogleNvmeControllerLogAction, std::ref(app)));
}

inline void requestGoogleNVMeControllerActionAdminNonData(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/google/v1/NVMe/<str>/Controllers/<str>/Actions/NVMeController.AdminNonDataCmd")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::post)(std::bind_front(
            handleGoogleNvmeControllerAdminNonDataAction, std::ref(app)));
}

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

    handleGoogleNvmeController(
        asyncResp, nvmeId,
        [asyncResp, nvmeId, controllerId](
            const boost::system::error_code ec, const std::string& storagePath,
            const std::vector<std::string>& controllerList) {
        if (ec)
        {
            redfish::messages::internalError(asyncResp->res);
            return;
        }
        redfish::storage_utils::getSystemPathFromStorage(
            asyncResp, storagePath,
            [asyncResp, nvmeId, controllerId,
             controllerList](std::optional<std::string_view> systemPath) {
            std::string systemName =
                systemPath ? std::filesystem::path(*systemPath).filename()
                           : "system";
            setupNVMeController(asyncResp, systemName, nvmeId, controllerId,
                                controllerList);
        });
    });
}

inline void requestGoogleNVMeController(App& app)
{
    BMCWEB_ROUTE(app, "/google/v1/NVMe/<str>/Controllers/<str>")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleGoogleNVMeControllerGet, std::ref(app)));
}

inline void requestGoogleNVMeControllerCollection(App& app)
{
    BMCWEB_ROUTE(app, "/google/v1/NVMe/<str>/Controllers")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::get)(std::bind_front(
            handleGoogleNvmeControllerCollection, std::ref(app)));
}

inline void requestGoogleNVMe(App& app)
{
    BMCWEB_ROUTE(app, "/google/v1/NVMe/<str>")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleGoogleNvme, std::ref(app)));
}

inline void requestGoogleNVMeCollection(App& app)
{
    BMCWEB_ROUTE(app, "/google/v1/NVMe")
        .privileges({{"ConfigureManager"}})
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleGoogleNvmeCollection, std::ref(app)));
}

} // namespace google_api
} // namespace crow
