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

#include "NvidiaGpuLongRunningCommand.hpp"

#include <MctpRequester.hpp>
#include <MessagePackUnpackUtils.hpp>
#include <NvidiaGpuMctpVdm.hpp>
#include <NvidiaLongRunningHandler.hpp>
#include <OcpMctpVdm.hpp>
#include <SerialQueue.hpp>
#include <boost/system/error_code.hpp>
#include <phosphor-logging/lg2.hpp>

#include <cstdint>
#include <memory>
#include <span>
#include <system_error>
#include <utility>

NvidiaGpuLongRunningCommand::NvidiaGpuLongRunningCommand(
    uint8_t eid, mctp::MctpRequester& mctpRequester,
    std::shared_ptr<SerialQueue> longRunningQueue,
    std::shared_ptr<NvidiaLongRunningResponseHandler>
        longRunningResponseHandler,
    Config config) :
    eid(eid), mctpRequester(mctpRequester),
    longRunningQueue(std::move(longRunningQueue)),
    longRunningResponseHandler(std::move(longRunningResponseHandler)),
    config(std::move(config)), request(this->config.requestSize, 0)
{
    const int rc = this->config.encodeRequest(request);
    if (rc == 0)
    {
        requestEncoded = true;
    }
    else
    {
        lg2::error("Failed to encode {NAME} request: rc={RC}, EID={EID}",
                   "NAME", this->config.metricName, "RC", rc, "EID", eid);
    }
}

void NvidiaGpuLongRunningCommand::update()
{
    longRunningQueue->submit(
        [weak{weak_from_this()}](SerialQueue::ReleaseHandle handle) {
            std::shared_ptr<NvidiaGpuLongRunningCommand> self = weak.lock();
            if (!self)
            {
                return;
            }
            self->doUpdate(std::move(handle));
        });
}

void NvidiaGpuLongRunningCommand::doUpdate(SerialQueue::ReleaseHandle handle)
{
    if (!requestEncoded)
    {
        return;
    }

    mctpRequester.sendRecvMsg(
        eid, request,
        [weak{weak_from_this()},
         handle = std::move(handle)](const std::error_code& ec,
                                     std::span<const uint8_t> buffer) mutable {
            std::shared_ptr<NvidiaGpuLongRunningCommand> self = weak.lock();
            if (!self)
            {
                return;
            }
            self->processResponse(std::move(handle), ec, buffer);
        });
}

void NvidiaGpuLongRunningCommand::processResponse(
    SerialQueue::ReleaseHandle handle, const std::error_code& ec,
    std::span<const uint8_t> buffer)
{
    if (ec)
    {
        lg2::error("Error updating {NAME}: sending message over MCTP failed, "
                   "rc={RC}, EID={EID}",
                   "NAME", config.metricName, "RC", ec.message(), "EID", eid);
        return;
    }

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

    UnpackBuffer unpackBuffer(buffer);

    int rc = gpu::decodeResponseCommonHeader(
        unpackBuffer, config.messageType,
        static_cast<uint8_t>(config.commandId), cc, reasonCode);

    if (rc != 0)
    {
        lg2::error("Error updating {NAME}: decode failed, "
                   "rc={RC}, cc={CC}, reasonCode={RESC}, EID={EID}",
                   "NAME", config.metricName, "RC", rc, "CC",
                   static_cast<uint8_t>(cc), "RESC", reasonCode, "EID", eid);
        return;
    }

    switch (cc)
    {
        case ocp::accelerator_management::CompletionCode::SUCCESS:
        {
            config.onImmediateSuccess(buffer);
            return;
        }

        case ocp::accelerator_management::CompletionCode::ACCEPTED:
        {
            uint8_t instanceId = 0;
            rc = ocp::accelerator_management::decodeInstanceId(buffer,
                                                               instanceId);
            if (rc != 0)
            {
                lg2::error(
                    "Error updating {NAME}: failed to decode instance id, "
                    "rc={RC}, EID={EID}",
                    "NAME", config.metricName, "RC", rc, "EID", eid);
                return;
            }

            rc = longRunningResponseHandler->registerResponseHandler(
                config.messageType, static_cast<uint8_t>(config.commandId),
                instanceId,
                [weak{weak_from_this()}, handle = std::move(handle)](
                    boost::system::error_code longRunningEc,
                    ocp::accelerator_management::CompletionCode longRunningCc,
                    uint16_t longRunningReasonCode,
                    std::span<const uint8_t> responseData) mutable {
                    std::shared_ptr<NvidiaGpuLongRunningCommand> self =
                        weak.lock();
                    if (!self)
                    {
                        return;
                    }

                    self->processLongRunningResponse(
                        longRunningEc, longRunningCc, longRunningReasonCode,
                        responseData);
                });

            if (rc != 0)
            {
                lg2::error(
                    "Error updating {NAME}: failed to register long running "
                    "response handler, rc={RC}, EID={EID}",
                    "NAME", config.metricName, "RC", rc, "EID", eid);
            }

            return;
        }

        default:
            lg2::error(
                "Error updating {NAME}: received unexpected completion code, "
                "cc={CC}, reasonCode={RESC}, EID={EID}",
                "NAME", config.metricName, "CC", static_cast<uint8_t>(cc),
                "RESC", reasonCode, "EID", eid);
            return;
    }
}

void NvidiaGpuLongRunningCommand::processLongRunningResponse(
    boost::system::error_code ec,
    ocp::accelerator_management::CompletionCode cc, uint16_t reasonCode,
    std::span<const uint8_t> responseData)
{
    if (ec)
    {
        lg2::error("Error updating {NAME}: long running response failed, "
                   "rc={RC}, EID={EID}",
                   "NAME", config.metricName, "RC", ec.message(), "EID", eid);
        return;
    }

    if (cc != ocp::accelerator_management::CompletionCode::SUCCESS)
    {
        lg2::error(
            "Error updating {NAME}: long running response indicated failure, "
            "cc={CC}, reasonCode={RESC}, EID={EID}",
            "NAME", config.metricName, "CC", static_cast<uint8_t>(cc), "RESC",
            reasonCode, "EID", eid);
        return;
    }

    config.onLongRunningPayload(responseData);
}
