/*
 * SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION &
 * AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "utils.hpp"

#include "dBusAsyncUtils.hpp"

#include <fcntl.h>    // For ftruncate
#include <sys/mman.h> // for memfd_create
#include <sys/stat.h> // for fstat
#include <unistd.h>   // for write and lseek

#include <boost/regex.hpp>
#include <phosphor-logging/lg2.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
#include <xyz/openbmc_project/Logging/Entry/server.hpp>
#include <xyz/openbmc_project/Software/ExtendedVersion/server.hpp>

#include <algorithm>
#include <array>
#include <cctype>
#include <ctime>
#include <fstream>
#include <future>
#include <iostream>
#include <map>
#include <mutex>
#include <stdexcept>
#include <string>
#include <vector>

namespace utils
{

static const boost::regex invalidDBusNameSubString{"[^a-zA-Z0-9._/]+"};
static const uint32_t INVALID_UINT32_VALUE = 0xFFFFFFFF;
uuid_t convertUUIDToString(const std::vector<uint8_t>& uuidIntArr)
{
    if (uuidIntArr.size() != UUID_INT_SIZE)
    {
        lg2::error("UUID Conversion: Failed, integer UUID size is not {UUIDSZ}",
                   "UUIDSZ", UUID_INT_SIZE);
        return "";
    }
    uuid_t uuidStr(UUID_LEN + 1, 0);

    snprintf(
        const_cast<char*>(uuidStr.data()), uuidStr.size(),
        "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
        uuidIntArr[0], uuidIntArr[1], uuidIntArr[2], uuidIntArr[3],
        uuidIntArr[4], uuidIntArr[5], uuidIntArr[6], uuidIntArr[7],
        uuidIntArr[8], uuidIntArr[9], uuidIntArr[10], uuidIntArr[11],
        uuidIntArr[12], uuidIntArr[13], uuidIntArr[14], uuidIntArr[15]);

    return uuidStr;
}

std::string convertHexToString(const std::vector<uint8_t>& data,
                               const size_t dataSize)
{
    std::string result("");
    if (dataSize == 0)
    {
        return result;
    }

    std::vector<uint8_t> nvu8ArrVal(dataSize, 0);
    memcpy(nvu8ArrVal.data(), data.data(), dataSize);

    for (const auto& token : nvu8ArrVal)
    {
        result += std::format("{:02x}", token);
    }
    return result;
}

void printBuffer(bool isTx, const std::vector<uint8_t>& buffer, uint8_t tag,
                 eid_t eid)
{
    if (!buffer.empty())
    {
        // Length of "EID: 1d, TAG: 03, Tx: "
        constexpr size_t headerSize = 22;
        // Length of "89 "
        constexpr size_t hexWithSpaceSize = 3;
        std::string output(headerSize + buffer.size() * hexWithSpaceSize, '\0');
        sprintf(output.data(), "EID: %02x, TAG: %02x, %s: ", eid, tag,
                isTx ? "Tx" : "Rx");
        for (size_t i = 0; i < buffer.size(); i++)
        {
            sprintf(&output[headerSize + i * hexWithSpaceSize], "%02x ",
                    buffer[i]);
        }
        // Changing last trailing space to string null terminator
        output.back() = '\0';
        lg2::info("{OUTPUT}", "OUTPUT", output);
    }
}

bool isValidDbusString(std::string_view input)
{
    const uint8_t* token = std::bit_cast<const uint8_t*>(input.data());
    const uint8_t* end = token + input.size();

    while (token < end)
    {
        uint32_t codepoint = 0;
        int numBytes = 0;

        // utf8 can be up to 4 bytes, check the leading byte to determine its
        // size
        if (*token < 0x80) // 1-byte - ascii
        {
            codepoint = *token;
            numBytes = 1;
        }
        else if ((*token & 0xE0) == 0xC0) // 2-byte
        {
            codepoint = *token & 0x1F;
            numBytes = 2;
        }
        else if ((*token & 0xF0) == 0xE0) // 3-byte
        {
            codepoint = *token & 0x0F;
            numBytes = 3;
        }
        else if ((*token & 0xF8) == 0xF0) // 4-byte
        {
            codepoint = *token & 0x07;
            numBytes = 4;
        }
        else
        {
            // the leading byte is invalid
            return false;
        }

        // check if it's overflow
        if (token + numBytes > end)
            return false;

        // check if the subsequent byte is 10xxxxxx and do OR to codepoint
        for (int i = 1; i < numBytes; ++i)
        {
            if ((token[i] & 0xC0) != 0x80)
            {
                return false;
            }
            codepoint = (codepoint << 6) | (token[i] & 0x3F);
        }

        // check if it's overlong
        if ((numBytes == 2 && codepoint < 0x80) ||
            (numBytes == 3 && codepoint < 0x800) ||
            (numBytes == 4 && codepoint < 0x10000))
        {
            return false;
        }

        // it can't be 0x0000 or higher than 0x10FFFF based on the dbus spec.
        if (codepoint > 0x10FFFF || codepoint == 0x0000)
            return false;

        token += numBytes;
    }

    return true;
}

void printBuffer(bool isTx, const uint8_t* ptr, size_t bufferLen, uint8_t tag,
                 eid_t eid)
{
    auto outBuffer = std::vector<uint8_t>(ptr, ptr + bufferLen);
    printBuffer(isTx, outBuffer, tag, eid);
}

std::vector<std::string> split(std::string_view srcStr, std::string_view delim,
                               std::string_view trimStr)
{
    std::vector<std::string> out;
    size_t start;
    size_t end = 0;

    while ((start = srcStr.find_first_not_of(delim, end)) != std::string::npos)
    {
        end = srcStr.find(delim, start);
        std::string_view dstStr = srcStr.substr(start, end - start);
        if (!trimStr.empty())
        {
            dstStr.remove_prefix(dstStr.find_first_not_of(trimStr));
            dstStr.remove_suffix(dstStr.size() - 1 -
                                 dstStr.find_last_not_of(trimStr));
        }

        if (!dstStr.empty())
        {
            out.push_back(std::string(dstStr));
        }
    }

    return out;
}

std::string getCurrentSystemTime()
{
    using namespace std::chrono;
    const time_point<system_clock> tp = system_clock::now();
    std::time_t tt = system_clock::to_time_t(tp);
    auto ms = duration_cast<microseconds>(tp.time_since_epoch()) -
              duration_cast<seconds>(tp.time_since_epoch());

    std::stringstream ss;
    ss << std::put_time(std::localtime(&tt), "%F %Z %T.")
       << std::to_string(ms.count());
    return ss.str();
}

// assuming <uuid, eid, mctpMedium, mctpBinding> is unique
// assuming we only have a single MCTP network id 0
// its safe to say if we are given a particular eid it will map to a particular
// uuid. A device can have multiple EIDs
std::optional<uuid_t> getUUIDFromEID(
    const std::multimap<std::string,
                        std::tuple<eid_t, MctpMedium, MctpBinding>>& eidTable,
    eid_t eid)
{
    for (const auto& entry : eidTable)
    {
        // Accessing the EID in the tuple
        if (std::get<0>(entry.second) == eid)
        {
            // Returning the UUID as an optional when found
            return entry.first;
        }
    }
    // Returning an empty optional if no UUID is found
    return std::nullopt;
}

uint64_t getCurrentSteadyClockTimestamp()
{
    return std::chrono::duration_cast<std::chrono::milliseconds>(
               std::chrono::steady_clock::now().time_since_epoch())
        .count();
}

eid_t getEidFromUUID(
    const std::multimap<uuid_t, std::tuple<eid_t, MctpMedium, MctpBinding>>&
        eidTable,
    uuid_t uuid)
{
    eid_t eid = std::numeric_limits<uint8_t>::max();
    for (const auto& entry : eidTable)
    {
        // TODO: as of now it is hard-coded for PCIe meidium, will handle in
        // seperate MR for selecting the fasted bandwidth medium instead of hard
        // coded value
        // Assuming UUID_LEN is defined correctly and accessible here
        if (std::string_view(entry.first)
                .starts_with(std::string_view(uuid.data(), UUID_LEN)))
        {
            eid = std::get<0>(
                entry.second); // Accessing the first element (eid) of the tuple
            break;
        }
    }
    return eid;
}

std::string makeDBusNameValid(const std::string& name)
{
    return boost::regex_replace(name, invalidDBusNameSubString, "_");
}

std::vector<Association> getAssociations(const std::string& objPath,
                                         const std::string& interfaceSubStr)
{
    auto mapperResponse = DBusHandler().getServiceMap(objPath.c_str());

    std::vector<Association> associations;

    for (const auto& [service, interfaces] : mapperResponse)
    {
        for (const auto& interface : interfaces)
        {
            if (interface.find(interfaceSubStr) != std::string::npos)
            {
                associations.push_back({});
                auto& association = associations.back();

                association.forward =
                    DBusHandler().getDbusProperty<std::string>(
                        objPath.c_str(), "Forward", interface.c_str());

                association.backward =
                    DBusHandler().getDbusProperty<std::string>(
                        objPath.c_str(), "Backward", interface.c_str());

                association.absolutePath =
                    DBusHandler().getDbusProperty<std::string>(
                        objPath.c_str(), "AbsolutePath", interface.c_str());
                association.absolutePath =
                    makeDBusNameValid(association.absolutePath);
            }
        }
    }

    return associations;
}

Associations getAssociations(const std::vector<Association>& associations)
{
    Associations tuples;
    for (auto& association : associations)
    {
        tuples.emplace_back(association.forward, association.backward,
                            association.absolutePath);
    }
    return tuples;
}

void convertBitMaskToVector(std::vector<uint8_t>& data,
                            const bitfield8_t* value, uint8_t size)
{
    for (uint8_t i = 0; i < size; i++)
    {
        if (value[i].bits.bit0)
        {
            data.push_back((i * 8) + 0);
        }
        if (value[i].bits.bit1)
        {
            data.push_back((i * 8) + 1);
        }
        if (value[i].bits.bit2)
        {
            data.push_back((i * 8) + 2);
        }
        if (value[i].bits.bit3)
        {
            data.push_back((i * 8) + 3);
        }
        if (value[i].bits.bit4)
        {
            data.push_back((i * 8) + 4);
        }
        if (value[i].bits.bit5)
        {
            data.push_back((i * 8) + 5);
        }
        if (value[i].bits.bit6)
        {
            data.push_back((i * 8) + 6);
        }
        if (value[i].bits.bit7)
        {
            data.push_back((i * 8) + 7);
        }
    }
}

std::string getDeviceNameFromDeviceType(const uint8_t deviceType)
{
    switch (deviceType)
    {
        case 0:
            return "GPU";
        case 1:
            return "SWITCH";
        case 2:
            return "BRIDGE";
        case 3:
            return "BASEBOARD";
        case 4:
            return "EROT";
        case 5:
            return "MCTPBRIDGE";
        default:
            return "NSM_DEV_ID_UNKNOWN";
    }
}

std::string getDeviceInstanceName(const uint8_t deviceType,
                                  const uint8_t instanceNumber)
{
    std::string deviceInstanceName = getDeviceNameFromDeviceType(deviceType);
    deviceInstanceName += "_";
    deviceInstanceName += std::to_string(static_cast<int>(instanceNumber));
    return deviceInstanceName;
}

requester::Coroutine coGetAssociations(const std::string& objPath,
                                       const std::string& interfaceSubStr,
                                       std::vector<Association>& associations)
{
    auto mapperResponse = co_await coGetServiceMap(objPath, dbus::Interfaces{});

    for (const auto& [service, interfaces] : mapperResponse)
    {
        for (const auto& interface : interfaces)
        {
            if (interface.find(interfaceSubStr) != std::string::npos)
            {
                associations.push_back({});
                auto& association = associations.back();

                auto allCurrentIfaceProperties = co_await coGetAllDbusProperty(
                    entityManagerServiceStr, objPath.c_str(),
                    interface.c_str());

                std::string forward{};
                if (allCurrentIfaceProperties.count("Forward"))
                {
                    forward = std::get<std::string>(
                        allCurrentIfaceProperties.at("Forward"));
                }
                association.forward = forward;

                std::string backward{};
                if (allCurrentIfaceProperties.count("Backward"))
                {
                    backward = std::get<std::string>(
                        allCurrentIfaceProperties.at("Backward"));
                }
                association.backward = backward;

                std::string absolutePath{};
                if (allCurrentIfaceProperties.count("AbsolutePath"))
                {
                    absolutePath = std::get<std::string>(
                        allCurrentIfaceProperties.at("AbsolutePath"));
                }
                association.absolutePath = absolutePath;
                association.absolutePath =
                    makeDBusNameValid(association.absolutePath);
            }
        }
    }
    // coverity[missing_return]
    co_return NSM_SUCCESS;
}
// Function to convert bitfield256_t to bitmap
std::vector<uint8_t> bitfield256_tToBitMap(bitfield256_t bf)
{
    std::vector<uint8_t> bitmap(32, 0); // 32 bytes = 256 bits

    // Iterate over each bitfield32_t in the bitfield256_t
    for (int i = 0; i < 8; i++)
    {
        uint32_t byte = bf.fields[i].byte;
        // Iterate over each bit in the bitfield32_t
        for (int j = 0; j < 32; j++)
        {
            // If the bit is set, set the corresponding bit in the bitmap
            // i * 4 accounts for the 4 bytes (32 bits) per bitfield32_t
            // element j / 8 determines which byte within the 4 bytes the
            // current bit belongs to.
            if (byte & (1 << j))
            {
                bitmap[i * 4 + j / 8] |= (1 << (j % 8));
            }
        }
    }
    return bitmap;
}

// Function to convert bitfield256_t to bitmap
std::vector<uint8_t> bitfield256_tToBitArray(bitfield256_t bf)
{
    std::vector<uint8_t> bitmap(32, 0); // 32 bytes = 256 bits

    // Iterate over each bitfield32_t in the bitfield256_t
    for (int i = 0; i < 8; i++)
    {
        uint32_t byte = bf.fields[i].byte;
        bitmap[i * 4 + 0] = (byte >> 24) & 0xFF;
        bitmap[i * 4 + 1] = (byte >> 16) & 0xFF;
        bitmap[i * 4 + 2] = (byte >> 8) & 0xFF;
        bitmap[i * 4 + 3] = (byte >> 0) & 0xFF;
    }
    return bitmap;
}

std::pair<std::vector<uint8_t>, std::vector<uint8_t>>
    bitmapToIndices(const std::vector<uint8_t>& bitmap)
{
    std::vector<uint8_t> zeroIndices, oneIndices;
    uint8_t index = 0;
    for (auto byte : bitmap)
    {
        for (auto bit = 0; bit < 8; ++bit)
        {
            if (byte & 0x01)
            {
                oneIndices.emplace_back(index++);
            }
            else
            {
                zeroIndices.emplace_back(index++);
            }
            byte >>= 1;
        }
    }

    return std::make_pair(zeroIndices, oneIndices);
}

std::vector<uint8_t> indicesToBitmap(const std::vector<uint8_t>& indices,
                                     const size_t size)
{
    constexpr const size_t maxBitmapSize = 8; // maximum size used by ERoT
    if (size > maxBitmapSize)
    {
        throw std::invalid_argument(
            "Requested bitmap size larger than maximum allowed value");
    }
    if (indices.empty())
    {
        return std::vector<uint8_t>(size, 0);
    }
    uint8_t maxIndex = *std::max_element(indices.begin(), indices.end());
    std::vector<uint8_t> bitmap;
    if (size == 0)
    {
        bitmap.resize(maxIndex / 8 + 1, 0);
    }
    else if (maxIndex > size * 8 - 1)
    {
        throw std::invalid_argument("Index out of bounds for specified size");
    }
    else
    {
        bitmap.resize(size, 0);
    }
    for (auto& index : indices)
    {
        size_t bitmapIndex = index / 8;
        size_t bitmapBit = index % 8;
        bitmap[bitmapIndex] |= 1 << bitmapBit;
    }

    return bitmap;
}

Bitfield256::Bitfield256()
{
    clear();
}
bool Bitfield256::setBit(const uint8_t& bitNumber)
{
    uint8_t fieldIndex = bitNumber / 32;
    uint8_t bitIndex = bitNumber % 32;
    uint32_t& byte = fields[fieldIndex].byte;
    bool wasSet = byte & (1 << bitIndex);
    byte |= (1 << bitIndex);
    return !wasSet;
}

bool Bitfield256::isAnyBitSet() const
{
    return std::any_of(std::begin(fields), std::end(fields),
                       [](const auto& field) { return field.byte != 0; });
}

std::string Bitfield256::getSetBits() const
{
    std::ostringstream oss;

    for (size_t i = 0; i < 8; ++i)
    {
        uint32_t byte = fields[i].byte;

        while (byte > 0)
        {
            // Get the position of the least significant set bit
            int position = __builtin_ctz(byte);
            oss << (i * 32 + position) << ", ";

            // Remove the least significant set bit
            byte &= (byte - 1);
        }
    }

    std::string result = oss.str();
    if (!result.empty())
    {
        result.erase(result.size() - 2); // Remove trailing ", "
    }

    return result;
}
void Bitfield256::clear()
{
    memset(fields, 0, sizeof(fields));
}

std::vector<sdbusplus::common::xyz::openbmc_project::software::SecurityCommon::
                UpdateMethods>
    updateMethodsBitfieldToList(bitfield32_t updateMethodBitfield)
{
    using namespace sdbusplus::common::xyz::openbmc_project::software;

    std::vector<SecurityCommon::UpdateMethods> updateMethods;
    if (updateMethodBitfield.bits.bit0)
    {
        updateMethods.emplace_back(SecurityCommon::UpdateMethods::Automatic);
    }
    if (updateMethodBitfield.bits.bit2)
    {
        updateMethods.emplace_back(
            SecurityCommon::UpdateMethods::MediumSpecificReset);
    }
    if (updateMethodBitfield.bits.bit3)
    {
        updateMethods.emplace_back(SecurityCommon::UpdateMethods::SystemReboot);
    }
    if (updateMethodBitfield.bits.bit4)
    {
        updateMethods.emplace_back(SecurityCommon::UpdateMethods::DCPowerCycle);
    }
    if (updateMethodBitfield.bits.bit5)
    {
        updateMethods.emplace_back(SecurityCommon::UpdateMethods::ACPowerCycle);
    }
    if (updateMethodBitfield.bits.bit16)
    {
        updateMethods.emplace_back(SecurityCommon::UpdateMethods::WarmReset);
    }
    if (updateMethodBitfield.bits.bit17)
    {
        updateMethods.emplace_back(SecurityCommon::UpdateMethods::HotReset);
    }
    if (updateMethodBitfield.bits.bit18)
    {
        updateMethods.emplace_back(SecurityCommon::UpdateMethods::FLR);
    }

    return updateMethods;
}
// Function to convert bitmap to bitfield256_t
bitfield256_t bitMapToBitfield256_t(const std::vector<uint8_t>& bitmap)
{
    bitfield256_t bf = {0}; // Initialize all fields to 0

    // Ensure the bitmap has the correct size
    if (bitmap.size() != 32)
    {
        return bf;
    }

    // Iterate over each group of 4 bytes in the bitmap
    for (int i = 0; i < 8; i++)
    {
        uint32_t byte = 0;
        byte |= static_cast<uint32_t>(bitmap[i * 4 + 0]) << 24;
        byte |= static_cast<uint32_t>(bitmap[i * 4 + 1]) << 16;
        byte |= static_cast<uint32_t>(bitmap[i * 4 + 2]) << 8;
        byte |= static_cast<uint32_t>(bitmap[i * 4 + 3]);
        bf.fields[i].byte = byte;
    }

    return bf;
}

std::string vectorTo256BitHexString(const std::vector<uint8_t>& value)
{
    // Ensure the vector has exactly 32 bytes (256 bits)
    if (value.size() != 32)
    {
        return "0x" + std::string(64, '0');
    }

    // Convert the vector to a hex string
    std::stringstream ss;
    ss << "0x";
    for (const auto& byte : value)
    {
        ss << std::hex << std::setw(2) << std::setfill('0')
           << static_cast<int>(byte);
    }
    return ss.str();
}

void readFdToBuffer(int fd, std::vector<uint8_t>& buffer)
{
    if (fd < 0)
    {
        throw std::runtime_error("readFdToBuffer - Invalid file descriptor");
    }
    if (lseek(fd, 0, SEEK_SET) < 0)
    {
        throw std::runtime_error("readFdToBuffer - lseek failed");
    }
    struct stat fileStat;
    if (fstat(fd, &fileStat) < 0)
    {
        throw std::runtime_error("readFdToBuffer - fstat failed" +
                                 std::string(strerror(errno)));
    }
    if (fileStat.st_size < 0)
    {
        throw std::runtime_error("readFdToBuffer - Invalid file size in fd");
    }
    buffer.resize(fileStat.st_size);
    ssize_t bytesRead = read(fd, buffer.data(), buffer.size());
    if (bytesRead < 0)
    {
        throw std::runtime_error("readFdToBuffer - Fd read failed" +
                                 std::string(strerror(errno)));
    }
    else if (static_cast<size_t>(bytesRead) != buffer.size())
    {
        throw std::runtime_error(
            "readFdToBuffer - Read fewer bytes than expected");
    }
}

void writeBufferToFd(int fd, const std::vector<uint8_t>& buffer)
{
    if (fd < 0)
    {
        throw std::runtime_error("writeBufferToFd - Invalid file descriptor");
    }
    if (lseek(fd, 0, SEEK_SET) < 0)
    {
        throw std::runtime_error("writeBufferToFd - lseek failed");
    }
    size_t totalBytesWritten = 0;
    while (totalBytesWritten < buffer.size())
    {
        ssize_t bytesWritten = write(fd, buffer.data() + totalBytesWritten,
                                     buffer.size() - totalBytesWritten);
        if (bytesWritten < 0)
        {
            throw std::runtime_error("writeBufferToFd - write failed: " +
                                     std::string(strerror(errno)));
        }
        totalBytesWritten += bytesWritten;
    }
    if (ftruncate(fd, buffer.size()) < 0)
    {
        throw std::runtime_error("writeBufferToFd - ftruncate failed: " +
                                 std::string(strerror(errno)));
    }
}

void appendBufferToFd(int fd, const std::vector<uint8_t>& buffer)
{
    if (fd < 0)
    {
        throw std::runtime_error("appendBufferToFd - Invalid file descriptor");
    }
    size_t totalBytesWritten = 0;
    while (totalBytesWritten < buffer.size())
    {
        ssize_t bytesWritten = write(fd, buffer.data() + totalBytesWritten,
                                     buffer.size() - totalBytesWritten);
        if (bytesWritten < 0)
        {
            throw std::runtime_error("appendBufferToFd - write failed: " +
                                     std::string(strerror(errno)));
        }
        totalBytesWritten += bytesWritten;
    }
}

std::string requestMsgToHexString(std::vector<uint8_t>& requestMsg)
{
    std::ostringstream oss;
    for (const auto& byte : requestMsg)
    {
        oss << std::setfill('0') << std::setw(2) << std::hex
            << static_cast<int>(byte) << " ";
    }
    return oss.str();
}

double convertAndScaleDownUint32ToDouble(uint32_t value, double scaleFactor)
{
    if (value == INVALID_UINT32_VALUE)
    {
        return static_cast<double>(INVALID_UINT32_VALUE);
    }
    else
    {
        return static_cast<double>(value) / scaleFactor;
    }
}

double uint64ToDoubleSafeConvert(uint64_t value)
{
    if (value > MAX_SAFE_INTEGER_IN_DOUBLE)
    {
        lg2::error(
            "Warning: Uint64 Value ({VAL}) exceeds safe range for double precision. Capping to maximum safe value.",
            "VAL", value);
        return static_cast<double>(MAX_SAFE_INTEGER_IN_DOUBLE);
    }
    return static_cast<double>(value);
}

double int64ToDoubleSafeConvert(int64_t value)
{
    if (value < 0)
    {
        if (static_cast<uint64_t>(-value) > MAX_SAFE_INTEGER_IN_DOUBLE)
        {
            lg2::error(
                "Warning: Int64 Value ({VAL}) exceeds safe range for double precision. Capping to maximum safe value.",
                "VAL", value);
            return static_cast<double>(-MAX_SAFE_INTEGER_IN_DOUBLE);
        }
    }
    else
    {
        if (static_cast<uint64_t>(value) > MAX_SAFE_INTEGER_IN_DOUBLE)
        {
            lg2::error(
                "Warning: Int64 Value ({VAL}) exceeds safe range for double precision. Capping to maximum safe value.",
                "VAL", value);
            return static_cast<double>(MAX_SAFE_INTEGER_IN_DOUBLE);
        }
    }

    return static_cast<double>(value);
}

uint16_t combineDeviceTypeAndRole(uint8_t deviceType, uint8_t deviceRole)
{
    return (uint16_t)((deviceRole << 8) |
                      deviceType); // Role in high byte, Type in low byte
}

void getDeviceTypeAndRole(uint16_t combined, uint8_t* deviceType,
                          uint8_t* deviceRole)
{
    *deviceType = (uint8_t)(combined & 0xFF); // Type is in low byte
    *deviceRole = (uint8_t)(combined >> 8);   // Role is in high byte
}

void convertMacAddressToString(const uint8_t* macAddress,
                               size_t macAddressDataLen,
                               std::string& macAddressString)
{
    const static size_t MAC_FORMAT_LENGTH = sizeof("XX:XX:XX:XX:XX:XX");
    if (macAddressDataLen < MAC_ADDRESS_DATA_LEN)
    {
        lg2::error(
            "convertMacAddressToString - Invalid mac address data length: {LEN}",
            "LEN", macAddressDataLen);
        macAddressString.clear();
        return;
    }
    char buffer[MAC_FORMAT_LENGTH];
    snprintf(buffer, MAC_FORMAT_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
             macAddress[0], macAddress[1], macAddress[2], macAddress[3],
             macAddress[4], macAddress[5]);
    macAddressString = buffer;
}

void convertGuid64ToString(uint64_t guid, std::string& guidString)
{
    guidString = std::format("{:04X}-{:04X}-{:04X}-{:04X}",
                             (guid >> 48) & 0xFFFF, (guid >> 32) & 0xFFFF,
                             (guid >> 16) & 0xFFFF, guid & 0xFFFF);
}
// Single-flight pattern implementation for single-threaded async execution
// for EM configuration PDI properties
requester::Coroutine coGetCachedBaseProperties(
    [[maybe_unused]] const std::string& objPath,
    [[maybe_unused]] const std::string& baseInterface,
    [[maybe_unused]] dbus::PropertyMap& cachedProperties)
{
#ifndef MOCK_DBUS_ASYNC_UTILS
    static std::unordered_map<
        std::string, std::unordered_map<std::string, dbus::PropertyMap>>
        basePropertiesCache;

    static std::unordered_map<
        std::string,
        std::unordered_map<std::string, std::shared_future<dbus::PropertyMap>>>
        pendingRequests;

    // Check if already cached
    auto objPathIt = basePropertiesCache.find(objPath);
    if (objPathIt != basePropertiesCache.end())
    {
        auto interfaceIt = objPathIt->second.find(baseInterface);
        if (interfaceIt != objPathIt->second.end())
        {
            // "Cache hit: Using cached base properties for
            // {OBJPATH}:{INTERFACE}", "OBJPATH", objPath, "INTERFACE",
            // baseInterface);
            cachedProperties = interfaceIt->second;
            co_return NSM_SUCCESS;
        }
    }

    // Check if request is already pending
    auto pendingObjIt = pendingRequests.find(objPath);
    if (pendingObjIt != pendingRequests.end())
    {
        auto pendingInterfaceIt = pendingObjIt->second.find(baseInterface);
        if (pendingInterfaceIt != pendingObjIt->second.end())
        {
            //     "Request pending: Waiting for ongoing request for
            //     {OBJPATH}:{INTERFACE}", "OBJPATH", objPath, "INTERFACE",
            //     baseInterface);

            try
            {
                dbus::PropertyMap result = pendingInterfaceIt->second.get();
                cachedProperties = result;
                co_return NSM_SUCCESS;
            }
            catch (...)
            {
                // If the future threw an exception, we'll try making our own
                // request Continue to the request creation logic below
            }
        }
    }

    // Create a promise for this request
    std::promise<dbus::PropertyMap> promise;
    std::shared_future<dbus::PropertyMap> future = promise.get_future().share();

    // Store the pending request
    pendingRequests[objPath][baseInterface] = future;

    // "Cache miss: First retrieval for {OBJPATH}:{INTERFACE}",
    // "OBJPATH", objPath, "INTERFACE", baseInterface);

    try
    {
        // Make the actual D-Bus call
        dbus::PropertyMap properties = co_await utils::coGetAllDbusProperty(
            utils::entityManagerServiceStr, objPath, baseInterface);

        // Cache the result and clean up pending request
        basePropertiesCache[objPath][baseInterface] = properties;

        // Remove from pending requests
        auto pendingObjIt = pendingRequests.find(objPath);
        if (pendingObjIt != pendingRequests.end())
        {
            pendingObjIt->second.erase(baseInterface);
            if (pendingObjIt->second.empty())
            {
                pendingRequests.erase(objPath);
            }
        }

        // Set the promise result
        promise.set_value(properties);

        cachedProperties = properties;
        co_return NSM_SUCCESS;
    }
    catch (const std::exception& e)
    {
        // Clean up pending request on error
        auto pendingObjIt = pendingRequests.find(objPath);
        if (pendingObjIt != pendingRequests.end())
        {
            pendingObjIt->second.erase(baseInterface);
            if (pendingObjIt->second.empty())
            {
                pendingRequests.erase(objPath);
            }
        }

        // Set the promise exception
        promise.set_exception(std::current_exception());

        lg2::error(
            "Failed to fetch base properties for {OBJPATH}:{INTERFACE}:{ERROR}",
            "OBJPATH", objPath, "INTERFACE", baseInterface, "ERROR", e.what());

        co_return NSM_SW_ERROR;
    }
#else
    // In test mode, just copy the current propertyMap
    auto& propertyMap = utils::MockDbusAsync::getPropertyMap();
    cachedProperties = propertyMap;
    co_return NSM_SUCCESS;
#endif
}

int parseStaticUuid(uuid_t& uuid, uint8_t& deviceType, uint8_t& instanceNumber,
                    uint8_t& deviceRole, std::string& remapPropName,
                    std::string& remapPropValue)
{
    int n1 = -1;
    int n2 = -1;
    char propName[128] = {0};
    char propValue[128] = {0};

    // Use sscanf with width specifiers to avoid buffer overflow
    int numParsed = std::sscanf(uuid.c_str(), "STATIC:%d:%d:%127[^:]:%127s",
                                &n1, &n2, propName, propValue);
    if (numParsed != 4)
    {
        return -3; // Parsing failed
    }

    if (n1 < 0 || n1 > 0xffff)
    {
        return -1;
    }
    if (n2 < 0 || n2 > 0xff)
    {
        return -2;
    }

    utils::getDeviceTypeAndRole(n1, &deviceType, &deviceRole);
    instanceNumber = static_cast<uint8_t>(n2);
    remapPropName = std::string(propName);
    remapPropValue = std::string(propValue);
    return 0;
}

} // namespace utils
