#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;

constexpr uint32_t kMinNvmeVerLogLid00hSupport = 0x020000;
constexpr int kDiscoverLogsMaxRetries =
    6; // exponentially backoff ~6.3s (100ms to 3.2s)
constexpr int kDiscoverLogsBaseBackoffMs = 100;

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;
    }

    lg2::info("NVMe version for controller {PATH}: {VERSION}", "PATH", path,
              "VERSION", lg2::hex, nvmeVersion);

    discoverSupportedLogPages();
}

void NVMeControllerEnabled::populateMetricStore()
{
    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>;
    using LockdownMetric =
        ControllerLogPageMetric<NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN,
                                SchedulerClockType>;

    auto defaultLogpageRefreshDuration =
        std::chrono::duration_cast<SchedulerClockType::duration>(
            std::chrono::seconds(60));

    auto identify = std::make_shared<IdentifyMetric>(
        shared_from_this(), scheduler,
        // Mitigate solution before Knuckle FW fix for b/404610159
        defaultLogpageRefreshDuration);

    std::list<std::shared_ptr<MetricBase<SchedulerClockType>>> metrics;
    metrics.push_back(identify);

    // Standard core metrics are statically supported across all NVMe versions
    metrics.push_back(std::make_shared<ErrorInfoMetric>(
        this->weak_from_this(), scheduler, defaultLogpageRefreshDuration));
    metrics.push_back(std::make_shared<SMARTMetric>(
        this->weak_from_this(), scheduler, defaultLogpageRefreshDuration));
    metrics.push_back(std::make_shared<FwSlotMetric>(
        this->weak_from_this(), scheduler, defaultLogpageRefreshDuration));
    metrics.push_back(std::make_shared<SelfTestMetric>(
        this->weak_from_this(), scheduler, defaultLogpageRefreshDuration));

    auto pluginName = findPluginName(config);
    if (!pluginName || pluginName != "OCP")
    {
        metrics.push_back(std::make_shared<HostTelemetryMetric>(
            this->weak_from_this(), scheduler,
            std::chrono::duration_cast<SchedulerClockType::duration>(
                std::chrono::seconds(900))));
    }

    // Command Lockdown (Log Page 14h) is dynamically registered only on
    // NVMe 2.0+ controllers that explicitly report support via Supported Log
    // Pages (00h) check.
    if (isLogPageSupported(NVME_LOG_LID_CMD_AND_FEAT_LOCKDOWN))
    {
        metrics.push_back(std::make_shared<LockdownMetric>(
            this->weak_from_this(), scheduler, defaultLogpageRefreshDuration));
    }

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

void NVMeControllerEnabled::discoverSupportedLogPages()
{
    if (nvmeVersion < kMinNvmeVerLogLid00hSupport)
    {
        populateMetricStore();
        return;
    }

    lg2::info(
        "Querying Supported Log Pages (00h) for NVMe 2.0+ controller: {PATH}",
        "PATH", path);

    discoverLogsToken = std::make_shared<bool>();
    std::weak_ptr<bool> weakToken = discoverLogsToken;

    fetchSupportedLogPages(0, weakToken);
}

void NVMeControllerEnabled::fetchSupportedLogPages(
    int retryCount, const std::weak_ptr<bool>& weakToken)
{
    std::weak_ptr<NVMeControllerEnabled> weakSelf = weak_from_this();

    nvmeIntf->adminGetLogPage(
        nvmeCtrl, NVME_LOG_LID_SUPPORTED_LOG_PAGES, NVME_NSID_NONE, 0, 0,
        [weakSelf, retryCount, weakToken](const std::error_code& ec,
                                          std::span<uint8_t> data) mutable {
        auto self = weakSelf.lock();
        if (!self || weakToken.expired())
        {
            lg2::info("Skipping fetchSupportedLogPages as token expired "
                      "or controller destroyed");
            return;
        }

        if (ec)
        {
            if (retryCount < kDiscoverLogsMaxRetries)
            {
                // Adaptive timer: exponential backoff
                int discoverLogsBackoffMs = kDiscoverLogsBaseBackoffMs
                                            << retryCount;
                self->discoverLogsRetryTimer =
                    std::make_shared<boost::asio::steady_timer>(self->io);
                self->discoverLogsRetryTimer->expires_after(
                    std::chrono::milliseconds(discoverLogsBackoffMs));
                self->discoverLogsRetryTimer->async_wait(
                    [weakSelf, retryCount,
                     weakToken](const boost::system::error_code& timerEc) {
                    auto self = weakSelf.lock();
                    if (!self || weakToken.expired() ||
                        timerEc == boost::asio::error::operation_aborted)
                    {
                        lg2::info("Skipping fetchSupportedLogPages as token "
                                  "expired or timer canceled or controller "
                                  "destroyed");
                        return; // Destructed or cancelled naturally!
                    }
                    self->fetchSupportedLogPages(retryCount + 1, weakToken);
                });
                return;
            }

            lg2::error(
                "{PATH}: Failed to get Supported Log Pages (00h): {ERROR}",
                "PATH", self->path, "ERROR", ec.message());
            self->supportedLogPages.clear();
            self->populateMetricStore();
            return;
        }

        if (data.size() < 1024)
        {
            lg2::error(
                "{PATH}: Undersized Supported Log Pages payload ({SIZE} bytes)",
                "PATH", self->path, "SIZE", data.size());
            self->supportedLogPages.clear();
            self->populateMetricStore();
            return;
        }

        self->supportedLogPages.assign(data.begin(), data.end());
        self->populateMetricStore();
    });
}

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

    status = Status::Enabled;

    if (isPrimary)
    {
        this->initializeMetricStore();
    }
}

void NVMeControllerEnabled::stop()
{
    status = Status::Disabled;

    // Resetting the discovery token here instantly revokes it, guaranteeing
    // that any stale async callbacks from fetchSupportedLogPages still pending
    // in the ASIO queue are invalidated upon execution.
    discoverLogsToken.reset();
    this->metricStore.reset();
    if (discoverLogsRetryTimer)
    {
        discoverLogsRetryTimer->cancel();
    }
}

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()
{
    if (discoverLogsRetryTimer)
    {
        discoverLogsRetryTimer->cancel();
    }
    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();
    }
}

void NVMeController::setNvmeVersion(uint32_t version)
{
    nvmeVersion = version;
}

bool NVMeController::isLogPageSupported(uint8_t lid) const
{
    if (nvmeVersion < kMinNvmeVerLogLid00hSupport)
    {
        return false;
    }

    if (lid == 0x00)
    {
        return true;
    }

    if (supportedLogPages.size() < 1024)
    {
        return false; // Under-sized payload or error condition
    }

    size_t byteOffset = static_cast<size_t>(lid) * 4;
    if (byteOffset >= supportedLogPages.size())
    {
        return false;
    }

    return (supportedLogPages[byteOffset] & 0x01) != 0;
}
