#include "create_pel.hpp"

#include "dump_utils.hpp"
#include "sbe_consts.hpp"

#include <fcntl.h>
#include <libekb.H>
#include <unistd.h>

#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/lg2.hpp>
#include <xyz/openbmc_project/Logging/Create/server.hpp>
#include <xyz/openbmc_project/Logging/Entry/server.hpp>

#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <format>
#include <map>
#include <stdexcept>
#include <string>
#include <tuple>
#include <vector>

namespace openpower::dump::pel
{

using namespace phosphor::logging;
using namespace openpower::dump::SBE;
constexpr auto loggingObjectPath = "/xyz/openbmc_project/logging";
constexpr auto loggingInterface = "xyz.openbmc_project.Logging.Create";
constexpr auto opLoggingInterface = "org.open_power.Logging.PEL";

uint32_t createSbeErrorPEL(const std::string& event, const sbeError_t& sbeError,
                           const FFDCData& ffdcData, const Severity severity,
                           const std::optional<PELFFDCInfo>& pelFFDCInfoOpt)
{
    uint32_t plid = 0;
    std::unordered_map<std::string, std::string> additionalData = {
        {"_PID", std::to_string(getpid())}, {"SBE_ERR_MSG", sbeError.what()}};
    auto bus = sdbusplus::bus::new_default();

    additionalData.emplace("_PID", std::to_string(getpid()));
    additionalData.emplace("SBE_ERR_MSG", sbeError.what());

    for (auto& data : ffdcData)
    {
        additionalData.emplace(data);
    }

    PELFFDCInfo pelFFDCInfo;
    if (pelFFDCInfoOpt)
    {
        pelFFDCInfo = *pelFFDCInfoOpt;
    }

    // Negative fd value indicates error case or invalid file
    // No need of special processing , just log error with additional ffdc.
    else if (sbeError.getFd() > 0)
    {
        // Refer phosphor-logging/extensions/openpower-pels/README.md section
        // "Self Boot Engine(SBE) First Failure Data Capture(FFDC) Support"
        // for details of related to createPEL with SBE FFDC information
        // using CreateWithFFDCFiles api.
        pelFFDCInfo.emplace_back(std::make_tuple(
            sdbusplus::xyz::openbmc_project::Logging::server::Create::
                FFDCFormat::Custom,
            FFDC_FORMAT_SUBTYPE, FFDC_FORMAT_VERSION, sbeError.getFd()));
    }
    try
    {
        auto service = util::getService(bus, opLoggingInterface,
                                        loggingObjectPath);
        auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
                                          opLoggingInterface,
                                          "CreatePELWithFFDCFiles");
        auto level =
            sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
                severity);
        method.append(event, level, additionalData, pelFFDCInfo);
        auto response = bus.call(method);

        // reply will be tuple containing bmc log id, platform log id
        std::tuple<uint32_t, uint32_t> reply = {0, 0};

        // parse dbus response into reply
        response.read(reply);
        plid = std::get<1>(reply); // platform log id is tuple "second"
    }
    catch (const sdbusplus::exception_t& e)
    {
        lg2::error(
            "D-Bus call exception OBJPATH={OBJPATH}, INTERFACE={INTERFACE}, "
            "EXCEPTION={ERROR}",
            "OBJPATH", loggingObjectPath, "INTERFACE", loggingInterface,
            "ERROR", e);

        throw;
    }
    catch (const std::exception& e)
    {
        throw;
    }

    return plid;
}

openpower::dump::pel::Severity convertSeverityToEnum(uint8_t severity)
{
    switch (severity)
    {
        case openpower::phal::FAPI2_ERRL_SEV_RECOVERED:
            return openpower::dump::pel::Severity::Informational;
        case openpower::phal::FAPI2_ERRL_SEV_PREDICTIVE:
            return openpower::dump::pel::Severity::Warning;
        case openpower::phal::FAPI2_ERRL_SEV_UNRECOVERABLE:
            return openpower::dump::pel::Severity::Error;
        default:
            return openpower::dump::pel::Severity::Error;
    }
}

void processFFDCPackets(const openpower::phal::sbeError_t& sbeError,
                        const std::string& event,
                        openpower::dump::pel::FFDCData& pelAdditionalData)
{
    const auto& ffdcFileList = sbeError.getFfdcFileList();
    for (const auto& [slid, ffdcTuple] : ffdcFileList)
    {
        uint8_t severity;
        int fd;
        std::filesystem::path path;
        std::tie(severity, fd, path) = ffdcTuple;

        Severity logSeverity = convertSeverityToEnum(severity);

        if (logSeverity != openpower::dump::pel::Severity::Informational)
        {
            lg2::info(
                "Changing severity from {SEV_ORIG} to informational in the "
                "dumping path",
                "SEV_ORIG", logSeverity);
            logSeverity = openpower::dump::pel::Severity::Informational;
        }

        PELFFDCInfo pelFFDCInfo;
        pelFFDCInfo.emplace_back(
            std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
                                Create::FFDCFormat::Custom,
                            FFDC_FORMAT_SUBTYPE, FFDC_FORMAT_VERSION, fd));

        auto logId = openpower::dump::pel::createSbeErrorPEL(
            event, sbeError, pelAdditionalData, logSeverity);
        lg2::info("Logged PEL {PELID} for SLID {SLID}", "PELID", logId, "SLID",
                  slid);
    }
}

FFDCFile::FFDCFile(const json& pHALCalloutData) :
    calloutData(pHALCalloutData.dump()),
    calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)
{
    prepareFFDCFile();
}

FFDCFile::~FFDCFile()
{
    removeCalloutFile();
}

int FFDCFile::getFileFD() const
{
    return fileFD;
}

void FFDCFile::prepareFFDCFile()
{
    createCalloutFile();
    writeCalloutData();
    setCalloutFileSeekPos();
}

void FFDCFile::createCalloutFile()
{
    fileFD = mkostemp(const_cast<char*>(calloutFile.c_str()), O_RDWR);

    if (fileFD == -1)
    {
        lg2::error("Failed to create phalPELCallouts file({FILE}), "
                   "errorno({ERRNO}) and errormsg({ERRORMSG})",
                   "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
                   strerror(errno));
        throw std::runtime_error("Failed to create phalPELCallouts file");
    }
}

void FFDCFile::writeCalloutData()
{
    ssize_t rc = write(fileFD, calloutData.c_str(), calloutData.size());

    if (rc == -1)
    {
        lg2::error("Failed to write phaPELCallout info in file({FILE}), "
                   "errorno({ERRNO}), errormsg({ERRORMSG})",
                   "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
                   strerror(errno));
        throw std::runtime_error("Failed to write phalPELCallouts info");
    }
    else if (rc != static_cast<ssize_t>(calloutData.size()))
    {
        lg2::warning("Could not write all phal callout info in file({FILE}), "
                     "written byte({WRITTEN}), total byte({TOTAL})",
                     "FILE", calloutFile, "WRITTEN", rc, "TOTAL",
                     calloutData.size());
    }
}

void FFDCFile::setCalloutFileSeekPos()
{
    int rc = lseek(fileFD, 0, SEEK_SET);

    if (rc == -1)
    {
        lg2::error("Failed to set SEEK_SET for phalPELCallouts in "
                   "file({FILE}), errorno({ERRNO}), errormsg({ERRORMSG})",
                   "FILE", calloutFile, "ERRNO", errno, "ERRORMSG",
                   strerror(errno));

        throw std::runtime_error(
            "Failed to set SEEK_SET for phalPELCallouts file");
    }
}

void FFDCFile::removeCalloutFile()
{
    close(fileFD);
    std::remove(calloutFile.c_str());
}

} // namespace openpower::dump::pel
