#include "fru_oem_ibm.hpp"

#include "oem/ibm/libpldmresponder/utils.hpp"

#include <com/ibm/VPD/Manager/client.hpp>
#include <phosphor-logging/lg2.hpp>

#include <format>
#include <ranges>

PHOSPHOR_LOG2_USING;

namespace pldm
{
namespace responder
{
namespace oem_ibm_fru
{

void pldm::responder::oem_ibm_fru::Handler::setIBMFruHandler(
    pldm::responder::fru::Handler* handler)
{
    fruHandler = handler;
}

int pldm::responder::oem_ibm_fru::Handler::processOEMFRUTable(
    const std::vector<uint8_t>& fruData)
{
    uint8_t dataSize = 0;
    const uint8_t* data = fruData.data();

    while (dataSize < fruData.size())
    {
        auto record =
            reinterpret_cast<const pldm_fru_record_data_format*>(data);
        if (!record)
        {
            return PLDM_ERROR_INVALID_DATA;
        }

        auto& entityAssociationMap = getAssociateEntityMap();
        uint16_t fruRSI = le16toh(record->record_set_id);

        dataSize += sizeof(pldm_fru_record_data_format) -
                    sizeof(pldm_fru_record_tlv);

        data += sizeof(pldm_fru_record_data_format) -
                sizeof(pldm_fru_record_tlv);

        for ([[maybe_unused]] const auto& i :
             std::views::iota(0, (int)record->num_fru_fields))
        {
            auto tlv = reinterpret_cast<const pldm_fru_record_tlv*>(data);
            if (!tlv)
            {
                return PLDM_ERROR_INVALID_DATA;
            }

            if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_PCIE_CONFIG_SPACE_DATA)
            {
                auto pcieData =
                    reinterpret_cast<const PcieConfigSpaceData*>(tlv->value);

                if (!pcieData)
                {
                    return PLDM_ERROR_INVALID_DATA;
                }

                auto vendorId =
                    std::format("0x{:04x}", htole16(pcieData->vendorId));
                auto deviceId =
                    std::format("0x{:04x}", htole16(pcieData->deviceId));
                auto revisionId =
                    std::format("0x{:02x}", htole16(pcieData->revisionId));

                std::string classCode = "0x";
                for (const auto& ele : pcieData->classCode)
                {
                    classCode += std::format("{:02x}", ele);
                }

                auto subSystemVendorId = std::format(
                    "0x{:04x}", htole16(pcieData->subSystemVendorId));
                auto subSystemId =
                    std::format("0x{:04x}", htole16(pcieData->subSystemId));

                updateDBusProperty(fruRSI, entityAssociationMap, vendorId,
                                   deviceId, revisionId, classCode,
                                   subSystemVendorId, subSystemId);
            }

            if (tlv->type == PLDM_OEM_IBM_FRU_FIELD_TYPE_FIRMWARE_UAK)
            {
                std::vector<uint8_t> value(&tlv->value[0],
                                           &tlv->value[tlv->length]);
                setFirmwareUAK(value);
            }

            dataSize += sizeof(pldm_fru_record_tlv) - sizeof(uint8_t) +
                        tlv->length;

            // Increment data pointer by the size of the current TLV
            data += sizeof(pldm_fru_record_tlv) - sizeof(uint8_t) + tlv->length;
        }
    }

    return PLDM_SUCCESS;
}

void Handler::updateDBusProperty(
    uint16_t fruRSI, const AssociatedEntityMap& fruAssociationMap,
    const std::string& vendorId, const std::string& deviceId,
    const std::string& revisionId, const std::string& classCode,
    const std::string& subSystemVendorId, const std::string& subSystemId)
{
    uint16_t entityType{};
    uint16_t entityInstanceNum{};
    uint16_t containerId{};
    uint16_t terminusHandle{};
    const pldm_pdr_record* record{};

    record = pldm_pdr_fru_record_set_find_by_rsi(
        pdrRepo, fruRSI, &terminusHandle, &entityType, &entityInstanceNum,
        &containerId);

    if (record)
    {
        for (const auto& [key, value] : fruAssociationMap)
        {
            if (entityInstanceNum == value.entity_instance_num &&
                entityType == value.entity_type &&
                containerId == value.entity_container_id)
            {
                if (!(pldm::responder::utils::checkIfIBMFru(key)))
                {
                    pldm::utils::setFruPresence(key, true);
                }
                dbus_map_update(key, "Function0VendorId", vendorId);
                dbus_map_update(key, "Function0DeviceId", deviceId);
                dbus_map_update(key, "Function0RevisionId", revisionId);
                dbus_map_update(key, "Function0ClassCode", classCode);
                dbus_map_update(key, "Function0SubsystemVendorId",
                                subSystemVendorId);
                dbus_map_update(key, "Function0SubsystemId", subSystemId);
            }
        }
    }
}

void Handler::dbus_map_update(const std::string& adapterObjPath,
                              const std::string& propertyName,
                              const std::string& propValue)
{
    pldm::utils::PropertyValue value = propValue;
    pldm::utils::DBusMapping dbusMapping;
    dbusMapping.objectPath = adapterObjPath;
    dbusMapping.interface = "xyz.openbmc_project.Inventory.Item.PCIeDevice";
    dbusMapping.propertyName = propertyName;
    dbusMapping.propertyType = "string";
    try
    {
        pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
    }
    catch (const std::exception& e)
    {
        error(
            "Failed to set property '{PROPERTY} at path '{PATH}' and interface '{INTERFACE}', error - {ERROR}",
            "PROPERTY", propertyName, "PATH", adapterObjPath, "INTERFACE",
            dbusMapping.interface, "ERROR", e);
    }
}

void Handler::setFirmwareUAK(const std::vector<uint8_t>& data)
{
    using VPDManager = sdbusplus::client::com::ibm::vpd::Manager<>;

    static constexpr auto uakObjPath = "/com/ibm/VPD/Manager";
    static constexpr auto fruPath =
        "/xyz/openbmc_project/inventory/system/chassis/motherboard";

    auto& bus = pldm::utils::DBusHandler::getBus();
    try
    {
        auto service = pldm::utils::DBusHandler().getService(
            uakObjPath, VPDManager::interface);
        auto method = bus.new_method_call(
            service.c_str(), uakObjPath, VPDManager::interface, "WriteKeyword");
        method.append(static_cast<sdbusplus::object_path>(fruPath), "UTIL",
                      "D8", data);
        bus.call_noreply(method, dbusTimeout);
    }
    catch (const std::exception& e)
    {
        error("Failed to make a DBus call to VPD manager, error - {ERROR}",
              "ERROR", e);
    }
}

} // namespace oem_ibm_fru
} // namespace responder
} // namespace pldm
