#include "NVMeSubsys.hpp"

#include "AsioHelper.hpp"
#include "NVMeCache.hpp"
#include "NVMeDrive.hpp"
#include "NVMeError.hpp"
#include "NVMePlugin.hpp"
#include "NVMeUtil.hpp"
#include "Thresholds.hpp"
#include "xyz/openbmc_project/Common/error.hpp"

#include <dlfcn.h>

#include <boost/asio/spawn.hpp>

#include <algorithm>
#include <charconv>
#include <filesystem>
#include <stdexcept>
#include <unordered_map>

using SchedulerClockType = std::chrono::steady_clock;
std::unordered_map<std::string, std::shared_ptr<Scheduler<SchedulerClockType>>>
    schedulers;

template <>
std::shared_ptr<Scheduler<SchedulerClockType>>
    Scheduler<SchedulerClockType>::getScheduler(const std::string& path)
{
    auto itr = std::find_if(
        schedulers.begin(), schedulers.end(),
        [&path](const std::pair<std::string,
                                std::shared_ptr<Scheduler<SchedulerClockType>>>&
                    pair) {
        // check if the given path is subdir of the subsystem path
        const std::string& parent = pair.first;
        if (parent.empty() || path.empty())
        {
            return false;
        }
        if (parent.size() > path.size())
        {
            return false;
        }
        if (!path.starts_with(parent))
        {
            return false;
        }
        if (parent.back() != '/' && path.size() > parent.size() &&
            path.at(parent.size()) != '/')
        {
            return false;
        }

        return true;
    });
    if (itr == schedulers.end())
    {
        return {};
    }
    return itr->second;
}

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

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

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

    associations.emplace_back("chassis", "storage", p.parent_path().string());
    associations.emplace_back("chassis", "drive", p.parent_path().string());
    associations.emplace_back("drive", "storage", path);

    for (const auto& [_, prog] : createProgress)
    {
        associations.emplace_back("awaiting", "awaited", prog->path);
    }

    for (const auto& [_, vol] : volumes)
    {
        associations.emplace_back("containing", "contained", vol->path);
    }

    return associations;
}

// get temporature from a NVMe Basic reading.
static double getTemperatureReading(int8_t reading)
{
    if (reading == static_cast<int8_t>(0x80) ||
        reading == static_cast<int8_t>(0x81))
    {
        // 0x80 = No temperature data or temperature data is more the 5 s
        // old 0x81 = Temperature sensor failure
        return std::numeric_limits<double>::quiet_NaN();
    }

    return reading;
}

std::shared_ptr<NVMeSubsystem> NVMeSubsystem::create(
    boost::asio::io_context& io, sdbusplus::asio::object_server& objServer,
    const std::shared_ptr<sdbusplus::asio::connection>& conn,
    const std::string& path, const std::string& name,
    const SensorData& configData, NVMeIntf intf)
{
    auto self = std::make_shared<NVMeSubsystem>(io, objServer, conn, path, name,
                                                configData, std::move(intf));
    self->init();
    return self;
}

NVMeSubsystem::NVMeSubsystem(
    boost::asio::io_context& io, sdbusplus::asio::object_server& objServer,
    const std::shared_ptr<sdbusplus::asio::connection>& conn,
    const std::string& path, const std::string& name,
    const SensorData& configData, NVMeIntf intf) :
    NVMeStorage(objServer, *dynamic_cast<sdbusplus::bus_t*>(conn.get()),
                path.c_str()),
    path(path), io(io), objServer(objServer), conn(conn), name(name),
    config(configData), nvmeIntf(std::move(intf)), status(Status::Stop)
{}

// Performs initialisation after shared_from_this() has been set up.
void NVMeSubsystem::init()
{
    NVMeIntf::Protocol protocol{NVMeIntf::Protocol::NVMeBasic};
    try
    {
        protocol = nvmeIntf.getProtocol();
    }
    catch (const std::runtime_error&)
    {
        throw std::runtime_error("NVMe interface is null");
    }

    // initiate the common interfaces (thermal sensor, Drive and Storage)
    if (protocol != NVMeIntf::Protocol::NVMeBasic &&
        protocol != NVMeIntf::Protocol::NVMeMI)
    {
        throw std::runtime_error("Unsupported NVMe interface");
    }

    /* xyz.openbmc_project.Inventory.Item.Storage */
    NVMeStorage::init(
        std::static_pointer_cast<NVMeStorage>(shared_from_this()));

    /* xyz.openbmc_project.Inventory.Item.Drive */
    drive = std::make_shared<NVMeDrive>(io, conn, path, weak_from_this());
    drive->protocol(NVMeDrive::DriveProtocol::NVMe);
    drive->type(NVMeDrive::DriveType::SSD);
    // TODO: update capacity

    // make association for Drive/Storage/Chassis
    createAssociation();
}

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

void NVMeSubsystem::processSecondaryControllerList(
    nvme_secondary_ctrl_list* secCntlrList)
{
    auto findPrimary = controllers.begin();
    int secCntlrCount = 0;
    if (secCntlrList != nullptr)
    {
        // all sc_entry pointing to a single pcid, so we only check
        // the first entry.
        findPrimary = controllers.find(secCntlrList->sc_entry[0].pcid);
        if (findPrimary == controllers.end())
        {
            std::cerr << "fail to match primary controller from "
                         "identify sencondary cntrl list"
                      << '\n';
            status = Status::Aborting;
            markFunctional(false);
            markAvailable(false);
            return;
        }
        secCntlrCount = secCntlrList->num;
    }

    // Enable primary controller since they are required to work
    auto& pc = findPrimary->second.first;
    primaryController = NVMeControllerEnabled::create(std::move(*pc));
    // replace with the new controller object
    pc = primaryController;

    std::vector<std::shared_ptr<NVMeController>> secCntrls;
    for (int i = 0; i < secCntlrCount; i++)
    {
        auto findSecondary = controllers.find(secCntlrList->sc_entry[i].scid);
        if (findSecondary == controllers.end())
        {
            std::cerr << "fail to match secondary controller from "
                         "identify sencondary cntrl list"
                      << '\n';
            break;
        }

        auto& secondaryController = findSecondary->second.first;

        // Check Secondary Controller State
        if (secCntlrList->sc_entry[i].scs != 0)
        {
            secondaryController =
                NVMeControllerEnabled::create(std::move(*secondaryController));
        }
        secondaryController->setSecondary();
        secCntrls.push_back(secondaryController);
    }
    primaryController->setPrimary(secCntrls);

    boost::asio::spawn(io, [self{shared_from_this()}](
                               const boost::asio::yield_context& yield) {
        try
        {
            self->fillDrive(yield);
            self->updateVolumes(yield);
            self->querySupportedFormats(yield);
            std::cerr << "finished NS enum" << '\n';
        }
        catch (const std::exception& e)
        {
            std::cerr << std::format("[{}] failed starting the subsystem: {}",
                                     self->name, e.what())
                      << '\n';
            self->status = Status::Aborting;
            self->markFunctional(false);
            self->markAvailable(false);
            return;
        }
        // start controller
        for (auto& [_, pair] : self->controllers)
        {
            // create controller plugin
            if (self->plugin)
            {
                pair.second = self->plugin->createControllerPlugin(
                    *pair.first, self->config);
            }
            pair.first->start(pair.second);
        }
        // start plugin
        if (self->plugin)
        {
            self->plugin->start();
        }

        // start Metric Scheduler
        auto scheduler =
            Scheduler<SchedulerClockType>::getScheduler(self->path);
        assert(
            scheduler &&
            "scheduler should be created at the beginning of Initializing Status");
        scheduler->start();
        scheduler->dequeue();

        self->status = Status::Start;
    });
}

void NVMeSubsystem::markFunctional(bool toggle)
{
    if (ctemp)
    {
        ctemp->markFunctional(toggle);
    }

    if (nvmeIntf.getProtocol() == NVMeIntf::Protocol::NVMeBasic)
    {
        return;
    }

    // disable the subsystem
    if (!toggle)
    {
        if (status == Status::Intiatilzing)
        {
            throw std::runtime_error(
                "cannot stop: the subsystem is intiatilzing");
        }

        if (status == Status::Terminating || status == Status::Stop)
        {
            return;
        }

        assert(status == Status::Start || status == Status::Aborting);

        status = Status::Terminating;

        // erase the scheduler to stop furthur Metric scheduling
        schedulers.erase(path);

        if (plugin)
        {
            plugin->stop();
        }
        // TODO: the controller should be stopped after controller level polling
        // is enabled

        // Tell any progress objects we're aborting the operation
        for (auto& [_, v] : createProgress)
        {
            v->abort();
        }

        // Tell the controllers they mustn't post further jobs
        if (primaryController)
        {
            primaryController->stop();
        }

        for (auto& [_, v] : controllers)
        {
            v.first->stop();
        }

        // Avoid triggering C*V D-Bus updates by clearing internal state
        // directly. The controller and volume objects and interfaces will be
        // removed which will update the mapper.
        attached.clear();
        volumes.clear();
        primaryController.reset();
        controllers.clear();
        // plugin.reset();

        updateAssociation();

        if (nvmeIntf.getProtocol() == NVMeIntf::Protocol::NVMeMI)
        {
            auto nvme =
                std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());

            bool posted =
                nvme->flushOperations([self{shared_from_this()}]() mutable {
                self->status = Status::Stop;
            });

            if (!posted)
            {
                std::cerr
                    << "Failed to flush operations, subsystem has stalled!"
                    << '\n';
            }
        }

        return;
    }

    if (status == Status::Intiatilzing)
    {
        throw std::runtime_error("cannot start: the subsystem is intiatilzing");
    }

    if (status == Status::Aborting)
    {
        throw std::runtime_error(
            "cannot start: subsystem initialisation has aborted and must transition to stopped");
    }

    if (status == Status::Start || status == Status::Terminating)
    {
        // Prevent consecutive calls to NVMeMiIntf::miScanCtrl()
        //
        // NVMeMiIntf::miScanCtrl() calls nvme_mi_scan_ep(..., true), which
        // forces a rescan and invalidates any nvme_mi_ctrl objects created on a
        // previous scan.
        //
        // We require a transition through Status::Stop (via
        // `markFunctional(false)`) so that the lifetime of the NVMeController
        // instances in this->controllers do not exceed the lifetime of their
        // associated nvme_mi_ctrl object.
        return;
    }

    assert(status == Status::Stop);

    status = Status::Intiatilzing;

    // create scheduler
    assert(schedulers.find(path) == schedulers.end() &&
           "scheduler should exsit only between [Intiatilzing, Terminating)");
    schedulers.emplace(path, new Scheduler<SchedulerClockType>(io));

    markAvailable(toggle);

    // add controllers for the subsystem
    if (nvmeIntf.getProtocol() == NVMeIntf::Protocol::NVMeMI)
    {
        auto nvme =
            std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());
        nvme->miScanCtrl(
            [self{shared_from_this()},
             nvme](const std::error_code& ec,
                   const std::vector<nvme_mi_ctrl_t>& ctrlList) mutable {
            if (ec || ctrlList.empty())
            {
                // TODO: mark the subsystem invalid and reschedule refresh
                std::cerr << "fail to scan controllers for the nvme subsystem"
                          << (ec ? ": " + ec.message() : "") << '\n';
                self->status = Status::Aborting;
                self->markFunctional(false);
                self->markAvailable(false);
                return;
            }

            // TODO: manually open nvme_mi_ctrl_t from cntrl id, instead hacking
            // into structure of nvme_mi_ctrl
            for (auto* c : ctrlList)
            {
                /* calucate the cntrl id from nvme_mi_ctrl:
                struct nvme_mi_ctrl
                {
                    struct nvme_mi_ep* ep;
                    __u16 id;
                    struct list_node ep_entry;
                };
                */
                // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                uint16_t* index = reinterpret_cast<uint16_t*>(
                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                    (reinterpret_cast<uint8_t*>(c) +
                     std::max(sizeof(uint16_t), sizeof(void*))));
                std::filesystem::path path = std::filesystem::path(self->path) /
                                             "controllers" /
                                             std::to_string(*index);

                try
                {
                    auto nvmeController = std::make_shared<NVMeController>(
                        self->io, self->objServer, self->conn, path.string(),
                        self->config, nvme, c, self->weak_from_this());

                    self->controllers.insert({*index, {nvmeController, {}}});
                }
                catch (const std::exception& e)
                {
                    std::cerr << "failed to create controller: "
                              << std::to_string(*index)
                              << ", reason: " << e.what() << '\n';
                }

                index++;
            }
            // self->createStorageAssociation();

            /* Begin of patch context
             *
             *
             *
             */
            /*
             *
             *
             * End of patch context
             */

            /*
            find primary controller and make association
            The controller is SR-IOV, meaning all controllers (within a
            subsystem) are pointing to a single primary controller. So we
            only need to do identify on an arbatary controller.
            If the controller list contains a single controller. Skip
            identifying the secondary controller list. It will be the primary
            controller.
            */
            if (ctrlList.size() == 1)
            {
                self->processSecondaryControllerList(nullptr);
                return;
            }
            auto* ctrl = ctrlList.back();
            nvme->adminIdentify(
                ctrl, nvme_identify_cns::NVME_IDENTIFY_CNS_SECONDARY_CTRL_LIST,
                0, 0,
                [self{self->shared_from_this()}](const nvme_ex_ptr& ex,
                                                 std::span<uint8_t> data) {
                if (ex || data.size() < sizeof(nvme_secondary_ctrl_list))
                {
                    std::cerr << "fail to identify secondary controller list"
                              << '\n';
                    self->status = Status::Aborting;
                    self->markFunctional(false);
                    self->markAvailable(false);
                    return;
                }
                nvme_secondary_ctrl_list* listHdr =
                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
                    reinterpret_cast<nvme_secondary_ctrl_list*>(data.data());

                if (listHdr->num == 0)
                {
                    std::cerr << "empty identify secondary controller list"
                              << '\n';
                    self->status = Status::Aborting;
                    self->markFunctional(false);
                    self->markAvailable(false);
                    return;
                }
                self->processSecondaryControllerList(listHdr);
            });
        });
    }
}

void NVMeSubsystem::markAvailable(bool toggle)
{
    if (ctemp)
    {
        ctemp->markAvailable(toggle);
    }

    if (nvmeIntf.getProtocol() == NVMeIntf::Protocol::NVMeBasic)
    {
        return;
    }

    if (toggle)
    {
        // TODO: make the Available interface true
        unavailableCount = 0;
        return;
    }
    // TODO: make the Available interface false
    unavailableCount = unavailableMaxCount;
}

std::shared_ptr<NVMeControllerEnabled>
    NVMeSubsystem::getPrimaryController() const
{
    if (!primaryController)
    {
        std::cerr << "dbus call for inactive NVMe subsystem " << name
                  << ". Returning Unavailable\n";
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }
    return primaryController;
}

/* Begin of patch context
 *
 *
 *
 */
/*
 *
 *
 * End of patch context
 */

void NVMeSubsystem::start()
{
    for (const auto& [_, lib] : pluginLibMap)
    {
        createplugin_t pluginFunc =
            // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
            reinterpret_cast<createplugin_t>(::dlsym(lib, "createPlugin"));
        auto p = pluginFunc(shared_from_this(), config);
        if (p)
        {
            plugin = p;
            break;
        }
    }
    // add thermal sensor for the subsystem
    std::optional<std::string> sensorName = createSensorNameFromPath(path);
    if (!sensorName)
    {
        // fail to parse sensor name from path, using name instead.
        sensorName.emplace(name);
    }

    std::vector<thresholds::Threshold> sensorThresholds;
    if (!parseThresholdsFromConfig(config, sensorThresholds))
    {
        std::cerr << "error populating thresholds for " << *sensorName << "\n";
        throw std::runtime_error("error populating thresholds for " +
                                 *sensorName);
    }

    if (ctemp || ctempTimer)
    {
        throw std::logic_error(
            "NVMeSubsystem::start() called from invalid state");
    }

    assert(!ctemp && !ctempTimer);

    PowerState powerState = PowerState::always;
    auto sensorBase = config.find(configInterfaceName(nvme::sensorType));
    if (sensorBase == config.end())
    {
        std::cerr << "Warning: " << name
                  << ": cannot find sensor config " +
                         configInterfaceName(nvme::sensorType)
                  << '\n';
    }
    else
    {
        const SensorBaseConfigMap& sensorConfig = sensorBase->second;
        powerState = getPowerState(sensorConfig);
    }

    /* Begin of patch context
     *
     *
     *
     */
    /*
     *
     *
     * End of patch context
     */

    ctemp = std::make_shared<NVMeSensor>(objServer, io, conn, *sensorName,
                                         std::move(sensorThresholds), path,
                                         powerState);
    ctempTimer = std::make_shared<boost::asio::steady_timer>(io);

    // start to poll value for CTEMP sensor.
    if (nvmeIntf.getProtocol() == NVMeIntf::Protocol::NVMeBasic)
    {
        auto intf =
            std::get<std::shared_ptr<NVMeBasicIntf>>(nvmeIntf.getInferface());
        ctemp_fetch_t<NVMeBasicIntf::DriveStatus*> dataFetcher =
            [intf, self{shared_from_this()},
             timer = std::weak_ptr<boost::asio::steady_timer>(ctempTimer)](
                std::function<void(const std::error_code&,
                                   NVMeBasicIntf::DriveStatus*)>&& cb) {
            /* Potentially defer sampling the sensor sensor if it is in error */
            if (!self->ctemp->sample())
            {
                cb(std::make_error_code(std::errc::operation_canceled),
                   nullptr);
                return;
            }

            intf->getStatus(std::move(cb));
        };
        ctemp_process_t<NVMeBasicIntf::DriveStatus*> dataProcessor =
            [self{shared_from_this()},
             timer = std::weak_ptr<boost::asio::steady_timer>(ctempTimer)](
                const std::error_code& error,
                NVMeBasicIntf::DriveStatus* status) {
            // deferred sampling
            if (error == std::errc::operation_canceled)
            {
                return;
            }
            // The device is physically absent
            if (error == std::errc::no_such_device)
            {
                std::cerr << "error reading ctemp from subsystem"
                          << ", reason:" << error.message() << "\n";
                self->markFunctional(false);
                self->markAvailable(false);
                return;
            }
            // other communication errors
            if (error)
            {
                std::cerr << "error reading ctemp from subsystem"
                          << ", reason:" << error.message() << "\n";
                self->ctemp->incrementError();
                return;
            }

            if (status == nullptr)
            {
                std::cerr << "empty data returned by data fetcher" << '\n';
                self->markFunctional(false);
                return;
            }

            uint8_t flags = status->Status;
            if (((flags & NVMeBasicIntf::StatusFlags::
                              NVME_MI_BASIC_SFLGS_DRIVE_NOT_READY) != 0) ||
                ((flags & NVMeBasicIntf::StatusFlags::
                              NVME_MI_BASIC_SFLGS_DRIVE_FUNCTIONAL) == 0))
            {
                std::cerr
                    << self->name
                    << ": health poll returns drive not ready or drive not functional"
                    << '\n';
                self->markFunctional(false);
                return;
            }
            self->ctemp->updateValue(
                getTemperatureReading(static_cast<int8_t>(status->Temp)));
        };

        pollCtemp(ctempTimer, pollingInterval, dataFetcher, dataProcessor);
    }
    else if (nvmeIntf.getProtocol() == NVMeIntf::Protocol::NVMeMI)
    {
        auto intf =
            std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());

        ctemp_fetch_t<nvme_mi_nvm_ss_health_status*> dataFetcher =
            [intf, self{shared_from_this()},
             timer = std::weak_ptr<boost::asio::steady_timer>(ctempTimer)](
                std::function<void(const std::error_code&,
                                   nvme_mi_nvm_ss_health_status*)>&& cb) {
            // do not poll the health status if subsystem is in cooldown
            if (self->unavailableCount > 0)
            {
                cb(std::make_error_code(std::errc::operation_canceled),
                   nullptr);
                return;
            }

            // do not poll the health status if the subsystem is intiatilzing
            if (self->status == Status::Intiatilzing)
            {
                std::cerr << "subsystem is intiatilzing, cancel the health poll"
                          << '\n';
                cb(std::make_error_code(std::errc::operation_canceled),
                   nullptr);
                return;
            }
            intf->miSubsystemHealthStatusPoll(std::move(cb));
        };
        ctemp_process_t<nvme_mi_nvm_ss_health_status*> dataProcessor =
            [self{shared_from_this()},
             timer = std::weak_ptr<boost::asio::steady_timer>(ctempTimer)](
                const std::error_code& error,
                nvme_mi_nvm_ss_health_status* status) {
            if (self->unavailableCount > 0)
            {
                self->unavailableCount--;
                return;
            }

            if (error == std::errc::operation_canceled)
            {
                std::cerr << "processing health data has been cancelled"
                          << '\n';
                return;
            }

            if (self->status == Status::Intiatilzing)
            {
                // on initialization, the subsystem will not update the status.
                std::cerr
                    << "subsystem is intiatilzing, do not process the status"
                    << '\n';
                return;
            }

            if (error == std::errc::no_such_device)
            {
                std::cerr << "error reading ctemp "
                             "from subsystem"
                          << ", reason:" << error.message() << "\n";
                // stop the subsystem
                self->markFunctional(false);
                self->markAvailable(false);

                return;
            }
            if (error)
            {
                std::cerr << "error reading ctemp "
                             "from subsystem"
                          << ", reason:" << error.message() << "\n";
                self->ctemp->incrementError();
                if (self->ctemp->inError())
                {
                    auto intf = std::get<std::shared_ptr<NVMeMiIntf>>(
                        self->nvmeIntf.getInferface());
                    intf->recover();
                    // stop the subsystem
                    self->markFunctional(false);
                    self->markAvailable(false);
                }
                return;
            }

            // Drive Functional
            bool df = (status->nss & 0x20) != 0;
            if (!df)
            {
                // stop the subsystem
                std::cerr << self->name << ": health poll returns df status 0"
                          << '\n';
                self->markFunctional(false);
                return;
            }

            self->markFunctional(true);

            // TODO: update the drive interface

            self->ctemp->updateValue(
                getTemperatureReading(static_cast<int8_t>(status->ctemp)));
            return;
        };

        pollCtemp(ctempTimer, pollingInterval, dataFetcher, dataProcessor);
    }
}

void NVMeSubsystem::stop()
{
    if (ctempTimer)
    {
        ctempTimer->cancel();
        ctempTimer.reset();
        ctemp.reset();
    }

    if (status == Status::Intiatilzing)
    {
        std::cerr << "status init" << '\n';
        auto timer = std::make_shared<boost::asio::steady_timer>(
            io, std::chrono::milliseconds(100));
        timer->async_wait(
            [self{shared_from_this()}, timer](boost::system::error_code ec) {
            if (ec)
            {
                return;
            }
            self->stop();
        });
    }
    else
    {
        std::cerr << "status else" << '\n';
        markFunctional(false);

        // There's been an explicit request to stop the subsystem. If it has
        // entered an unavailable state, reset that too. If the subsystem
        // continues to be unavailable beyond a subsequent invocation of start()
        // this will be detected in the usual fashion. Put another way: Don't
        // unnecessarily impede the progress of a subsequent start().
        unavailableCount = 0;
    }

    if (plugin)
    {
        plugin.reset();
    }
}

sdbusplus::message::object_path
    NVMeSubsystem::createVolume(boost::asio::yield_context yield, uint64_t size,
                                size_t lbaFormat, bool metadataAtEnd)
{
    if (status != Status::Start)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    // #0 (sequence of runtime/callbacks)
    auto progId = getRandomId();

    auto pc = getPrimaryController();
    nvme_mi_ctrl_t ctrl = pc->getMiCtrl();

    auto intf = std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());

    using submit_callback_t = void(std::tuple<nvme_ex_ptr>);
    auto [ex] = boost::asio::async_initiate<boost::asio::yield_context,
                                            submit_callback_t>(
        [weak{weak_from_this()}, progId, intf, ctrl, size, lbaFormat,
         metadataAtEnd](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));

        // #1
        intf->createNamespace(ctrl, size, lbaFormat, metadataAtEnd,

                              // submitted_cb
                              [h](const nvme_ex_ptr& ex) mutable {
            // #2

            // Async completion of the createNamespace call.
            // The actual nvme_mi_admin_ns_mgmt_create() call is still running
            // in a separate thread. Pass the error status back out.
            h(std::make_tuple(ex));
        },

                              // finished_cb
                              [weak, progId](const nvme_ex_ptr& ex,
                                             NVMeNSIdentify newns) mutable {
            // #5. This will only be called once #4 completes.
            // It will not be called if the submit failed.
            auto self = weak.lock();
            if (!self)
            {
                std::cerr << "createNamespace completed while nvmesensor was "
                             "exiting\n";
                return;
            }
            // The NS create has completed (either successfully or not)
            self->createVolumeFinished(progId, ex, newns);
        });
    },
        yield);

    // #3

    // Exception must be thrown outside of the async block
    if (ex)
    {
        // TODO: (b/375054188) Exception handling to be refactored
        // NOLINTNEXTLINE(cert-err09-cpp,cert-err60-cpp,cert-err61-cpp,misc-throw-by-value-catch-by-reference)
        throw *ex;
    }

    // Progress endpoint for clients to poll, if the submit was successful.
    std::string progPath = path + "/CreateProgress/" + progId;

    auto prog = std::make_shared<NVMeCreateVolumeProgress>(conn, progPath);
    if (!createProgress.insert({progId, prog}).second)
    {
        throw std::logic_error("duplicate progress id");
    }

    updateAssociation();

    // #4
    return progPath;
}

void NVMeSubsystem::createVolumeFinished(const std::string& progId,
                                         const nvme_ex_ptr& ex,
                                         NVMeNSIdentify ns)
{
    try
    {
        auto p = createProgress.find(progId);
        if (p == createProgress.end())
        {
            throw std::logic_error("Missing progress entry");
        }
        auto prog = p->second;

        if (prog->status() == OperationStatus::Aborted)
        {
            return;
        }
        assert(status == Status::Start);

        if (ex)
        {
            prog->createFailure(ex);
            return;
        }

        std::shared_ptr<NVMeVolume> vol;
        try
        {
            vol = addVolume(ns);
        }
        // TODO: (b/375054188) Exception handling to be refactored
        // NOLINTNEXTLINE(cert-err09-cpp,cert-err60-cpp,cert-err61-cpp,misc-throw-by-value-catch-by-reference)
        catch (nvme_ex_ptr e)
        {
            prog->createFailure(e);
            return;
        }

        prog->createSuccess(vol);
        updateAssociation();
    }
    catch (const std::exception& e)
    {
        std::cerr << "Unhandled error in createVolumeFinished: " << e.what()
                  << "\n";
    }
}

std::string NVMeSubsystem::volumePath(uint32_t nsid) const
{
    return path + "/volumes/" + std::to_string(nsid);
}

void NVMeSubsystem::addIdentifyNamespace(boost::asio::yield_context yield,
                                         uint32_t nsid)
{
    assert((status == Status::Start || status == Status::Intiatilzing) &&
           std::format("Subsystem not in Start state, have {}",
                       static_cast<int>(status))
               .c_str());

    auto pc = getPrimaryController();
    nvme_mi_ctrl_t ctrl = getPrimaryController()->getMiCtrl();

    auto intf = std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());

    using admin_identify_t = void(std::tuple<nvme_ex_ptr, std::span<uint8_t>>);

    auto [ex, data] = boost::asio::async_initiate<boost::asio::yield_context,
                                                  admin_identify_t>(
        [intf, ctrl, nsid](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));
        intf->adminIdentify(
            ctrl, nvme_identify_cns::NVME_IDENTIFY_CNS_ALLOCATED_NS, nsid,
            NVME_CNTLID_NONE,
            [h](const nvme_ex_ptr& ex, std::span<uint8_t> data) mutable {
            h(std::make_tuple(ex, data));
        });
    }, yield);

    if (ex)
    {
        // TODO: (b/375054188) Exception handling to be refactored
        // NOLINTNEXTLINE(cert-err09-cpp,cert-err60-cpp,cert-err61-cpp,misc-throw-by-value-catch-by-reference)
        throw *ex;
    }

    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    nvme_id_ns& id = *reinterpret_cast<nvme_id_ns*>(data.data());

    // msb 6:5 and lsb 3:0
    size_t lbafIndex = ((id.flbas >> 1) & 0x30) | (id.flbas & 0x0f);
    size_t blockSize = 1UL << id.lbaf[lbafIndex].ds;
    bool metadataAtEnd = (id.flbas & (1 << 4)) != 0;

    NVMeNSIdentify ns = {
        .namespaceId = nsid,
        .size = ::le64toh(id.nsze * blockSize),
        .capacity = ::le64toh(id.ncap * blockSize),
        .blockSize = blockSize,
        .lbaFormat = lbafIndex,
        .metadataAtEnd = metadataAtEnd,
    };

    addVolume(ns);

    // determine attached controllers
    std::tie(ex, data) = boost::asio::async_initiate<boost::asio::yield_context,
                                                     admin_identify_t>(
        [intf, ctrl, nsid](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));
        intf->adminIdentify(
            ctrl, nvme_identify_cns::NVME_IDENTIFY_CNS_NS_CTRL_LIST, nsid,
            NVME_CNTLID_NONE,
            [h](const nvme_ex_ptr& ex, std::span<uint8_t> data) mutable {
            h(std::make_tuple(ex, data));
        });
    }, yield);

    if (ex)
    {
        // TODO: (b/375054188) Exception handling to be refactored
        // NOLINTNEXTLINE(cert-err09-cpp,cert-err60-cpp,cert-err61-cpp,misc-throw-by-value-catch-by-reference)
        throw *ex;
    }

    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    nvme_ctrl_list& list = *reinterpret_cast<nvme_ctrl_list*>(data.data());
    uint16_t num = ::le16toh(list.num);
    if (num == NVME_ID_CTRL_LIST_MAX)
    {
        std::cerr << "Warning: full ctrl list returned\n";
    }

    for (auto i = 0; i < num; i++)
    {
        uint16_t c = ::le16toh(list.identifier[i]);
        attachCtrlVolume(c, nsid);
    }
}

void NVMeSubsystem::updateVolumes(boost::asio::yield_context yield)
{
    assert((status == Status::Start || status == Status::Intiatilzing) &&
           std::format("Subsystem not in Start state, have {}",
                       static_cast<int>(status))
               .c_str());

    auto pc = getPrimaryController();
    nvme_mi_ctrl_t ctrl = getPrimaryController()->getMiCtrl();

    auto intf = std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());
    using admin_list_ns_t =
        void(std::tuple<nvme_ex_ptr, std::vector<uint32_t>>);
    auto [ex, ns] = boost::asio::async_initiate<boost::asio::yield_context,
                                                admin_list_ns_t>(
        [intf, ctrl](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));
        intf->adminListNamespaces(ctrl,
                                  [h](const nvme_ex_ptr& ex,
                                      const std::vector<uint32_t>& ns) mutable {
            h(std::make_tuple(ex, ns));
        });
    }, yield);

    if (ex)
    {
        // TODO: (b/375054188) Exception handling to be refactored
        // NOLINTNEXTLINE(cert-err09-cpp,cert-err60-cpp,cert-err61-cpp,misc-throw-by-value-catch-by-reference)
        throw *ex;
    }

    std::vector<uint32_t> existing;
    existing.reserve(volumes.size());
    for (auto& [n, _] : volumes)
    {
        existing.push_back(n);
    }

    std::vector<uint32_t> additions;
    std::vector<uint32_t> deletions;

    // namespace lists are ordered
    std::set_difference(ns.begin(), ns.end(), existing.begin(), existing.end(),
                        std::back_inserter(additions));

    std::set_difference(existing.begin(), existing.end(), ns.begin(), ns.end(),
                        std::back_inserter(deletions));

    std::cerr << std::format(
        "[{}] subsystem enum {} NS, {} will be added, {} will be deleted\n",
        name, ns.size(), additions.size(), deletions.size());

    for (auto n : deletions)
    {
        forgetVolume(volumes.find(n)->second);
    }

    for (auto n : additions)
    {
        addIdentifyNamespace(yield, n);
    }
}

void NVMeSubsystem::fillDrive(boost::asio::yield_context yield)
{
    assert(status == Status::Intiatilzing);
    auto pc = getPrimaryController();
    nvme_mi_ctrl_t ctrl = pc->getMiCtrl();

    auto intf = std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());

    using admin_identify_t = void(std::tuple<nvme_ex_ptr, std::span<uint8_t>>);

    auto [ex, data] = boost::asio::async_initiate<boost::asio::yield_context,
                                                  admin_identify_t>(
        [intf, ctrl](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));
        intf->adminIdentify(
            ctrl, nvme_identify_cns::NVME_IDENTIFY_CNS_CTRL, NVME_NSID_NONE,
            NVME_CNTLID_NONE,
            [h](const nvme_ex_ptr& ex, std::span<uint8_t> data) mutable {
            h(std::make_tuple(ex, data));
        });
    }, yield);

    if (ex)
    {
        throw std::runtime_error(
            std::format("{}: Error for controller identify", name));
    }

    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    nvme_id_ctrl& id = *reinterpret_cast<nvme_id_ctrl*>(data.data());
    drive->serialNumber(nvmeString((const char*)id.sn, sizeof(id.sn)));
    drive->model(nvmeString((const char*)id.mn, sizeof(id.mn)));
    drive->capacity(char128ToUint64((const unsigned char*)id.tnvmcap));

    auto fwVer = nvmeString((const char*)id.fr, sizeof(id.fr));
    if (!fwVer.empty())
    {
        // Formatting per
        // https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/43458/2/xyz/openbmc_project/Software/Version.interface.yaml#47
        // TODO find/write a better reference
        std::string v("xyz.openbmc_project.NVMe.ControllerFirmwareVersion");
        auto pc = getPrimaryController();
        pc->version(v);
        pc->purpose(SoftwareVersion::VersionPurpose::Other);
        pc->extendedVersion(v + ":" + fwVer);
    }
}

std::shared_ptr<NVMeVolume> NVMeSubsystem::getVolume(
    const sdbusplus::message::object_path& volPath) const
{
    if (volPath.parent_path() != path + "/volumes")
    {
        std::cerr << "getVolume path '" << volPath.str
                  << "' doesn't match parent " << path << "\n";
        return nullptr;
    }

    std::string id = volPath.filename();
    uint32_t nsid = 0;
    auto e = std::from_chars(id.data(), id.data() + id.size(), nsid);
    if (e.ptr != id.data() + id.size() || e.ec != std::errc())
    {
        std::cerr << "getVolume path '" << volPath.str << "' bad nsid\n";
        return nullptr;
    }

    auto v = volumes.find(nsid);
    if (v == volumes.end())
    {
        std::cerr << "getVolume nsid " << nsid << " not found\n";
        return nullptr;
    }

    return v->second;
}

std::vector<uint32_t> NVMeSubsystem::attachedVolumes(uint16_t ctrlId) const
{
    std::vector<uint32_t> vols;

    if (!controllers.contains(ctrlId))
    {
        std::cerr << "attachedVolumes bad controller " << ctrlId << '\n';
        return vols;
    }

    try
    {
        std::ranges::copy(attached.at(ctrlId), std::back_inserter(vols));
    }
    catch (std::out_of_range&)
    {
        // no volumes attached
    }
    return vols;
}

void NVMeSubsystem::attachCtrlVolume(uint16_t c, uint32_t ns)
{
    assert((status == Status::Start || status == Status::Intiatilzing) &&
           std::format("Subsystem not in Start state, have {}",
                       static_cast<int>(status))
               .c_str());

    if (!controllers.contains(c))
    {
        throw std::runtime_error(
            std::format("attachCtrlVolume bad controller {}", c));
    }
    if (!volumes.contains(ns))
    {
        throw std::runtime_error(std::format("attachCtrlVolume bad ns {}", ns));
    }
    attached[c].insert(ns);
    std::cout << name << " attached insert " << c << " " << ns << "\n";
    controllers[c].first->updateAssociation();
}

void NVMeSubsystem::detachCtrlVolume(uint16_t c, uint32_t ns)
{
    assert(status == Status::Start &&
           std::format("Subsystem is not in Start state: {}",
                       static_cast<int>(status))
               .c_str());

    if (!controllers.contains(c))
    {
        throw std::runtime_error(
            std::format("detachCtrlVolume bad controller {}", c));
    }
    if (!volumes.contains(ns))
    {
        throw std::runtime_error(std::format("detachCtrlVolume bad ns {}", ns));
    }
    attached[c].erase(ns);
    std::cout << name << " attached erase " << c << " " << ns << "\n";
    controllers[c].first->updateAssociation();
}

void NVMeSubsystem::detachAllCtrlVolume(uint32_t ns)
{
    assert(status == Status::Start &&
           std::format("Subsystem is not in Start state: {}",
                       static_cast<int>(status))
               .c_str());

    if (!volumes.contains(ns))
    {
        throw std::runtime_error(std::format("detachCtrlVolume bad ns {}", ns));
    }
    // remove from attached controllers list
    for (auto& [c, attach_vols] : attached)
    {
        if (attach_vols.erase(ns) == 1)
        {
            controllers[c].first->updateAssociation();
        }
    }
}

// Will throw a nvme_ex_ptr if the NS already exists */
std::shared_ptr<NVMeVolume> NVMeSubsystem::addVolume(const NVMeNSIdentify& ns)
{
    assert((status == Status::Start || status == Status::Intiatilzing) &&
           std::format("Subsystem not in Start state, have {}",
                       static_cast<int>(status))
               .c_str());

    if (volumes.contains(ns.namespaceId))
    {
        std::string errMsg = std::string("Internal error, NSID exists " +
                                         std::to_string(ns.namespaceId));
        std::cerr << errMsg << "\n";
        throw makeLibNVMeError(errMsg);
    }

    auto vol = NVMeVolume::create(objServer, conn, shared_from_this(), ns);
    volumes.insert({ns.namespaceId, vol});

    updateAssociation();
    return vol;
}

void NVMeSubsystem::forgetVolume(const std::shared_ptr<NVMeVolume>& volume)
{
    // remove any progress references
    for (const auto& [progId, prog] : createProgress)
    {
        std::string s = prog->volumePath();
        if (prog->volumePath() == volume->path)
        {
            createProgress.erase(progId);
            break;
        }
    }

    // remove from attached controllers list
    detachAllCtrlVolume(volume->namespaceId());

    if (volumes.erase(volume->namespaceId()) != 1)
    {
        throw std::runtime_error(std::format(
            "volume {} disappeared unexpectedly", volume->namespaceId()));
    }

    updateAssociation();
}

void NVMeSubsystem::querySupportedFormats(boost::asio::yield_context yield)
{
    assert((status == Status::Start || status == Status::Intiatilzing) &&
           std::format("Subsystem not in Start state, have {}",
                       static_cast<int>(status))
               .c_str());

    auto pc = getPrimaryController();
    nvme_mi_ctrl_t ctrl = pc->getMiCtrl();

    auto intf = std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());

    using admin_identify_t = void(std::tuple<nvme_ex_ptr, std::span<uint8_t>>);
    auto [ex, data] = boost::asio::async_initiate<boost::asio::yield_context,
                                                  admin_identify_t>(
        [intf, ctrl](auto&& handler) {
        auto h = asio_helper::CopyableCallback(
            std::forward<decltype(handler)>(handler));
        intf->adminIdentify(
            ctrl, nvme_identify_cns::NVME_IDENTIFY_CNS_NS, NVME_NSID_ALL,
            NVME_CNTLID_NONE,
            [h](const nvme_ex_ptr& ex, std::span<uint8_t> data) mutable {
            h(std::make_tuple(ex, data));
        });
    }, yield);

    if (ex)
    {
        throw std::runtime_error(
            std::format("{}: Error getting LBA formats :{}", name, ex->what()));
    }

    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
    nvme_id_ns& id = *reinterpret_cast<nvme_id_ns*>(data.data());

    // nlbaf is 0’s based
    size_t nlbaf = id.nlbaf + 1;
    if (nlbaf > 64)
    {
        throw std::runtime_error(std::format("{}: Bad nlbaf {}", name, nlbaf));
    }

    std::cerr << name << ": Got nlbaf " << nlbaf << "\n";
    std::vector<LBAFormat> formats;
    for (size_t i = 0; i < nlbaf; i++)
    {
        size_t blockSize = 1UL << id.lbaf[i].ds;
        size_t metadataSize = id.lbaf[i].ms;
        RelPerf rp = relativePerformanceFromRP(id.lbaf[i].rp);
        std::cerr << name << ": lbaf " << i << " blocksize " << blockSize
                  << "\n";
        formats.push_back({.index = i,
                           .blockSize = blockSize,
                           .metadataSize = metadataSize,
                           .relativePerformance = rp});
    }
    setSupportedFormats(formats);
}

void NVMeSubsystem::deleteVolume(boost::asio::yield_context yield,
                                 const std::shared_ptr<NVMeVolume>& volume)
{
    if (status != Status::Start)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    auto pc = getPrimaryController();
    nvme_mi_ctrl_t ctrl = pc->getMiCtrl();

    auto intf = std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());

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

        intf->adminDeleteNamespace(
            ctrl, nsid,
            [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, "Delete");

    forgetVolume(volume);
}

// submitCb is called once the sanitize has been submitted
void NVMeSubsystem::startSanitize(
    const NVMeSanitizeParams& params,
    std::function<void(nvme_ex_ptr ex)>&& submitCb)
{
    if (status != Status::Start)
    {
        throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
    }

    auto pc = getPrimaryController();
    nvme_mi_ctrl_t ctrl = pc->getMiCtrl();

    auto intf = std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());

    intf->adminSanitize(
        ctrl, params.nvmeAction(), params.passes, params.pattern,
        params.patternInvert,
        [submitCb](nvme_ex_ptr ex) { submitCb(std::move(ex)); });
}

void NVMeSubsystem::sanitizeStatus(
    std::function<void(nvme_ex_ptr ex, bool inProgress, bool failed,
                       bool completed, uint16_t sstat, uint16_t sprog,
                       uint32_t scdw10)>&& cb)
{
    if (status != Status::Start)
    {
        std::cerr << "Subsystem not in Start state, have "
                  << static_cast<int>(status) << '\n';
        return;
    }

    auto pc = getPrimaryController();
    nvme_mi_ctrl_t ctrl = pc->getMiCtrl();

    auto intf = std::get<std::shared_ptr<NVMeMiIntf>>(nvmeIntf.getInferface());

    intf->adminGetLogPage(
        ctrl, NVME_LOG_LID_SANITIZE, NVME_NSID_NONE, 0, 0,
        [self{shared_from_this()}, cb](const std::error_code& ec,
                                       std::span<uint8_t> data) {
        if (ec)
        {
            std::string msg = "GetLogPage failed: " + ec.message();
            auto ex = makeLibNVMeError(msg);
            cb(ex, false, false, false, 0, 0, 0);
            return;
        }

        nvme_sanitize_log_page* log =
            // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
            reinterpret_cast<nvme_sanitize_log_page*>(data.data());
        uint8_t sanStatus = log->sstat & NVME_SANITIZE_SSTAT_STATUS_MASK;
        cb(nvme_ex_ptr(), sanStatus == NVME_SANITIZE_SSTAT_STATUS_IN_PROGESS,
           sanStatus == NVME_SANITIZE_SSTAT_STATUS_COMPLETED_FAILED,
           sanStatus == NVME_SANITIZE_SSTAT_STATUS_COMPLETE_SUCCESS, log->sstat,
           log->sprog, log->scdw10);
    });
}
