#include "NVMeController.hpp"

#include "dbus-sensor_config.h"

#include "AsioHelper.hpp"
#include "NVMeCacheImpl.hpp"
#include "NVMeError.hpp"
#include "NVMePlugin.hpp"
#include "NVMeSubsys.hpp"

#include <boost/asio/async_result.hpp>
#include <boost/asio/spawn.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/exception.hpp>
#include <sdbusplus/message/native_types.hpp>
#include <xyz/openbmc_project/Common/File/error.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

#include <cstdint>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <system_error>
#include <tuple>
#include <vector>

// using sdbusplus::xyz::openbmc_project::Inventory::Item::server::
//     StorageController;
using sdbusplus::xyz::openbmc_project::NVMe::server::NVMeAdmin;
using SchedulerClockType = std::chrono::steady_clock;

inline std::optional<std::string> findPluginName(const SensorData& config)
{
    // find base configuration
    auto sensorBase = config.find(configInterfaceName(nvme::sensorType));
    if (sensorBase == config.end())
    {
        return {};
    }
    const SensorBaseConfigMap& sensorConfig = sensorBase->second;
    auto findPlugin = sensorConfig.find("Plugin");
    if (findPlugin == sensorConfig.end())
    {
        return std::nullopt;
    }
    return std::get<std::string>(findPlugin->second);
}

std::shared_ptr<NVMeControllerEnabled>
    NVMeControllerEnabled::create(NVMeController&& nvmeController)
{
    auto self = std::shared_ptr<NVMeControllerEnabled>(
        new NVMeControllerEnabled(std::move(nvmeController)));
    self->init();
    return self;
}

NVMeControllerEnabled::NVMeControllerEnabled(NVMeController&& nvmeController) :
    NVMeController(nvmeController),
    NVMeAdmin(*this->NVMeController::conn, this->NVMeController::path.c_str(),
              {{"FirmwareCommitStatus", {FwCommitStatus::Ready}},
               {"FirmwareDownloadStatus", {FwDownloadStatus::Ready}}}),
    SoftwareExtVersion(dynamic_cast<sdbusplus::bus_t&>(*conn), path.c_str()),
    SoftwareVersion(dynamic_cast<sdbusplus::bus_t&>(*conn), path.c_str())
{}

void NVMeControllerEnabled::init()
{
    createAssociation();

    passthruInterface =
        objServer.add_interface(path, "xyz.openbmc_project.NVMe.Passthru");

    passthruInterface->register_method(
        "AdminNonDataCmd",
        [selfWeak{weak_from_this()}](
            boost::asio::yield_context yield, uint8_t opcode, uint32_t cdw1,
            uint32_t cdw2, uint32_t cdw3, uint32_t cdw10, uint32_t cdw11,
            uint32_t cdw12, uint32_t cdw13, uint32_t cdw14, uint32_t cdw15) {
        auto self = selfWeak.lock();
        if (!self)
        {
            checkLibNVMeError(std::make_error_code(std::errc::no_such_device),
                              -1, "AdminNonDataCmd");
            return std::tuple<uint32_t, uint32_t, uint32_t>{0, 0, 0};
        }

        if (self->status != Status::Enabled)
        {
            lg2::error("Controller has been disabled");
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }
        return self->adminNonDataCmdMethod(std::move(yield), opcode, cdw1, cdw2,
                                           cdw3, cdw10, cdw11, cdw12, cdw13,
                                           cdw14, cdw15);
    });
    passthruInterface->initialize();

    securityInterface = objServer.add_interface(
        path, "xyz.openbmc_project.Inventory.Item.StorageControllerSecurity");
    securityInterface->register_method(
        "SecuritySend", [selfWeak{weak_from_this()}](
                            boost::asio::yield_context yield, uint8_t proto,
                            uint16_t protoSpecific, std::vector<uint8_t> data) {
        auto self = selfWeak.lock();
        if (!self)
        {
            checkLibNVMeError(std::make_error_code(std::errc::no_such_device),
                              -1, "SecuritySend");
            return;
        }

        if (self->status != Status::Enabled)
        {
            lg2::error("Controller has been disabled");
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }

        return self->securitySendMethod(std::move(yield), proto, protoSpecific,
                                        data);
    });
    securityInterface->register_method(
        "SecurityReceive",
        [selfWeak{weak_from_this()}](boost::asio::yield_context yield,
                                     uint8_t proto, uint16_t protoSpecific,
                                     uint32_t transferLength) {
        auto self = selfWeak.lock();
        if (!self)
        {
            checkLibNVMeError(std::make_error_code(std::errc::no_such_device),
                              -1, "SecurityReceive");
            return std::vector<uint8_t>{};
        }

        if (self->status != Status::Enabled)
        {
            lg2::error("Controller has been disabled");
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }

        return self->securityReceiveMethod(std::move(yield), proto,
                                           protoSpecific, transferLength);
    });

    if (this->featureLockdownEnabled)
    {
        lockdownInterface =
            objServer.add_interface(path, "xyz.openbmc_project.NVMe.Lockdown");

        lockdownInterface->register_method(
            "LockdownInband",
            [selfWeak{weak_from_this()}](boost::asio::yield_context yield,
                                         uint8_t prohibit,
                                         const std::vector<uint8_t>& adminCmds,
                                         const std::vector<uint8_t>& features,
                                         const std::vector<uint8_t>& logPages) {
            auto self = selfWeak.lock();
            if (!self)
            {
                checkLibNVMeError(
                    std::make_error_code(std::errc::no_such_device), -1,
                    "LockdownInband");
                return std::tuple<uint32_t, uint32_t, uint32_t, std::string,
                                  uint32_t>{0, 0, 0, "", 0};
            }

            if (self->status != Status::Enabled)
            {
                lg2::error("Controller has been disabled");
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    Unavailable();
            }

            return self->lockdownInbandMethod(std::move(yield), prohibit,
                                              adminCmds, features, logPages);
        });
        lockdownInterface->initialize();
    }

    // StorageController interface is implemented manually to allow
    // async methods
    ctrlInterface = objServer.add_interface(
        path, "xyz.openbmc_project.Inventory.Item.StorageController");
    ctrlInterface->register_method(
        "AttachVolume", [selfWeak{weak_from_this()}](
                            boost::asio::yield_context yield,
                            const sdbusplus::message::object_path& volPath) {
        auto self = selfWeak.lock();
        if (!self)
        {
            checkLibNVMeError(std::make_error_code(std::errc::no_such_device),
                              -1, "SecurityReceive");
            return;
        }

        if (self->status != Status::Enabled)
        {
            lg2::error("Controller has been disabled");
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }

        return self->attachVolume(std::move(yield), volPath);
    });
    ctrlInterface->register_method(
        "DetachVolume", [selfWeak{weak_from_this()}](
                            boost::asio::yield_context yield,
                            const sdbusplus::message::object_path& volPath) {
        auto self = selfWeak.lock();
        if (!self)
        {
            checkLibNVMeError(std::make_error_code(std::errc::no_such_device),
                              -1, "SecurityReceive");
            return;
        }

        if (self->status != Status::Enabled)
        {
            lg2::error("Controller has been disabled");
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }

        return self->detachVolume(std::move(yield), volPath);
    });

    ctrlInterface->initialize();

    securityInterface->initialize();
    // StorageController::emit_added();

    NVMeAdmin::emit_added();
    SoftwareExtVersion::emit_added();
    SoftwareVersion::emit_added();
}

void NVMeControllerEnabled::initializeMetricStore()
{
    // if metric store feature is disabled then create empty metric store
    // the dbus interface will be there but with no metrics
    if (metricStoreFeature == MetricStoreFeature::Disabled)
    {
        this->metricStore.emplace(this->NVMeController::io,
                                  this->NVMeController::conn,
                                  this->NVMeController::path);
        return;
    }
    auto scheduler = Scheduler<SchedulerClockType>::getScheduler(path);

    using IdentifyMetric =
        IdentifyMetric<NVME_IDENTIFY_CNS_CTRL, SchedulerClockType>;

    using ErrorInfoMetric =
        ControllerLogPageMetric<NVME_LOG_LID_ERROR, SchedulerClockType>;
    using SMARTMetric =
        ControllerLogPageMetric<NVME_LOG_LID_SMART, SchedulerClockType>;
    using FwSlotMetric =
        ControllerLogPageMetric<NVME_LOG_LID_FW_SLOT, SchedulerClockType>;
    using SelfTestMetric =
        ControllerLogPageMetric<NVME_LOG_LID_DEVICE_SELF_TEST,
                                SchedulerClockType>;
    using HostTelemetryMetric =
        ControllerLogPageMetric<NVME_LOG_LID_TELEMETRY_HOST,
                                SchedulerClockType>;

    auto identify = std::make_shared<IdentifyMetric>(
        this->shared_from_this(), scheduler,
        // Metigate solution before Knuckle FW fix for b/404610159
        std::chrono::seconds(60));

    auto errorInfo = std::make_shared<ErrorInfoMetric>(
        this->weak_from_this(), scheduler,
        // TODO: configurable interval
        std::chrono::duration_cast<SchedulerClockType::duration>(
            std::chrono::seconds(60)));

    auto smart = std::make_shared<SMARTMetric>(
        this->weak_from_this(), scheduler,
        // TODO: configurable interval
        std::chrono::duration_cast<SchedulerClockType::duration>(
            std::chrono::seconds(60)));

    auto fwSlot = std::make_shared<FwSlotMetric>(
        this->weak_from_this(), scheduler,
        // TODO: configurable interval
        std::chrono::duration_cast<SchedulerClockType::duration>(
            std::chrono::seconds(60)));

    auto selfTest = std::make_shared<SelfTestMetric>(
        this->weak_from_this(), scheduler,
        // TODO: configurable interval
        std::chrono::duration_cast<SchedulerClockType::duration>(
            std::chrono::seconds(60)));
    auto pluginName = findPluginName(config);
    auto hostTelemetry =
        (!pluginName || pluginName != "OCP")
            ? std::make_shared<HostTelemetryMetric>(
                  this->weak_from_this(), scheduler,
                  // TODO: configurable interval
                  std::chrono::duration_cast<SchedulerClockType::duration>(
                      std::chrono::seconds(900)))
            : std::shared_ptr<HostTelemetryMetric>();

    std::list<std::shared_ptr<MetricBase<SchedulerClockType>>> metrics{
        std::move(identify), std::move(errorInfo), std::move(smart),
        std::move(fwSlot),   std::move(selfTest),  std::move(hostTelemetry)};

    this->metricStore.emplace(
        this->NVMeController::io, this->NVMeController::conn,
        this->NVMeController::path, metrics.begin(), metrics.end());
}

void NVMeControllerEnabled::start(
    const std::shared_ptr<NVMeControllerPlugin>& nvmePlugin)
{
    this->NVMeController::start(nvmePlugin);

    if (isPrimary)
    {
        this->initializeMetricStore();
    }
    status = Status::Enabled;
}

void NVMeControllerEnabled::stop()
{
    status = Status::Disabled;
    this->metricStore.reset();
}

void NVMeController::createAssociation()
{
    assocIntf = objServer.add_interface(path, association::interface);
    assocIntf->register_property("Associations", makeAssociation());
    assocIntf->initialize();
}

void NVMeController::updateAssociation()
{
    if (assocIntf)
    {
        assocIntf->set_property("Associations", makeAssociation());
    }
}

std::vector<Association> NVMeController::makeAssociation() const
{
    std::vector<Association> associations;
    std::filesystem::path p(path);

    auto s = subsys.lock();
    if (!s)
    {
        lg2::error("makeAssociation() after shutdown");
        return associations;
    }

    associations.emplace_back("storage", "storage_controller", s->path);

    for (const auto& cntrl : secondaryControllers)
    {
        associations.emplace_back("secondary", "primary", cntrl);
    }

    for (uint32_t nsid : s->attachedVolumes(getCntrlId()))
    {
        auto p = s->volumePath(nsid);
        associations.emplace_back("attaching", "attached", p);
    }

    return associations;
}

sdbusplus::message::unix_fd NVMeControllerEnabled::getLogPage(uint8_t lid,
                                                              uint32_t nsid,
                                                              uint8_t lsp,
                                                              uint16_t lsi)
{
    if (status != Status::Enabled)
    {
        lg2::error("Controller has been disabled");
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    std::array<int, 2> pipe{};
    if (::pipe(pipe.data()) < 0)
    {
        lg2::error("GetLogPage fails to open pipe: {ERROR}", "ERROR",
                   strerror(errno));
        throw sdbusplus::xyz::openbmc_project::Common::File::Error::Open();
    }

    // standard NVMe Log IDs
    if (lid < uint8_t{0xC0})
    {
        nvmeIntf->adminGetLogPage(
            nvmeCtrl, static_cast<nvme_cmd_get_log_lid>(lid), nsid, lsp, lsi,
            [pipe, &io = this->io](const std::error_code& ec,
                                   std::span<uint8_t> data) {
            if (ec)
            {
                lg2::error("fail to GetLogPage: {ERROR}", "ERROR",
                           ec.message());
                close(pipe[1]);
                close(pipe[0]);
                return;
            }

            // async write to pipe
            auto asyncPipe =
                std::make_shared<boost::asio::posix::stream_descriptor>(
                    io, pipe[1]);
            std::weak_ptr<boost::asio::posix::stream_descriptor> weakPipe =
                asyncPipe;

            auto asyncBuffer = std::make_shared<std::vector<uint8_t>>(
                data.begin(), data.end());
            boost::asio::async_write(
                *asyncPipe, boost::asio::buffer(*asyncBuffer),
                [asyncPipe, asyncBuffer](const boost::system::error_code& error,
                                         std::size_t /* transferredSize */) {
                if (error)
                {
                    lg2::error("GetLogPage fails to write fd: {ERROR}", "ERROR",
                               error.message());
                }
            });

            // set a timer of 5 second for the client to read the telemetry.
            auto timer = std::make_shared<boost::asio::steady_timer>(io);
            timer->expires_after(std::chrono::seconds(5));
            timer->async_wait([timer, fd{pipe[0]}, weakPipe](
                                  const boost::system::error_code& /* ec */) {
                auto pipe = weakPipe.lock();
                if (pipe)
                {
                    pipe->cancel();
                }
                close(fd);
            });
        });
    }
    // vendor Log IDs
    else if (!plugin.expired())
    {
        auto nvmePlugin = plugin.lock();
        auto handler = nvmePlugin->getGetLogPageHandler();
        if (handler)
        {
            std::function<void(const std::error_code&, std::span<uint8_t>)> cb =
                [pipe, &io = this->io](std::error_code ec,
                                       std::span<uint8_t> data) {
                if (ec)
                {
                    lg2::error("fail to GetLogPage: {ERROR}", "ERROR",
                               ec.message());
                    close(pipe[1]);
                    close(pipe[0]);
                    return;
                }

                // async write to pipe
                auto asyncPipe =
                    std::make_shared<boost::asio::posix::stream_descriptor>(
                        io, pipe[1]);
                std::weak_ptr<boost::asio::posix::stream_descriptor> weakPipe =
                    asyncPipe;

                auto asyncBuffer = std::make_shared<std::vector<uint8_t>>(
                    data.begin(), data.end());
                boost::asio::async_write(
                    *asyncPipe, boost::asio::buffer(*asyncBuffer),
                    [asyncPipe,
                     asyncBuffer](const boost::system::error_code& error,
                                  std::size_t /* transferredSize */) {
                    if (error)
                    {
                        lg2::error("GetLogPage fails to write fd: {ERROR}",
                                   "ERROR", error.message());
                    }
                });

                // set a timer of 5 second for the client to read the telemetry.
                auto timer = std::make_shared<boost::asio::steady_timer>(io);
                timer->expires_after(std::chrono::seconds(5));
                timer->async_wait(
                    [timer, fd{pipe[0]},
                     weakPipe](const boost::system::error_code& /* ec */) {
                    auto pipe = weakPipe.lock();
                    if (pipe)
                    {
                        pipe->cancel();
                    }
                    close(fd);
                });
            };
            handler(lid, nsid, lsp, lsi, std::move(cb));
        }
        else // No VU LogPage handler
        {
            close(pipe[1]);
            close(pipe[0]);
            throw sdbusplus::xyz::openbmc_project::Common::Error::
                InvalidArgument();
        }
    }
    else // No VU plugin
    {
        close(pipe[0]);
        close(pipe[1]);
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }
    return sdbusplus::message::unix_fd{pipe[0]};
}

sdbusplus::message::unix_fd
    NVMeControllerEnabled::identify(uint8_t cns, uint32_t nsid, uint16_t cntid)
{
    if (status != Status::Enabled)
    {
        lg2::error("Controller has been disabled");
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    std::array<int, 2> pipe{};
    if (::pipe(pipe.data()) < 0)
    {
        lg2::error("Identify fails to open pipe: {ERROR}", "ERROR",
                   strerror(errno));
        throw sdbusplus::xyz::openbmc_project::Common::File::Error::Open();
    }

    nvmeIntf->adminIdentify(
        nvmeCtrl, static_cast<nvme_identify_cns>(cns), nsid, cntid,
        [pipe, &io = this->io](const nvme_ex_ptr& ex, std::span<uint8_t> data) {
        if (ex)
        {
            lg2::error("fail to Identify: {ERROR}", "ERROR", ex->what());
            close(pipe[1]);
            close(pipe[0]);
            return;
        }

        // async write to pipe
        auto asyncPipe =
            std::make_shared<boost::asio::posix::stream_descriptor>(io,
                                                                    pipe[1]);
        std::weak_ptr<boost::asio::posix::stream_descriptor> weakPipe =
            asyncPipe;

        auto asyncBuffer = std::make_shared<std::vector<uint8_t>>(data.begin(),
                                                                  data.end());
        boost::asio::async_write(
            *asyncPipe, boost::asio::buffer(*asyncBuffer),
            [asyncPipe, asyncBuffer](const boost::system::error_code& error,
                                     std::size_t /* transferredSize */) {
            if (error)
            {
                lg2::error("Identify fails to write fd: {ERROR}", "ERROR",
                           error.message());
            }
        });

        // set a timer of 5 second for the client to read the telemetry.
        auto timer = std::make_shared<boost::asio::steady_timer>(io);
        timer->expires_after(std::chrono::seconds(5));
        timer->async_wait([timer, fd{pipe[0]}, weakPipe](
                              const boost::system::error_code& /* ec */) {
            auto pipe = weakPipe.lock();
            if (pipe)
            {
                pipe->cancel();
            }
            close(fd);
        });
    });
    return sdbusplus::message::unix_fd{pipe[0]};
}

NVMeAdmin::FwCommitStatus NVMeControllerEnabled::firmwareCommitStatus(
    NVMeAdmin::FwCommitStatus status)
{
    auto commitStatus = this->NVMeAdmin::firmwareCommitStatus();
    // The function is only allowed to reset the status back to ready
    if (status != FwCommitStatus::Ready ||
        commitStatus == FwCommitStatus::Ready ||
        commitStatus == FwCommitStatus::InProgress)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed{};
    }
    return this->NVMeAdmin::firmwareCommitStatus(status);
}

void NVMeControllerEnabled::firmwareCommitAsync(uint8_t commitAction,
                                                uint8_t firmwareSlot, bool bpid)
{
    auto commitStatus = this->NVMeAdmin::firmwareCommitStatus();
    if (commitStatus != FwCommitStatus::Ready)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed();
    }

    if (status != Status::Enabled)
    {
        lg2::error("Controller has been disabled");
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    this->NVMeAdmin::firmwareCommitStatus(FwCommitStatus::InProgress);
    nvmeIntf->adminFwCommit(
        nvmeCtrl, static_cast<nvme_fw_commit_ca>(commitAction & 0b111),
        firmwareSlot, bpid,
        [self{shared_from_this()}](const std::error_code& ec,
                                   nvme_status_field status) {
        if (ec)
        {
            self->NVMeAdmin::firmwareCommitStatus(FwCommitStatus::Failed);
            return;
        }
        if (status != NVME_SC_SUCCESS)
        {
            self->NVMeAdmin::firmwareCommitStatus(FwCommitStatus::RequireReset);
            return;
        }

        self->NVMeAdmin::firmwareCommitStatus(FwCommitStatus::Success);
    });
}

NVMeAdmin::FwDownloadStatus NVMeControllerEnabled::firmwareDownloadStatus(
    NVMeAdmin::FwDownloadStatus status)
{
    auto downloadStatus = this->NVMeAdmin::firmwareDownloadStatus();
    // The function is only allowed to reset the status back to ready
    if (status != FwDownloadStatus::Ready ||
        downloadStatus == FwDownloadStatus::Ready ||
        downloadStatus == FwDownloadStatus::InProgress)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed{};
    }
    return this->NVMeAdmin::firmwareDownloadStatus(status);
}

void NVMeControllerEnabled::firmwareDownloadAsync(std::string pathToImage)
{
    auto downloadStatus = this->NVMeAdmin::firmwareDownloadStatus();
    if (downloadStatus != FwDownloadStatus::Ready)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed();
    }
    if (std::filesystem::exists(pathToImage))
    {
        this->NVMeAdmin::firmwareDownloadStatus(FwDownloadStatus::InProgress);
        nvmeIntf->adminFwDownload(
            nvmeCtrl, pathToImage,
            [self{shared_from_this()}](const std::error_code& ec,
                                       nvme_status_field status) {
            if (ec || status != NVME_SC_SUCCESS)
            {
                self->NVMeAdmin::firmwareDownloadStatus(
                    FwDownloadStatus::Failed);
                return;
            }
            self->NVMeAdmin::firmwareDownloadStatus(FwDownloadStatus::Success);
        });
    }
    else
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
    }
}

NVMeControllerEnabled::~NVMeControllerEnabled()
{
    objServer.remove_interface(securityInterface);
    objServer.remove_interface(passthruInterface);
    if (lockdownInterface)
    {
        objServer.remove_interface(lockdownInterface);
    }
    SoftwareVersion::emit_removed();
    SoftwareExtVersion::emit_removed();
    NVMeAdmin::emit_removed();
    // StorageController::emit_removed();
    objServer.remove_interface(ctrlInterface);
}

NVMeController::NVMeController(
    boost::asio::io_context& io, sdbusplus::asio::object_server& objServer,
    std::shared_ptr<sdbusplus::asio::connection> conn, std::string path,
    const SensorData& configData, std::shared_ptr<NVMeMiIntf> nvmeIntf,
    nvme_mi_ctrl_t ctrl, std::weak_ptr<NVMeSubsystem> subsys,
    bool enableFeatureLockdown) :
    isPrimary(true), io(io), objServer(objServer), conn(std::move(conn)),
    path(std::move(path)), config(configData), nvmeIntf(std::move(nvmeIntf)),
    nvmeCtrl(ctrl), subsys(std::move(subsys)),
    featureLockdownEnabled(enableFeatureLockdown)
{}

NVMeController::~NVMeController()
{
    objServer.remove_interface(assocIntf);
}

void NVMeController::start(
    const std::shared_ptr<NVMeControllerPlugin>& nvmePlugin)
{
    plugin = nvmePlugin;
}

void NVMeController::stop() {}

void NVMeController::setSecAssoc(
    const std::vector<std::shared_ptr<NVMeController>>& secCntrls)
{
    secondaryControllers.clear();

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

    for (const auto& cntrl : secCntrls)
    {
        secondaryControllers.push_back(cntrl->path);
    }
    updateAssociation();
}

void NVMeControllerEnabled::securitySendMethod(boost::asio::yield_context yield,
                                               uint8_t proto,
                                               uint16_t protoSpecific,
                                               std::span<uint8_t> data)
{
    if (status != Status::Enabled)
    {
        lg2::error("Controller has been disabled");
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    using callback_t = void(std::tuple<std::error_code, int>);
    auto [err, nvmeStatus] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, proto, protoSpecific,
             &data](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminSecuritySend(
            ctrl, proto, protoSpecific, data,
            [h](const std::error_code& err, int nvmeStatus) mutable {
            h(std::make_tuple(err, nvmeStatus));
        });
    },
            yield);

    // exception must be thrown outside of the async block
    checkLibNVMeError(err, nvmeStatus, "SecuritySend");
}

std::vector<uint8_t> NVMeControllerEnabled::securityReceiveMethod(
    boost::asio::yield_context yield, uint8_t proto, uint16_t protoSpecific,
    uint32_t transferLength)
{
    if (status != Status::Enabled)
    {
        lg2::error("Controller has been disabled");
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    using callback_t =
        void(std::tuple<std::error_code, int, std::vector<uint8_t>>);
    auto [err, nvmeStatus, data] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, proto, protoSpecific,
             transferLength](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminSecurityReceive(ctrl, proto, protoSpecific, transferLength,
                                   [h](const std::error_code& err,
                                       int nvmeStatus,
                                       std::span<uint8_t> data) mutable {
            std::vector<uint8_t> d(data.begin(), data.end());
            h(std::make_tuple(err, nvmeStatus, d));
        });
    },
            yield);

    // exception must be thrown outside of the async block
    checkLibNVMeError(err, nvmeStatus, "SecurityReceive");
    return data;
}

std::tuple<uint32_t, uint32_t, uint32_t>
    NVMeControllerEnabled::adminNonDataCmdMethod(
        boost::asio::yield_context yield, uint8_t opcode, uint32_t cdw1,
        uint32_t cdw2, uint32_t cdw3, uint32_t cdw10, uint32_t cdw11,
        uint32_t cdw12, uint32_t cdw13, uint32_t cdw14, uint32_t cdw15)
{
    using callback_t = void(std::tuple<std::error_code, int, uint32_t>);
    auto [err, nvmeStatus, completionDw0] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, opcode, cdw1, cdw2, cdw3, cdw10,
             cdw11, cdw12, cdw13, cdw14, cdw15](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminNonDataCmd(ctrl, opcode, cdw1, cdw2, cdw3, cdw10, cdw11,
                              cdw12, cdw13, cdw14, cdw15,
                              [h](const std::error_code& err, int nvmeStatus,
                                  uint32_t completionDw0) mutable {
            h(std::make_tuple(err, nvmeStatus, completionDw0));
        });
    },
            yield);

    lg2::debug("nvme_status:{STATUS}, dw0:{DW0}", "STATUS", nvmeStatus, "DW0",
               completionDw0);
    if (nvmeStatus < 0)
    {
        throw sdbusplus::exception::SdBusError(err.value(),
                                               "adminNonDataCmdMethod");
    }

    // Parse MI status Or MI status from nvme_status
    uint32_t miStatus = 0;
    uint32_t adminStatus = 0;
    if (nvme_status_get_type(nvmeStatus) == NVME_STATUS_TYPE_MI)
    {
        // there is no Admin status and dw0 if MI layer failed.
        miStatus = nvme_status_get_value(nvmeStatus);
        adminStatus = 0;
        completionDw0 = 0;
    }
    else
    {
        miStatus = 0;
        adminStatus = nvme_status_get_value(nvmeStatus);
    }
    return {miStatus, adminStatus, completionDw0};
}

std::tuple<uint32_t, uint32_t, uint32_t, std::string, uint32_t>
    NVMeControllerEnabled::lockdownInbandMethod(
        boost::asio::yield_context yield, uint8_t prohibit,
        const std::vector<uint8_t>& adminCmds,
        const std::vector<uint8_t>& features,
        const std::vector<uint8_t>& logPages)
{
    using callback_t =
        void(std::tuple<std::error_code, int, uint32_t, std::string, uint32_t>);

    auto [err, nvmeStatus, completionDw0, failureScope, failureId] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, prohibit, adminCmds, features,
             logPages](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminLockdownInband(ctrl, prohibit, adminCmds, features, logPages,
                                  [h](const std::error_code& err,
                                      int nvmeStatus, uint32_t completionDw0,
                                      const std::string& scope,
                                      uint32_t id) mutable {
            h(std::make_tuple(err, nvmeStatus, completionDw0, scope, id));
        });
    },
            yield);

    lg2::debug("NVMe command result: status={STATUS}, dw0={DW0}", "STATUS",
               nvmeStatus, "DW0", completionDw0);
    if (nvmeStatus < 0)
    {
        throw sdbusplus::exception::SdBusError(err.value(),
                                               "lockdownInbandMethod");
    }

    uint32_t miStatus = 0;
    uint32_t adminStatus = 0;
    if (nvme_status_get_type(nvmeStatus) == NVME_STATUS_TYPE_MI)
    {
        // If it's an MI status (e.g., protocol failure), Admin status is 0.
        miStatus = nvme_status_get_value(nvmeStatus);
        adminStatus = 0;
        completionDw0 = 0;
    }
    else
    {
        // If it's an Admin status (e.g., command failed on the drive), MI
        // status is 0.
        miStatus = 0;
        adminStatus = nvme_status_get_value(nvmeStatus);
    }

    // Returns the standardized tuple for the D-Bus client
    return {miStatus, adminStatus, completionDw0, failureScope, failureId};
}

void NVMeControllerEnabled::attachVolume(
    boost::asio::yield_context yield,
    const sdbusplus::message::object_path& volumePath)
{
    if (status != Status::Enabled)
    {
        lg2::error("Controller has been disabled");
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    uint32_t nsid = 0;
    if (auto s = subsys.lock())
    {
        auto vol = s->getVolume(volumePath);
        if (!vol)
        {
            throw sdbusplus::exception::SdBusError(ENOENT, "attachVolume");
        }
        nsid = vol->namespaceId();
    }
    else
    {
        return;
    }

    using callback_t = void(std::tuple<std::error_code, int>);
    uint16_t ctrlid = getCntrlId();
    auto [err, nvmeStatus] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, ctrlid, nsid](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminAttachDetachNamespace(
            ctrl, ctrlid, nsid, true,
            [h](const std::error_code& err, int nvmeStatus) mutable {
            h(std::make_tuple(err, nvmeStatus));
        });
    }, yield);

    // exception must be thrown outside of the async block
    checkLibNVMeError(err, nvmeStatus, "attachVolume");

    if (status == Status::Enabled)
    {
        if (auto s = subsys.lock())
        {
            try
            {
                s->attachCtrlVolume(getCntrlId(), nsid);
            }
            catch (const std::exception& e)
            {
                lg2::error("{ERROR}", "ERROR", e.what());
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InternalFailure();
            }
        }
        updateAssociation();
    }
}

void NVMeControllerEnabled::detachVolume(
    boost::asio::yield_context yield,
    const sdbusplus::message::object_path& volumePath)
{
    if (status != Status::Enabled)
    {
        lg2::error("Controller has been disabled");
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    uint32_t nsid = 0;
    if (auto s = subsys.lock())
    {
        auto vol = s->getVolume(volumePath);
        if (!vol)
        {
            throw sdbusplus::exception::SdBusError(ENOENT, "detachVolume");
        }
        nsid = vol->namespaceId();
    }
    else
    {
        return;
    }

    using callback_t = void(std::tuple<std::error_code, int>);
    uint16_t ctrlid = getCntrlId();
    auto [err, nvmeStatus] =
        boost::asio::async_initiate<boost::asio::yield_context, callback_t>(
            [intf{nvmeIntf}, ctrl{nvmeCtrl}, ctrlid, nsid](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        intf->adminAttachDetachNamespace(
            ctrl, ctrlid, nsid, false,
            [h](const std::error_code& err, int nvmeStatus) mutable {
            h(std::make_tuple(err, nvmeStatus));
        });
    }, yield);

    // exception must be thrown outside of the async block
    checkLibNVMeError(err, nvmeStatus, "detachVolume");

    if (status == Status::Enabled)
    {
        if (auto s = subsys.lock())
        {
            try
            {
                s->detachCtrlVolume(getCntrlId(), nsid);
            }
            catch (const std::exception& e)
            {
                lg2::error("{ERROR}", "ERROR", e.what());
                throw sdbusplus::xyz::openbmc_project::Common::Error::
                    InternalFailure();
            }
        }
        updateAssociation();
    }
}
