#include "NvidiaGpuMctpVdm.hpp"

#include <MctpRequester.hpp>
#include <NvidiaEventReporting.hpp>
#include <OcpMctpVdm.hpp>
#include <boost/container_hash/hash.hpp>
#include <phosphor-logging/lg2.hpp>

#include <array>
#include <cstdint>
#include <initializer_list>
#include <span>
#include <system_error>
#include <unordered_map>

std::unordered_map<NvidiaEventHandler::EventKey, EventHandler,
                   boost::hash<NvidiaEventHandler::EventKey>>
    NvidiaEventHandler::eventHandlers;

static std::array<uint64_t, messageTypeCount> buildEventSourceMasks(
    std::initializer_list<EventDescriptor> events)
{
    std::array<uint64_t, messageTypeCount> masks{};

    for (const auto& event : events)
    {
        const uint8_t idx = static_cast<uint8_t>(event.messageType);

        if (idx >= messageTypeCount)
        {
            lg2::error(
                "Invalid message type {MSG} for event code {CODE}, skipping",
                "MSG", idx, "CODE", event.eventCode);
            continue;
        }

        if (event.eventCode >= 64)
        {
            lg2::error(
                "Event code {CODE} exceeds 64-bit mask capacity, skipping",
                "CODE", event.eventCode);
            continue;
        }

        masks[idx] |= (1ULL << event.eventCode);
    }

    return masks;
}

NvidiaEventReportingConfig::NvidiaEventReportingConfig(
    uint8_t eid, mctp::MctpRequester& req,
    std::initializer_list<EventDescriptor> events) :
    eid{eid}, requester{req}, eventMasks{buildEventSourceMasks(events)}
{
    for (const auto& event : events)
    {
        NvidiaEventHandler::registerEventHandler(
            eid, event.messageType, event.eventCode, event.eventHandler);
    }
}

void NvidiaEventReportingConfig::init()
{
    int rc = gpu::encodeSetEventSubscriptionRequest(generationSettingEnablePush,
                                                    bmc_eid, subscriptionReq);
    if (rc != 0)
    {
        lg2::error("Failed to setup device subscription for eid {EID}", "EID",
                   eid);
        return;
    }

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

void NvidiaEventReportingConfig::handleSetupSubscription(
    const std::error_code& ec, std::span<const uint8_t> buffer)
{
    if (ec)
    {
        lg2::error("failed to setup event subscription on eid {EID}: {EC}",
                   "EID", eid, "EC", ec.message());
        return;
    }

    ocp::accelerator_management::CompletionCode cc{};
    uint16_t reasonCode = 0;
    int rc = gpu::decodeSetEventSubscriptionResponse(buffer, cc, reasonCode);
    if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS)
    {
        lg2::error("failed to setup event subscription on eid {EID}: "
                   "rc={RC}, cc={CC}, reasonCode={RESC}",
                   "EID", eid, "RC", rc, "CC", cc, "RESC", reasonCode);
        return;
    }

    // Device is set up for push notifications, now configure event sources
    currentMessageTypeIdx = 0;
    sendNextEventSource();
}

void NvidiaEventReportingConfig::sendNextEventSource()
{
    // Find next message type with events that can be encoded
    while (currentMessageTypeIdx < messageTypeCount)
    {
        // Skip message types with no events
        if (eventMasks[currentMessageTypeIdx] == 0)
        {
            currentMessageTypeIdx++;
            continue;
        }

        uint64_t events = eventMasks[currentMessageTypeIdx];
        auto messageType = static_cast<uint8_t>(currentMessageTypeIdx);

        const int rc =
            gpu::encodeSetEventSourcesRequest(events, messageType, sourcesReq);
        if (rc != 0)
        {
            lg2::error(
                "Failed to encode event sources request for EID {EID} messageType {MSG}",
                "EID", eid, "MSG", messageType);
            currentMessageTypeIdx++;
            continue;
        }

        break;
    }

    if (currentMessageTypeIdx >= messageTypeCount)
    {
        lg2::info("Finished setting up event sources for eid {EID}", "EID",
                  eid);
        // All event sources processed
        return;
    }

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

void NvidiaEventReportingConfig::handleSetupEvents(
    const std::error_code& ec, std::span<const uint8_t> buffer)
{
    if (ec)
    {
        lg2::error("failed to set up events for eid {EID}: {MSG}", "EID", eid,
                   "MSG", ec.message());
        currentMessageTypeIdx++;
        sendNextEventSource();
        return;
    }

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

    const int rc = gpu::decodeSetEventSourcesResponse(buffer, cc, reasonCode);
    if (rc != 0 || cc != ocp::accelerator_management::CompletionCode::SUCCESS)
    {
        lg2::error("failed to set event sources on eid {EID}: "
                   "rc={RC}, cc={CC}, reasonCode={RESC}",
                   "EID", eid, "RC", rc, "CC", cc, "RESC", reasonCode);
        currentMessageTypeIdx++;
        sendNextEventSource();
        return;
    }

    // Move to next message type and continue
    currentMessageTypeIdx++;
    sendNextEventSource();
}

void NvidiaEventHandler::handleEvent(uint8_t eid,
                                     std::span<const uint8_t> buffer)
{
    EventInfo eventInfo{};
    uint8_t messageType = 0;
    uint8_t eventId = 0;
    uint8_t eventSize = 0;
    std::span<const uint8_t> eventData;

    const int rc = ocp::accelerator_management::decodeEvent(
        buffer, gpu::nvidiaPciVendorId, messageType, eventInfo.ackRequired,
        eventInfo.version, eventId, eventInfo.eventClass, eventInfo.eventState,
        eventSize, eventData);

    if (rc != 0)
    {
        lg2::error("Failed to decode event log");
        return;
    }

    EventKey key{eid, static_cast<gpu::MessageType>(messageType), eventId};
    const auto itr = eventHandlers.find(key);
    if (itr == eventHandlers.end())
    {
        lg2::error(
            "No handler registered for event code {CODE} message type {MSG} from eid {EID}",
            "CODE", eventId, "MSG", messageType, "EID", eid);
        return;
    }

    itr->second(eventInfo, eventData);
}
