/*
 * SPDX-FileCopyrightText: Copyright OpenBMC Authors
 * SPDX-License-Identifier: Apache-2.0
 */

#include "NvidiaGpuClockSpeedControl.hpp"

#include "Inventory.hpp"
#include "NvidiaGpuControlErrors.hpp"
#include "NvidiaUtils.hpp"
#include "Utils.hpp"

#include <MctpRequester.hpp>
#include <NvidiaGpuMctpVdm.hpp>
#include <OcpMctpVdm.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/io_context.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/message/native_types.hpp>

#include <chrono>
#include <cstdint>
#include <functional>
#include <limits>
#include <memory>
#include <optional>
#include <span>
#include <string>
#include <system_error>
#include <utility>
#include <vector>

static constexpr const char* controlClockSpeedIfaceName =
    "xyz.openbmc_project.Control.OperatingClockSpeed";
static constexpr const char* controlClockSpeedPrefix =
    "/xyz/openbmc_project/control/operatingclockspeed/";

static constexpr uint64_t mhzToHzFactor = 1'000'000;

// Debounce window to coalesce the RequestedSpeedLimitMin and Max writes of a
// single PATCH (which arrive back to back) into one SetClockLimit.
static constexpr std::chrono::milliseconds setLimitDebounce{100};

NvidiaGpuClockSpeedControl::NvidiaGpuClockSpeedControl(
    sdbusplus::asio::object_server& objectServer, const std::string& deviceName,
    mctp::MctpRequester& mctpRequester, uint8_t eid,
    boost::asio::io_context& io, std::shared_ptr<Inventory> inventory) :
    inventory(std::move(inventory)), mctpRequester(mctpRequester),
    name(escapeName(deviceName)), objectServer(objectServer), setLimitTimer(io),
    eid(eid)
{
    const int rc = gpu::encodeGetClockLimitRequest(
        0, gpu::ClockType::GRAPHICS_CLOCK, requestBuffer);
    if (rc == 0)
    {
        requestEncoded = true;
    }
    else
    {
        lg2::error("Failed to encode clock limit request for {NAME}: rc={RC}",
                   "NAME", name, "RC", rc);
    }

    const sdbusplus::object_path inventoryPath = inventoryPrefix / name;
    const sdbusplus::object_path objPath(controlClockSpeedPrefix + name);

    controlClockSpeedInterface =
        objectServer.add_interface(objPath.str, controlClockSpeedIfaceName);

    associationInterface =
        objectServer.add_interface(objPath, association::interface);
    std::vector<Association> associations;
    associations.emplace_back("controlling", "controlled_by", inventoryPath);
    associationInterface->register_property("Associations", associations);
    if (!associationInterface->initialize())
    {
        lg2::error(
            "Error initializing Association interface for Clock Speed Control for {NAME}, eid={EID}",
            "NAME", name, "EID", eid);
    }

    controlClockSpeedInterface->register_property(
        "PresentSpeedLimitMaxHz", std::numeric_limits<uint64_t>::max(),
        sdbusplus::asio::PropertyPermission::readOnly);
    controlClockSpeedInterface->register_property(
        "PresentSpeedLimitMinHz", uint64_t{0},
        sdbusplus::asio::PropertyPermission::readOnly);

    controlClockSpeedInterface->register_property<uint64_t>(
        "RequestedSpeedLimitMaxHz", std::numeric_limits<uint64_t>::max(),
        std::bind_front(
            &NvidiaGpuClockSpeedControl::handleRequestedSpeedLimitMaxHzSet,
            this),
        [this](uint64_t&) { return requestedMaxHz; });
    controlClockSpeedInterface->register_property<uint64_t>(
        "RequestedSpeedLimitMinHz", std::numeric_limits<uint64_t>::max(),
        std::bind_front(
            &NvidiaGpuClockSpeedControl::handleRequestedSpeedLimitMinHzSet,
            this),
        [this](uint64_t&) { return requestedMinHz; });

    if (!controlClockSpeedInterface->initialize())
    {
        lg2::error(
            "Error initializing OperatingClockSpeed interface for {NAME}, eid={EID}",
            "NAME", name, "EID", eid);
    }
}

NvidiaGpuClockSpeedControl::~NvidiaGpuClockSpeedControl()
{
    objectServer.remove_interface(associationInterface);
    objectServer.remove_interface(controlClockSpeedInterface);
}

void NvidiaGpuClockSpeedControl::update()
{
    sendGetClockLimitRequest();
}

void NvidiaGpuClockSpeedControl::sendGetClockLimitRequest()
{
    if (!requestEncoded)
    {
        return;
    }

    mctpRequester.sendRecvMsg(
        eid, requestBuffer,
        [weak{weak_from_this()}](const std::error_code& ec,
                                 std::span<const uint8_t> buffer) {
            auto self = weak.lock();
            if (!self)
            {
                lg2::error("Invalid NvidiaGpuClockSpeedControl reference");
                return;
            }
            self->handleGetClockLimitResponse(ec, buffer);
        });
}

void NvidiaGpuClockSpeedControl::handleGetClockLimitResponse(
    const std::error_code& ec, std::span<const uint8_t> buffer)
{
    if (setClockLimitReadbackPending)
    {
        // This response is the read-back for a completed SetClockLimit: the
        // device's new state has now been observed, so open the coalesce gate.
        // Done before the error returns below so a failed read-back cannot
        // wedge the gate shut forever. Any writes that arrived while the set
        // was in flight have re-armed setLimitTimer and dispatch on its next
        // expiry, so no manual re-dispatch is needed here.
        setClockLimitReadbackPending = false;
        setClockLimitInflight = false;
    }

    if (ec)
    {
        lg2::error("Error reading clock limit for {NAME}: MCTP failed, rc={RC}",
                   "NAME", name, "RC", ec.message());
        return;
    }

    ocp::accelerator_management::CompletionCode cc{};
    uint16_t reasonCode = 0;
    uint32_t requestedLimitMin = 0;
    uint32_t requestedLimitMax = 0;
    uint32_t presentLimitMin = 0;
    uint32_t presentLimitMax = 0;

    int rc = gpu::decodeGetClockLimitResponse(
        buffer, cc, reasonCode, requestedLimitMin, requestedLimitMax,
        presentLimitMin, presentLimitMax);

    if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS)
    {
        lg2::error(
            "Error decoding clock limit for {NAME}: rc={RC}, cc={CC}, reasonCode={REASON}",
            "NAME", name, "RC", rc, "CC", static_cast<uint8_t>(cc), "REASON",
            reasonCode);
        return;
    }

    const uint64_t newPresentMaxHz =
        static_cast<uint64_t>(presentLimitMax) * mhzToHzFactor;
    const uint64_t newPresentMinHz =
        static_cast<uint64_t>(presentLimitMin) * mhzToHzFactor;
    const uint64_t newRequestedMaxHz =
        static_cast<uint64_t>(requestedLimitMax) * mhzToHzFactor;
    const uint64_t newRequestedMinHz =
        static_cast<uint64_t>(requestedLimitMin) * mhzToHzFactor;

    // PresentSpeedLimit*Hz are read-only, so set_property updates the stored
    // value and emits PropertiesChanged only when it actually changes.
    // RequestedSpeedLimit*Hz are client-writable; updating them via
    // set_property would re-enter the client set-handler, so the member is the
    // source of truth and the change signal is emitted directly.
    controlClockSpeedInterface->set_property("PresentSpeedLimitMaxHz",
                                             newPresentMaxHz);
    controlClockSpeedInterface->set_property("PresentSpeedLimitMinHz",
                                             newPresentMinHz);
    if (newRequestedMaxHz != requestedMaxHz)
    {
        requestedMaxHz = newRequestedMaxHz;
        controlClockSpeedInterface->signal_property("RequestedSpeedLimitMaxHz");
    }
    if (newRequestedMinHz != requestedMinHz)
    {
        requestedMinHz = newRequestedMinHz;
        controlClockSpeedInterface->signal_property("RequestedSpeedLimitMinHz");
    }
}

int NvidiaGpuClockSpeedControl::handleRequestedSpeedLimitMaxHzSet(
    const uint64_t& newMaxHz, uint64_t& /*current*/)
{
    if (!inventory)
    {
        lg2::error(
            "RequestedSpeedLimitMaxHz set rejected for eid {EID}: inventory not available",
            "EID", eid);
        throw Unavailable();
    }

    std::optional<uint64_t> minHw = inventory->getMinSpeedInHz();
    std::optional<uint64_t> maxHw = inventory->getMaxSpeedInHz();
    if (!minHw || !maxHw)
    {
        lg2::error(
            "RequestedSpeedLimitMaxHz set rejected for eid {EID}: hardware min/max not yet known",
            "EID", eid);
        throw Unavailable();
    }

    if (newMaxHz < *minHw || newMaxHz > *maxHw)
    {
        lg2::error(
            "RequestedSpeedLimitMaxHz set rejected for eid {EID}: value {VAL} out of range [{MIN}, {MAX}]",
            "EID", eid, "VAL", newMaxHz, "MIN", *minHw, "MAX", *maxHw);
        throw InvalidArgument();
    }

    // Record the requested max and arm the debounce timer. The actual
    // SetClockLimit is issued once the burst settles, so a PATCH that sets
    // both RequestedSpeedLimitMin and Max is coalesced into a single request.
    // Do not touch requestedMaxHz here: the D-Bus value is only updated once
    // the device confirms via a GetClockLimit response.
    pendingMaxHz = newMaxHz;
    armSetLimitTimer();

    return 1;
}

int NvidiaGpuClockSpeedControl::handleRequestedSpeedLimitMinHzSet(
    const uint64_t& newMinHz, uint64_t& /*current*/)
{
    if (!inventory)
    {
        lg2::error(
            "RequestedSpeedLimitMinHz set rejected for eid {EID}: inventory not available",
            "EID", eid);
        throw Unavailable();
    }

    std::optional<uint64_t> minHw = inventory->getMinSpeedInHz();
    std::optional<uint64_t> maxHw = inventory->getMaxSpeedInHz();
    if (!minHw || !maxHw)
    {
        lg2::error(
            "RequestedSpeedLimitMinHz set rejected for eid {EID}: hardware min/max not yet known",
            "EID", eid);
        throw Unavailable();
    }

    if (newMinHz < *minHw || newMinHz > *maxHw)
    {
        lg2::error(
            "RequestedSpeedLimitMinHz set rejected for eid {EID}: value {VAL} out of range [{MIN}, {MAX}]",
            "EID", eid, "VAL", newMinHz, "MIN", *minHw, "MAX", *maxHw);
        throw InvalidArgument();
    }

    pendingMinHz = newMinHz;
    armSetLimitTimer();

    return 1;
}

void NvidiaGpuClockSpeedControl::armSetLimitTimer()
{
    setLimitTimer.expires_after(setLimitDebounce);
    setLimitTimer.async_wait(
        [weak{weak_from_this()}](const boost::system::error_code& ec) {
            if (ec == boost::asio::error::operation_aborted)
            {
                // Superseded by a later set within the debounce window.
                return;
            }
            std::shared_ptr<NvidiaGpuClockSpeedControl> self = weak.lock();
            if (!self)
            {
                return;
            }
            self->applyPendingClockLimit();
        });
}

void NvidiaGpuClockSpeedControl::applyPendingClockLimit()
{
    if (setClockLimitInflight)
    {
        // A previous SetClockLimit is still in flight; retry once it lands.
        armSetLimitTimer();
        return;
    }

    const uint64_t minHz = pendingMinHz.value_or(requestedMinHz);
    const uint64_t maxHz = pendingMaxHz.value_or(requestedMaxHz);
    pendingMinHz.reset();
    pendingMaxHz.reset();

    sendSetClockLimitRequest(static_cast<uint32_t>(minHz / mhzToHzFactor),
                             static_cast<uint32_t>(maxHz / mhzToHzFactor));
}

void NvidiaGpuClockSpeedControl::sendSetClockLimitRequest(uint32_t limitMinMHz,
                                                          uint32_t limitMaxMHz)
{
    const int rc = gpu::encodeSetClockLimitRequest(
        0, gpu::ClockType::GRAPHICS_CLOCK, gpu::ClockLimitFlag::PERSISTENCE,
        limitMinMHz, limitMaxMHz, setClockLimitRequestBuffer);

    if (rc != 0)
    {
        lg2::error(
            "Error encoding SET_CLOCK_LIMIT request for eid {EID}, rc={RC}",
            "EID", eid, "RC", rc);
        return;
    }

    setClockLimitInflight = true;

    mctpRequester.sendRecvMsg(
        eid, setClockLimitRequestBuffer,
        [weak{weak_from_this()}](const std::error_code& ec,
                                 std::span<const uint8_t> buffer) {
            auto self = weak.lock();
            if (!self)
            {
                lg2::error("Invalid NvidiaGpuClockSpeedControl reference");
                return;
            }
            self->handleSetClockLimitResponse(ec, buffer);
        });
}

void NvidiaGpuClockSpeedControl::handleSetClockLimitResponse(
    const std::error_code& ec, std::span<const uint8_t> buffer)
{
    if (ec)
    {
        lg2::error("Error setting clock limit for eid {EID}: {MSG}", "EID", eid,
                   "MSG", ec.message());
        setClockLimitInflight = false;
        return;
    }

    ocp::accelerator_management::CompletionCode cc{};
    uint16_t reasonCode = 0;
    const int rc = gpu::decodeSetClockLimitResponse(buffer, cc, reasonCode);

    if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS)
    {
        lg2::error(
            "Error decoding SetClockLimit response for eid {EID}: rc={RC}, cc={CC}, reasonCode={RESC}",
            "EID", eid, "RC", rc, "CC", static_cast<uint8_t>(cc), "RESC",
            reasonCode);
        setClockLimitInflight = false;
        return;
    }

    // The set succeeded; re-read from the device so requestedMin/MaxHz and
    // presentMin/MaxHz reflect the new state without waiting for the next
    // periodic poll. setClockLimitInflight stays set until this read-back's
    // response lands so the coalesce gate does not reopen on stale state.
    if (!requestEncoded)
    {
        // No read-back can be sent, so no response will ever arrive to reopen
        // the coalesce gate; release it here to avoid wedging it shut.
        setClockLimitInflight = false;
        return;
    }
    setClockLimitReadbackPending = true;
    sendGetClockLimitRequest();
}
