/*
 * SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION &
 * AFFILIATES. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

#include "NvidiaGpuThresholds.hpp"

#include <MctpRequester.hpp>
#include <NvidiaGpuMctpVdm.hpp>
#include <OcpMctpVdm.hpp>
#include <phosphor-logging/lg2.hpp>

#include <array>
#include <cerrno>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <span>
#include <vector>

void processReadThermalParameterResponse(
    const std::function<void(uint8_t, int32_t)>& callback,
    const std::span<const uint8_t> respMsg, int sendRecvMsgResult)
{
    if (sendRecvMsgResult != 0)
    {
        lg2::error(
            "Error reading thermal parameter: sending message over MCTP failed, rc={RC}",
            "RC", sendRecvMsgResult);
        callback(EPROTO, 0);
        return;
    }

    ocp::accelerator_management::CompletionCode cc{};
    uint16_t reasonCode = 0;
    int32_t threshold = 0;

    auto rc = gpu::decodeReadThermalParametersResponse(respMsg, cc, reasonCode,
                                                       threshold);

    if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS)
    {
        lg2::error(
            "Error reading thermal parameter: decode failed, rc={RC}, cc={CC}, reasonCode={RESC}",
            "RC", rc, "CC", cc, "RESC", reasonCode);
        callback(EPROTO, 0);
        return;
    }

    callback(0, threshold);
};

void readThermalParameter(uint8_t eid, uint8_t id,
                          mctp::MctpRequester& mctpRequester,
                          const std::function<void(uint8_t, int32_t)>& callback)
{
    auto reqMsg = std::make_shared<
        std::array<uint8_t, sizeof(gpu::ReadThermalParametersRequest)>>();

    auto respMsg = std::make_shared<
        std::array<uint8_t, sizeof(gpu::ReadThermalParametersResponse)>>();

    auto rc = gpu::encodeReadThermalParametersRequest(0, id, *reqMsg);
    if (rc != 0)
    {
        lg2::error(
            "Error reading thermal parameter for eid {EID} and parameter id {PID} : encode failed. rc={RC}",
            "EID", eid, "PID", id, "RC", rc);
        callback(rc, 0);
        return;
    }

    mctpRequester.sendRecvMsg(
        eid, *reqMsg, *respMsg,
        [reqMsg, respMsg, callback](int sendRecvMsgResult) {
            processReadThermalParameterResponse(callback, *respMsg,
                                                sendRecvMsgResult);
        });
}

void readThermalParameterCallback(
    uint8_t eid, const std::shared_ptr<std::vector<uint8_t>>& ids,
    mctp::MctpRequester& mctpRequester,
    const std::function<void(uint8_t, std::vector<int32_t>)>& callback,
    size_t index, const std::shared_ptr<std::vector<int32_t>>& thresholds,
    uint8_t rc, int32_t threshold)
{
    if (rc != 0)
    {
        lg2::error(
            "Error reading thermal parameter for eid {EID} and parameter id {PID}. rc={RC}",
            "EID", eid, "PID", (*ids)[index], "RC", rc);
        callback(rc, *thresholds);
        return;
    }

    thresholds->push_back(threshold);

    ++index;
    if (index == ids->size())
    {
        callback(rc, *thresholds);
    }
    else
    {
        readThermalParameter(eid, (*ids)[index], mctpRequester,
                             std::bind_front(readThermalParameterCallback, eid,
                                             ids, std::ref(mctpRequester),
                                             callback, index, thresholds));
    }
}

void readThermalParameters(
    uint8_t eid, const std::vector<uint8_t>& ids,
    mctp::MctpRequester& mctpRequester,
    const std::function<void(uint8_t, std::vector<int32_t>)>& callback)
{
    auto thresholds = std::make_shared<std::vector<int32_t>>();
    size_t index = 0;

    readThermalParameter(
        eid, ids[index], mctpRequester,
        std::bind_front(readThermalParameterCallback, eid,
                        std::make_shared<std::vector<uint8_t>>(ids),
                        std::ref(mctpRequester), callback, index, thresholds));
}
