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

#include "Inventory.hpp"
#include "MctpMockTestBase.hpp"
#include "MessagePackUnpackUtils.hpp"
#include "MockMctpRequester.hpp"
#include "NvidiaGpuClockSpeedControl.hpp"
#include "NvidiaGpuMctpVdm.hpp"
#include "OcpMctpVdm.hpp"
#include "TestUtils.hpp"

// NOLINTNEXTLINE(misc-include-cleaner): sd_bus_error lives here
#include <systemd/sd-bus.h>

#include <boost/system/error_code.hpp>
#include <sdbusplus/message.hpp>

#include <algorithm>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <ranges>
#include <span>
#include <string>
#include <system_error>
#include <variant>
#include <vector>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

namespace
{

constexpr const char* clockSpeedIface =
    "xyz.openbmc_project.Control.OperatingClockSpeed";
constexpr const char* clockSpeedPathPrefix =
    "/xyz/openbmc_project/control/operatingclockspeed/";

constexpr uint64_t mhzToHz = 1'000'000;

// Bounds reported by the mock GPU's inventory; every in-range test value is
// picked from inside [minClockMHz, maxClockMHz].
constexpr uint32_t minClockMHz = 300;
constexpr uint32_t maxClockMHz = 2100;

// Long enough to cover the control's 100 ms debounce plus D-Bus round trips.
constexpr std::chrono::seconds pumpTimeout{5};

std::vector<uint8_t> buildGetClockLimitResponse(
    uint32_t requestedMin, uint32_t requestedMax, uint32_t presentMin,
    uint32_t presentMax)
{
    std::vector<uint8_t> buf(ocp::accelerator_management::commonResponseSize +
                             (4 * sizeof(uint32_t)));
    PackBuffer pack(buf);
    ocp::accelerator_management::packHeader(
        pack, gpu::nvidiaPciVendorId,
        ocp::accelerator_management::MessageType::RESPONSE, 0,
        static_cast<uint8_t>(gpu::MessageType::PLATFORM_ENVIRONMENTAL));
    pack.pack(static_cast<uint8_t>(
        gpu::PlatformEnvironmentalCommands::GET_CLOCK_LIMIT));
    pack.pack(static_cast<uint8_t>(
        ocp::accelerator_management::CompletionCode::SUCCESS));
    pack.pack(static_cast<uint16_t>(0)); // reserved
    pack.pack(static_cast<uint16_t>(4 * sizeof(uint32_t)));
    pack.pack(requestedMin);
    pack.pack(requestedMax);
    pack.pack(presentMin);
    pack.pack(presentMax);
    return buf;
}

// SetClockLimit carries no payload, so its success reply is the common
// response header with a zero data size.
std::vector<uint8_t> buildSetClockLimitResponse()
{
    std::vector<uint8_t> buf(ocp::accelerator_management::commonResponseSize);
    PackBuffer pack(buf);
    ocp::accelerator_management::packHeader(
        pack, gpu::nvidiaPciVendorId,
        ocp::accelerator_management::MessageType::RESPONSE, 0,
        static_cast<uint8_t>(gpu::MessageType::PLATFORM_ENVIRONMENTAL));
    pack.pack(static_cast<uint8_t>(
        gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT));
    pack.pack(static_cast<uint8_t>(
        ocp::accelerator_management::CompletionCode::SUCCESS));
    pack.pack(static_cast<uint16_t>(0)); // reserved
    pack.pack(static_cast<uint16_t>(0)); // data_size
    return buf;
}

// GetInventoryInformation reply carrying a uint32, the encoding the graphics
// clock bounds use.
std::vector<uint8_t> buildInventoryUint32Response(uint32_t value)
{
    return test_utils::buildPlatformEnvSuccessResponse(
        gpu::PlatformEnvironmentalCommands::GET_INVENTORY_INFORMATION, value);
}

// A 16-byte payload decodes cleanly for every non-integral inventory property
// (string fields and the 16-byte GUID alike).
std::vector<uint8_t> buildInventoryStringResponse()
{
    const std::string value = "NVIDIA-CLK-TEST0";
    std::vector<uint8_t> buf(
        ocp::accelerator_management::commonResponseSize + value.size());
    PackBuffer pack(buf);
    ocp::accelerator_management::packHeader(
        pack, gpu::nvidiaPciVendorId,
        ocp::accelerator_management::MessageType::RESPONSE, 0,
        static_cast<uint8_t>(gpu::MessageType::PLATFORM_ENVIRONMENTAL));
    pack.pack(static_cast<uint8_t>(
        gpu::PlatformEnvironmentalCommands::GET_INVENTORY_INFORMATION));
    pack.pack(static_cast<uint8_t>(
        ocp::accelerator_management::CompletionCode::SUCCESS));
    pack.pack(static_cast<uint16_t>(0));            // reserved
    pack.pack(static_cast<uint16_t>(value.size())); // data_size
    for (const char c : value)
    {
        pack.pack(static_cast<uint8_t>(c));
    }
    return buf;
}

uint8_t commandOf(std::span<const uint8_t> request)
{
    return request[ocp::accelerator_management::messageHeaderSize];
}

// GetInventoryInformation appends the property id after the common header.
uint8_t inventoryPropertyOf(std::span<const uint8_t> request)
{
    return request[ocp::accelerator_management::commonRequestSize];
}

// Payload of a SetClockLimit request, as it sits on the wire after the common
// request header.
struct SetClockLimitFields
{
    uint8_t clockType{};
    uint8_t flag{};
    uint32_t limitMinMHz{};
    uint32_t limitMaxMHz{};
};

SetClockLimitFields decodeSetClockLimitRequest(std::span<const uint8_t> request)
{
    UnpackBuffer buffer{request};
    ocp::accelerator_management::MessageType msgType{};
    uint8_t instanceId = 0;
    uint8_t nsmMsgType = 0;
    ocp::accelerator_management::unpackHeader(buffer, gpu::nvidiaPciVendorId,
                                              msgType, instanceId, nsmMsgType);

    uint8_t command = 0;
    uint8_t dataSize = 0;
    SetClockLimitFields fields;
    buffer.unpack(command);
    buffer.unpack(dataSize);
    buffer.unpack(fields.clockType);
    buffer.unpack(fields.flag);
    buffer.unpack(fields.limitMinMHz);
    buffer.unpack(fields.limitMaxMHz);
    return fields;
}

class NvidiaGpuClockSpeedControlTest : public MctpMockTestBase
{
  protected:
    void SetUp() override
    {
        MctpMockTestBase::SetUp();
        if (testing::Test::IsSkipped())
        {
            return;
        }
        ON_CALL(mctpMock, sendRecvMsg)
            .WillByDefault(
                [this](uint8_t /*eid*/, std::span<const uint8_t> request,
                       auto callback) {
                    sentRequests.emplace_back(request.begin(), request.end());
                    const std::vector<uint8_t> response = buildReply(request);
                    callback(std::error_code{}, response);
                });
    }

    // Answers a request the way a healthy GPU would.
    std::vector<uint8_t> buildReply(std::span<const uint8_t> request) const
    {
        switch (
            static_cast<gpu::PlatformEnvironmentalCommands>(commandOf(request)))
        {
            case gpu::PlatformEnvironmentalCommands::GET_INVENTORY_INFORMATION:
            {
                const auto propertyId = static_cast<gpu::InventoryPropertyId>(
                    inventoryPropertyOf(request));
                if (propertyId == gpu::InventoryPropertyId::MIN_GRAPHICS_CLOCK)
                {
                    return buildInventoryUint32Response(minClockMHz);
                }
                if (propertyId == gpu::InventoryPropertyId::MAX_GRAPHICS_CLOCK)
                {
                    return buildInventoryUint32Response(maxClockMHz);
                }
                return buildInventoryStringResponse();
            }
            case gpu::PlatformEnvironmentalCommands::GET_CLOCK_LIMIT:
                return buildGetClockLimitResponse(
                    clockLimit.requestedMin, clockLimit.requestedMax,
                    clockLimit.presentMin, clockLimit.presentMax);
            case gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT:
                return buildSetClockLimitResponse();
            default:
                return {};
        }
    }

    // Inventory drives the range check in the setters, so it must have
    // answered its MIN/MAX_GRAPHICS_CLOCK queries before the control is used.
    static std::shared_ptr<Inventory> createInventory(
        const std::string& name, uint8_t eid = test_utils::defaultEid)
    {
        auto inventory = std::make_shared<Inventory>(
            bus(), objects(), name, requester(),
            gpu::DeviceIdentification::DEVICE_GPU, eid, ioContext(), nullptr,
            nullptr);
        inventory->init();
        return inventory;
    }

    // shared_ptr ownership is required: the async handlers resolve
    // weak_from_this().
    static std::shared_ptr<NvidiaGpuClockSpeedControl> createControl(
        const std::string& name, const std::shared_ptr<Inventory>& inventory,
        uint8_t eid = test_utils::defaultEid)
    {
        return std::make_shared<NvidiaGpuClockSpeedControl>(
            objects(), name, requester(), eid, ioContext(), inventory);
    }

    static std::string pathFor(const std::string& name)
    {
        return clockSpeedPathPrefix + name;
    }

    size_t countRequests(gpu::PlatformEnvironmentalCommands command) const
    {
        return static_cast<size_t>(
            std::ranges::count_if(sentRequests, [command](const auto& request) {
                return commandOf(request) == static_cast<uint8_t>(command);
            }));
    }

    // The most recent request for `command`, or an empty vector if the
    // command was never sent.
    std::vector<uint8_t> lastRequest(
        gpu::PlatformEnvironmentalCommands command) const
    {
        for (const auto& request : sentRequests | std::views::reverse)
        {
            if (commandOf(request) == static_cast<uint8_t>(command))
            {
                return request;
            }
        }
        return {};
    }

    // Result of a D-Bus property write: the error name lets a rejected write
    // be told apart from a transport failure.
    struct SetResult
    {
        bool succeeded{false};
        std::string errorName;
    };

    // Writes a property on this connection's own object server. Async because
    // sd-bus rejects self-directed synchronous calls with ELOOP.
    static SetResult setSpeedLimit(const std::string& path,
                                   const std::string& property, uint64_t value)
    {
        auto result = std::make_shared<std::optional<SetResult>>();

        bus()->async_method_call(
            [result](const boost::system::error_code& ec,
                     sdbusplus::message_t& reply) {
                SetResult outcome;
                outcome.succeeded = !ec;
                // NOLINTNEXTLINE(misc-include-cleaner): from sd-bus.h
                const sd_bus_error* error = reply.get_error();
                if (error != nullptr && error->name != nullptr)
                {
                    outcome.errorName = error->name;
                }
                *result = outcome;
            },
            bus()->get_unique_name(), path, "org.freedesktop.DBus.Properties",
            "Set", clockSpeedIface, property, std::variant<uint64_t>(value));

        pumpIoUntil([result] { return result->has_value(); }, pumpTimeout);
        return result->value_or(SetResult{false, "timeout"});
    }

    // Values the mock GPU reports for GetClockLimit, in MHz.
    struct ClockLimit
    {
        uint32_t requestedMin{minClockMHz};
        uint32_t requestedMax{maxClockMHz};
        uint32_t presentMin{minClockMHz};
        uint32_t presentMax{maxClockMHz};
    };
    ClockLimit clockLimit;

    std::vector<std::vector<uint8_t>> sentRequests;
};

// Constructor — D-Bus interface creation

TEST_F(NvidiaGpuClockSpeedControlTest, ConstructorCreatesClockSpeedInterface)
{
    const std::string name = "clk_ctor";
    const auto control = createControl(name, createInventory(name));

    // Present* start at their registered defaults until the first poll.
    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "PresentSpeedLimitMinHz"),
              0U);
    // Requested* are backed by the class members, which start at zero.
    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "RequestedSpeedLimitMinHz"),
              0U);
    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "RequestedSpeedLimitMaxHz"),
              0U);
}

// Update — GetClockLimit publishes both the present and the requested limits

TEST_F(NvidiaGpuClockSpeedControlTest, UpdatePublishesClockLimits)
{
    const std::string name = "clk_update";
    clockLimit = {.requestedMin = 600,
                  .requestedMax = 1800,
                  .presentMin = 700,
                  .presentMax = 1700};

    const auto control = createControl(name, createInventory(name));
    control->update();

    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "PresentSpeedLimitMinHz"),
              700U * mhzToHz);
    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "PresentSpeedLimitMaxHz"),
              1700U * mhzToHz);
    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "RequestedSpeedLimitMinHz"),
              600U * mhzToHz);
    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "RequestedSpeedLimitMaxHz"),
              1800U * mhzToHz);
}

// Set — a write inside the device's range reaches the device as SetClockLimit

TEST_F(NvidiaGpuClockSpeedControlTest, SetRequestedMaxIssuesSetClockLimit)
{
    const std::string name = "clk_set_max";
    const auto control = createControl(name, createInventory(name));
    sentRequests.clear();

    const uint64_t newMaxHz = 1500ULL * mhzToHz;
    const SetResult result =
        setSpeedLimit(pathFor(name), "RequestedSpeedLimitMaxHz", newMaxHz);
    ASSERT_TRUE(result.succeeded) << result.errorName;

    ASSERT_TRUE(pumpIoUntil(
        [this] {
            return countRequests(
                       gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT) > 0;
        },
        pumpTimeout));

    const std::vector<uint8_t> request =
        lastRequest(gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT);
    ASSERT_FALSE(request.empty());

    const SetClockLimitFields fields = decodeSetClockLimitRequest(request);
    EXPECT_EQ(fields.clockType,
              static_cast<uint8_t>(gpu::ClockType::GRAPHICS_CLOCK));
    EXPECT_EQ(fields.flag,
              static_cast<uint8_t>(gpu::ClockLimitFlag::PERSISTENCE));
    EXPECT_EQ(fields.limitMaxMHz, 1500U);
}

// Set — Min and Max writes of one PATCH coalesce into a single SetClockLimit

TEST_F(NvidiaGpuClockSpeedControlTest, SetMinAndMaxCoalesceIntoOneRequest)
{
    const std::string name = "clk_coalesce";
    const auto control = createControl(name, createInventory(name));
    sentRequests.clear();

    ASSERT_TRUE(setSpeedLimit(pathFor(name), "RequestedSpeedLimitMinHz",
                              1200ULL * mhzToHz)
                    .succeeded);
    ASSERT_TRUE(setSpeedLimit(pathFor(name), "RequestedSpeedLimitMaxHz",
                              1400ULL * mhzToHz)
                    .succeeded);

    ASSERT_TRUE(pumpIoUntil(
        [this] {
            return countRequests(
                       gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT) > 0;
        },
        pumpTimeout));

    // Let any second debounce expiry that would follow land before counting.
    pumpIoUntil([] { return false; }, std::chrono::seconds{1});

    EXPECT_EQ(
        countRequests(gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT), 1U);

    const std::vector<uint8_t> request =
        lastRequest(gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT);
    ASSERT_FALSE(request.empty());

    const SetClockLimitFields fields = decodeSetClockLimitRequest(request);
    EXPECT_EQ(fields.limitMinMHz, 1200U);
    EXPECT_EQ(fields.limitMaxMHz, 1400U);
}

// Set — a successful SetClockLimit is followed by a GetClockLimit read-back,
// so D-Bus reflects the device without waiting for the next poll.

TEST_F(NvidiaGpuClockSpeedControlTest, SetSuccessReadsBackFromDevice)
{
    const std::string name = "clk_readback";
    const auto control = createControl(name, createInventory(name));
    sentRequests.clear();

    clockLimit = {.requestedMin = 900,
                  .requestedMax = 1600,
                  .presentMin = 900,
                  .presentMax = 1600};

    ASSERT_TRUE(setSpeedLimit(pathFor(name), "RequestedSpeedLimitMaxHz",
                              1600ULL * mhzToHz)
                    .succeeded);

    ASSERT_TRUE(pumpIoUntil(
        [this] {
            return countRequests(
                       gpu::PlatformEnvironmentalCommands::GET_CLOCK_LIMIT) > 0;
        },
        pumpTimeout));

    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "RequestedSpeedLimitMaxHz"),
              1600U * mhzToHz);
    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "PresentSpeedLimitMaxHz"),
              1600U * mhzToHz);
}

// Set — rejected writes

TEST_F(NvidiaGpuClockSpeedControlTest, SetAboveHardwareMaxRejected)
{
    const std::string name = "clk_too_high";
    const auto control = createControl(name, createInventory(name));
    sentRequests.clear();

    const SetResult result =
        setSpeedLimit(pathFor(name), "RequestedSpeedLimitMaxHz",
                      (maxClockMHz + 1ULL) * mhzToHz);

    EXPECT_FALSE(result.succeeded);
    EXPECT_EQ(result.errorName,
              "xyz.openbmc_project.Common.Error.InvalidArgument");
    EXPECT_EQ(
        countRequests(gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT), 0U);
}

TEST_F(NvidiaGpuClockSpeedControlTest, SetBelowHardwareMinRejected)
{
    const std::string name = "clk_too_low";
    const auto control = createControl(name, createInventory(name));
    sentRequests.clear();

    const SetResult result =
        setSpeedLimit(pathFor(name), "RequestedSpeedLimitMinHz",
                      (minClockMHz - 1ULL) * mhzToHz);

    EXPECT_FALSE(result.succeeded);
    EXPECT_EQ(result.errorName,
              "xyz.openbmc_project.Common.Error.InvalidArgument");
    EXPECT_EQ(
        countRequests(gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT), 0U);
}

TEST_F(NvidiaGpuClockSpeedControlTest, SetWithoutInventoryRejected)
{
    const std::string name = "clk_no_inventory";
    const auto control = createControl(name, nullptr);

    const SetResult result = setSpeedLimit(
        pathFor(name), "RequestedSpeedLimitMaxHz", 1500ULL * mhzToHz);

    EXPECT_FALSE(result.succeeded);
    EXPECT_EQ(result.errorName, "xyz.openbmc_project.Common.Error.Unavailable");
}

TEST_F(NvidiaGpuClockSpeedControlTest, SetBeforeInventoryKnownRejected)
{
    const std::string name = "clk_inventory_pending";
    // No init(): the graphics clock bounds have not been read from the device.
    auto inventory = std::make_shared<Inventory>(
        bus(), objects(), name, requester(),
        gpu::DeviceIdentification::DEVICE_GPU, test_utils::defaultEid,
        ioContext(), nullptr, nullptr);
    const auto control = createControl(name, inventory);

    const SetResult result = setSpeedLimit(
        pathFor(name), "RequestedSpeedLimitMaxHz", 1500ULL * mhzToHz);

    EXPECT_FALSE(result.succeeded);
    EXPECT_EQ(result.errorName, "xyz.openbmc_project.Common.Error.Unavailable");
}

// Error handling — a failed exchange must neither crash nor publish values

TEST_F(NvidiaGpuClockSpeedControlTest, UpdateMctpTransportErrorNoCrash)
{
    const std::string name = "clk_mctp_err";
    const auto inventory = createInventory(name);
    const auto control = createControl(name, inventory);

    ON_CALL(mctpMock, sendRecvMsg)
        .WillByDefault(mock_mctp::respondWith(
            std::make_error_code(std::errc::timed_out), {}));

    EXPECT_NO_THROW(control->update());
    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "PresentSpeedLimitMinHz"),
              0U);
}

TEST_F(NvidiaGpuClockSpeedControlTest, UpdateBadCompletionCodeNoCrash)
{
    const std::string name = "clk_bad_cc";
    const auto inventory = createInventory(name);
    const auto control = createControl(name, inventory);

    ON_CALL(mctpMock, sendRecvMsg)
        .WillByDefault(mock_mctp::respondWith(
            {}, test_utils::buildPlatformEnvErrorResponse(
                    gpu::PlatformEnvironmentalCommands::GET_CLOCK_LIMIT,
                    static_cast<uint8_t>(
                        ocp::accelerator_management::CompletionCode::ERROR),
                    0)));

    EXPECT_NO_THROW(control->update());
    EXPECT_EQ(getProperty<uint64_t>(pathFor(name), clockSpeedIface,
                                    "PresentSpeedLimitMinHz"),
              0U);
}

TEST_F(NvidiaGpuClockSpeedControlTest, UpdateEmptyBufferNoCrash)
{
    const std::string name = "clk_empty";
    const auto inventory = createInventory(name);
    const auto control = createControl(name, inventory);

    ON_CALL(mctpMock, sendRecvMsg)
        .WillByDefault(mock_mctp::respondWith({}, {}));

    EXPECT_NO_THROW(control->update());
}

// A SetClockLimit that fails must release the coalesce gate, so a later write
// still reaches the device.

TEST_F(NvidiaGpuClockSpeedControlTest, SetFailureDoesNotBlockLaterSet)
{
    const std::string name = "clk_set_err";
    const auto control = createControl(name, createInventory(name));

    ON_CALL(mctpMock, sendRecvMsg)
        .WillByDefault([this](uint8_t /*eid*/, std::span<const uint8_t> request,
                              auto callback) {
            sentRequests.emplace_back(request.begin(), request.end());
            if (commandOf(request) ==
                static_cast<uint8_t>(
                    gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT))
            {
                callback(std::make_error_code(std::errc::timed_out), {});
                return;
            }
            const std::vector<uint8_t> response = buildReply(request);
            callback(std::error_code{}, response);
        });

    sentRequests.clear();
    ASSERT_TRUE(setSpeedLimit(pathFor(name), "RequestedSpeedLimitMaxHz",
                              1500ULL * mhzToHz)
                    .succeeded);
    ASSERT_TRUE(pumpIoUntil(
        [this] {
            return countRequests(
                       gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT) > 0;
        },
        pumpTimeout));

    ASSERT_TRUE(setSpeedLimit(pathFor(name), "RequestedSpeedLimitMaxHz",
                              1600ULL * mhzToHz)
                    .succeeded);
    EXPECT_TRUE(pumpIoUntil(
        [this] {
            return countRequests(
                       gpu::PlatformEnvironmentalCommands::SET_CLOCK_LIMIT) > 1;
        },
        pumpTimeout));
}

// Destructor

TEST_F(NvidiaGpuClockSpeedControlTest, DestructorDoesNotCrash)
{
    const std::string name = "clk_dtor";
    auto control = createControl(name, createInventory(name));
    ASSERT_NE(control, nullptr);
    EXPECT_NO_THROW(control.reset());
    drainPendingAsync();
}

} // namespace
