extern "C"
{
#include <i2c/smbus.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
}
#include "include/common_utility.hpp"

namespace util
{

std::vector<fs::path> findFiles(const fs::path& dirPath,
                                const std::string& matchString)
{
    std::vector<fs::path> foundPaths;
    if (!fs::exists(dirPath))
    {
        lg2::error("Directory {PATH} does not exist", "PATH", dirPath);
        return foundPaths;
    }

    std::regex search(matchString);
    std::smatch match;
    for (const auto& p : fs::directory_iterator(dirPath))
    {
        std::string path = p.path().string();
        if (std::regex_search(path, match, search))
        {
            foundPaths.emplace_back(p.path());
        }
    }
    if (foundPaths.empty())
    {
        lg2::error("No file found in {PATH} with {STRING}", "PATH", dirPath,
                   "STRING", matchString);
    }

    return foundPaths;
}

bool checkPartNumber(std::string_view fileName, const json& configuration)
{
    auto [boardName,
          partNumberPrefixes] = getBoardAndPartNumberPrefixes(configuration);
    if (boardName.empty() || partNumberPrefixes.empty())
    {
        lg2::error("Board or PartNumberPrefix is empty in {NAME}", "NAME",
                   fileName);
        return false;
    }

    const std::string fruService = "xyz.openbmc_project.FruDevice";
    const std::string fruObject = "/xyz/openbmc_project/FruDevice/" + boardName;
    const std::string fruInterface = "xyz.openbmc_project.FruDevice";
    const std::string property = "BOARD_PART_NUMBER";

    auto [success, value] = getProperty(fruService, fruObject, fruInterface,
                                        property);
    if (!success)
    {
        lg2::info("{FILENAME} PartNumber is not available", "FILENAME",
                  fileName);
        return false;
    }

    const auto* strVal = std::get_if<std::string>(&value);
    if (strVal != nullptr)
    {
        const std::string dbusPartNumberPrefix = strVal->substr(0, 7);
        auto it = std::find(partNumberPrefixes.begin(),
                            partNumberPrefixes.end(), dbusPartNumberPrefix);
        if (it == partNumberPrefixes.end())
        {
            lg2::error("{FILENAME} PartNumberPrefix is not match", "FILENAME",
                       fileName);
            return false;
        }
    }
    else
    {
        lg2::error("{FILENAME} PartNumber is not a string", "FILENAME",
                   fileName);
    }

    std::vector<std::string> properties = {
        "BOARD_INFO_AM1",   "BOARD_INFO_AM2",   "BOARD_INFO_AM3",
        "PRODUCT_INFO_AM1", "PRODUCT_INFO_AM2", "PRODUCT_INFO_AM3"};
    for (const auto& property : properties)
    {
        if (configuration.contains(property))
        {
            std::string jsonValue = configuration[property];
            auto [success, dbusValue] = getProperty(fruService, fruObject,
                                                    fruInterface, property);
            if (!success)
            {
                continue;
            }
            auto* strVal = std::get_if<std::string>(&dbusValue);
            if (strVal != nullptr)
            {
                std::string dbusProperty = strVal->substr();
                if (jsonValue != dbusProperty)
                {
                    lg2::error("{PROPERTY} does not match", "PROPERTY",
                               property);
                    return false;
                }
            }
            else
            {
                lg2::error("{FILENAME} {PROPERTY} is not a string", "FILENAME",
                           fileName, "PROPERTY", property);
                return false;
            }
        }
    }

    lg2::info("Vr config Added: {FILENAME}", "FILENAME", fileName);
    return true;
}

std::string getBoodID()
{
    const std::string bootIdPath = "/proc/sys/kernel/random/boot_id";
    std::ifstream bootIdFile(bootIdPath);

    if (!bootIdFile.is_open())
    {
        lg2::error("Unable to open boot_id file");
        return "";
    }

    std::string bootId;
    std::getline(bootIdFile, bootId);

    bootIdFile.close();

    lg2::info("Boot ID: {ID}", "ID", bootId);

    return bootId;
}

void summarizeLog(DbusUtil* dbusUtil, std::string_view msg,
                  const fs::path& logDirPath, const std::string_view filename)
{
    std::time_t currentTime =
        std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());

    const std::string kCurrentBoot = "currentBoot";
    const std::string kPreviousBoot = "previousBoot";
    const std::string kBootIdFile = "boot_id.log";

    const fs::path logDirPathCurrent = logDirPath / kCurrentBoot;
    const fs::path logDirPathPrevious = logDirPath / kPreviousBoot;

    if (!fs::exists(logDirPathCurrent))
    {
        fs::create_directories(logDirPathCurrent);
        std::ofstream ofsCurrent(logDirPathCurrent / kBootIdFile);
        ofsCurrent << getBoodID();
        ofsCurrent.close();
    }
    else
    {
        std::ifstream ifsCurrent(logDirPathCurrent / kBootIdFile);
        std::string bootIdCurrent;
        ifsCurrent >> bootIdCurrent;
        ifsCurrent.close();

        std::string bootId = getBoodID();
        if (bootIdCurrent != bootId)
        {
            fs::remove_all(logDirPathPrevious);
            fs::rename(logDirPathCurrent, logDirPathPrevious);

            fs::create_directories(logDirPathCurrent);
            std::ofstream ofsCurrent(logDirPathCurrent / kBootIdFile);
            ofsCurrent << bootId;
            ofsCurrent.close();
        }
    }

    size_t fileCount = 0;
    for (const auto& entry : fs::directory_iterator(logDirPathCurrent))
    {
        if (entry.is_regular_file() &&
            entry.path().filename().string().starts_with(filename))
        {
            fileCount++;
        }
    }

    if (fileCount > 100)
    {
        return;
    }

    std::string filenameStr = std::string(filename) + "_" +
                              std::to_string(fileCount);

    fs::path logFilePath = logDirPathCurrent / filenameStr;

    std::ofstream ofs(logFilePath, std::ios::binary | std::ios::app);
    if (!ofs.is_open())
    {
        lg2::error("Error: Unable to open file.");
        return;
    }

    ofs.seekp(0, std::ios::end);
    uint64_t fileSize = ofs.tellp();
    uint64_t msgSize =
        msg.size() +
        25; // 25 for timestamp length: "Www Mmm dd hh:mm:ss yyyy\n"

    std::string now = std::ctime(&currentTime);
    std::replace(now.begin(), now.end(), '\n', ':');

    if (msgSize > kMaxLogSize)
    {
        std::string_view truncatedMsg = msg.substr(0, kMaxLogSize - 25);

        ofs.close();
        ofs.open(logFilePath, std::ios::binary | std::ios::trunc);
        ofs << now << "\n" << truncatedMsg << '\n';
    }
    else
    {
        if (fileSize + msgSize > kMaxLogSize)
        {
            ofs.close();

            uint64_t bytesToKeep = kMaxLogSize - msgSize;

            if (bytesToKeep > fileSize)
            {
                bytesToKeep = fileSize;
            }

            std::ifstream ifs(logFilePath, std::ios::binary);
            ifs.seekg(static_cast<int64_t>(fileSize - bytesToKeep),
                      std::ios::beg);
            std::vector<char> buffer(bytesToKeep);
            ifs.read(buffer.data(), static_cast<int64_t>(buffer.size()));
            ifs.close();

            ofs.open(logFilePath, std::ios::binary | std::ios::trunc);
            ofs.write(buffer.data(), static_cast<int64_t>(buffer.size()));
        }

        ofs << now << "\n" << msg << '\n';
    }

    ofs.close();

    lg2::info("{TIME}", "TIME", now);
    lg2::info("{MSG}", "MSG", msg);
    lg2::info("Stored log file: {FILE}", "FILE", logFilePath);
    std::cerr << logFilePath << "<logFilePath\n";

    dbusUtil->dbusAddStoredLog(filenameStr);
}

std::pair<bool, PropertyValue> getProperty(const std::string& serviceName,
                                           const std::string& objectPath,
                                           const std::string& interface,
                                           const std::string& propertyName)
{
    try
    {
        auto bus = sdbusplus::bus::new_default();
        auto method =
            bus.new_method_call(serviceName.c_str(), objectPath.c_str(),
                                "org.freedesktop.DBus.Properties", "Get");
        method.append(interface, propertyName);
        auto reply = bus.call(method);
        PropertyValue value;
        reply.read(value);
        return {true, value};
    }
    catch (const sdbusplus::exception_t& e)
    {
        lg2::error("Unable to get property: {ERR}", "ERR", e);
        return {false, {}};
    }
}

int i2cOpenDevice(const uint16_t bus, const uint16_t address)
{
    std::string i2cDev = "/dev/i2c-" + std::to_string(bus);
    int fd = open(i2cDev.c_str(), O_RDWR);
    if (fd < 0)
    {
        lg2::error("Unable to open i2c device.");
        return -1;
    }
    if (ioctl(fd, I2C_SLAVE_FORCE, address) < 0)
    {
        close(fd);
        lg2::error("Unable to set i2c slave address.");
        return -1;
    }
    return fd;
}

void i2cWriteByte(const uint8_t bus, const uint8_t address,
                  const uint8_t command, const uint8_t value)
{
    int fd = i2cOpenDevice(bus, address);
    if (fd < 0)
    {
        lg2::error("i2cWriteByte failed");
        return;
    }

    i2c_smbus_write_byte_data(fd, command, value);
    close(fd);
}

std::vector<uint8_t> i2cWriteRead(const uint8_t bus, const uint8_t address,
                                  const std::vector<uint8_t>& writeBuf,
                                  const uint16_t writeLen,
                                  const uint16_t recvLen)
{
    std::vector<uint8_t> recvData;

    int fd = i2cOpenDevice(bus, address);
    if (fd < 0)
    {
        lg2::error("i2cWriteRead failed");
        close(fd);
        return {};
    }

    struct i2c_rdwr_ioctl_data data
    {};
    // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
    struct i2c_msg messages[2];

    messages[0].addr = address;
    messages[0].flags = 0;
    messages[0].len = writeLen;
    messages[0].buf = const_cast<uint8_t*>(writeBuf.data()); // NOLINT

    recvData.resize(recvLen);
    messages[1].addr = address;
    messages[1].flags = I2C_M_RD;
    messages[1].len = recvLen;
    messages[1].buf = recvData.data();

    data.msgs = static_cast<i2c_msg*>(messages);
    data.nmsgs = 2;

    if (ioctl(fd, I2C_RDWR, &data) < 0)
    {
        lg2::error("Unable to write and read data from i2c device.");
    }
    close(fd);

    return recvData;
}

std::uint8_t i2cReadByte(const uint8_t bus, const uint8_t address,
                         const uint8_t reg)
{
    int fd = i2cOpenDevice(bus, address);
    if (fd < 0)
    {
        lg2::error("i2cReadByte failed");
        return 0;
    }

    uint8_t value = 0;
    uint8_t buf = reg;
    struct i2c_rdwr_ioctl_data data
    {};
    // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
    struct i2c_msg messages[2];

    messages[0].addr = address;
    messages[0].flags = 0;
    messages[0].len = 1;
    messages[0].buf = &buf;

    messages[1].addr = address;
    messages[1].flags = I2C_M_RD;
    messages[1].len = 1;
    messages[1].buf = &value;

    data.msgs = static_cast<i2c_msg*>(messages);
    data.nmsgs = 2;

    if (ioctl(fd, I2C_RDWR, &data) < 0)
    {
        lg2::error("Unable to read byte from i2c device.");
    }
    close(fd);
    return 0;
}

std::vector<uint8_t> i2cReadBytes(const uint8_t bus, const uint8_t address,
                                  const uint8_t reg, const uint16_t length)
{
    int fd = i2cOpenDevice(bus, address);
    if (fd < 0)
    {
        lg2::error("i2cReadBytes failed");
        return {};
    }

    std::vector<uint8_t> buffer(length);
    uint8_t buf = reg;
    struct i2c_rdwr_ioctl_data data
    {};
    // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
    struct i2c_msg messages[2];

    messages[0].addr = address;
    messages[0].flags = 0;
    messages[0].len = 1;
    messages[0].buf = &buf;

    messages[1].addr = address;
    messages[1].flags = I2C_M_RD;
    messages[1].len = length;
    messages[1].buf = buffer.data();

    data.msgs = static_cast<i2c_msg*>(messages);
    data.nmsgs = 2;

    if (ioctl(fd, I2C_RDWR, &data) < 0)
    {
        lg2::error("Unable to read bytes from i2c device.");
    }
    close(fd);
    return {};
}

double convertFromLinear(const uint16_t value)
{
    uint8_t exponentField = value >> 11;
    uint16_t mantissaField = value & 0x7FFU;
    bool negativeExp = exponentField > 0x0FU;
    if (negativeExp)
    {
        exponentField = 32 - exponentField;
    }
    if (mantissaField > 0x03FFU)
    {
        mantissaField = 2048 - mantissaField;
    }

    int8_t exponent = static_cast<int8_t>(exponentField);
    int16_t mantissa = static_cast<int16_t>(mantissaField);
    return negativeExp ? mantissa / std::pow(2.0, exponent)
                       : mantissa * std::pow(2.0, exponent);
}

double convertFromVoutLinear(const uint16_t value, const int8_t exponent)
{
    return value * std::pow(2.0, exponent);
}

double convertFromDirect(const uint16_t value, const int16_t m, const int16_t b,
                         const int8_t r)
{
    if (m == 0)
    {
        lg2::error("Error: Divided by zero");
        return 0;
    }
    return (value * std::pow(10.0, -r) - b) / m;
}

uint16_t parseDec(const json& element)
{
    if (!element.is_string())
    {
        lg2::error("Element is not a string");
        return 0;
    }
    std::string value = element.get<std::string>();
    std::regex decimalRegex("^-?[0-9]+$");
    if (!std::regex_match(value, decimalRegex))
    {
        lg2::error("Element is not decimal string");
        return 0;
    }
    return static_cast<uint16_t>(std::stoul(value, nullptr, 0));
}

std::vector<uint8_t> parseHexByteArray(const json& element)
{
    if (!element.is_array())
    {
        return {};
    }

    std::vector<uint8_t> values;
    for (const auto& valueElement : element)
    {
        values.emplace_back(parseHexByte(valueElement));
    }
    return values;
}

uint8_t parseHexByte(const json& element)
{
    if (!element.is_string())
    {
        lg2::error("Element is not a string");
        return 0;
    }
    std::string value = element.get<std::string>();
    std::regex hexPattern("^0x[0-9a-fA-F]{1,3}$");
    if (!std::regex_match(value, hexPattern))
    {
        lg2::error("Element is not hexadecimal string");
        return 0;
    }
    return static_cast<uint8_t>(std::stoul(value, nullptr, 16));
}

uint16_t bytesIntoWord(std::string_view upperByte, std::string_view lowerByte)
{
    return (parseHexByte(upperByte) << 8) | parseHexByte(lowerByte);
}

std::string byteArrayToHexString(uint8_t* buf, const uint16_t len)
{
    std::stringstream result;
    for (uint16_t i = 0; i < len; ++i)
    {
        result << "0x" << std::setw(2) << std::setfill('0') << std::hex
               << static_cast<int>(buf[i]) << std::dec << " "; // NOLINT
    }
    return result.str();
}

std::string getCurrentTimestamp()
{
    std::time_t currentTime =
        std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    std::tm* gmTime = std::gmtime(&currentTime);
    gmTime->tm_hour -= 8;
    std::mktime(gmTime);
    std::ostringstream oss;
    oss << std::put_time(gmTime, "%Y-%m-%d %H:%M:%S");
    return oss.str();
}

} // namespace util
