#pragma once

#include "absl/strings/substitute.h"
#include "bm_config.h"

#include "app.hpp"
#include "managed_store.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/sw_utils.hpp"

#include <utils/json_utils.hpp>

#include <filesystem>
#include <fstream>

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace redfish
{

constexpr absl::string_view kPldmServiceName = "xyz.openbmc_project.pldm";
constexpr absl::string_view kPldmObjectPath = "/xyz/openbmc_project/pldm";
constexpr absl::string_view kPldmControlInterface =
    "xyz.openbmc_project.PLDM.control";
constexpr absl::string_view kPldmLoadSingleFileMethod =
    "loadSingleFileAndSyncCache";

std::string biosSettingFilepathFromConfig = BIOS_SETTING_FILE_PATH;

std::string readBiosSettingsIntoBase64(std::string biosSettingBlobPath)
{
    // If the path doesn't exist, set the properties to an empty string
    if (!std::filesystem::exists(biosSettingBlobPath))
    {
        BMCWEB_LOG_ERROR << "the BIOS setting file doesn't exist, path:"
                         << biosSettingBlobPath;
        return {};
    }
    const auto fileSize = std::filesystem::file_size(biosSettingBlobPath);
    if (fileSize == 0)
    {
        BMCWEB_LOG_DEBUG << "the BIOS setting file is empty, path:"
                         << biosSettingBlobPath;
        return {};
    }
    // ManagedFd would be nice but stdplus is not included as DEPENDS in gbmcweb
    std::ifstream ifs(biosSettingBlobPath, std::ios::binary);
    ifs.exceptions(std::ifstream::failbit);
    std::vector<char> fileData(fileSize);
    try
    {
        std::copy(std::istreambuf_iterator<char>(ifs),
                  std::istreambuf_iterator<char>(), fileData.begin());
    }
    catch (std::ios_base::failure& fail)
    {
        BMCWEB_LOG_ERROR << "Failed to read the BIOS setting file";
        return {};
    }
    return crow::utility::base64encode(
        std::string_view(fileData.data(), fileData.size()));
}

inline std::string resourceIdFromNameString(const std::string& name)
{
    // Find out the index of last non digit character(0,1,2,3,4,5,6,7,8,9)
    // assuming the inout has at least one digit so that we can get resource
    // index. For example, system1->1.
    return name.substr(name.find_last_not_of("0123456789") + 1);
}

inline void handleBios(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                       const std::string& systemName, bool multiHost)
{
    // systemId should be empty for single host system.
    std::string systemId =
        multiHost ? resourceIdFromNameString(systemName) : "";

    asyncResp->res.jsonValue["@odata.id"] =
        absl::Substitute("/redfish/v1/Systems/$0/Bios", systemName);
    asyncResp->res.jsonValue["@odata.type"] = "#Bios.v1_1_0.Bios";
    asyncResp->res.jsonValue["Name"] = "BIOS Configuration";
    asyncResp->res.jsonValue["Description"] = "BIOS Configuration Service";
    asyncResp->res.jsonValue["Id"] = "BIOS";
    asyncResp->res.jsonValue["Actions"]["#Bios.ResetBios"] = {
        {"target",
         absl::Substitute("/redfish/v1/Systems/$0/Bios/Actions/Bios.ResetBios",
                          systemName)}};

    // Get the ActiveSoftwareImage and SoftwareImages
    sw_util::populateSoftwareInformation(asyncResp, sw_util::biosPurpose, "",
                                         true);

    // Populated BIOS setting blob
    std::string biosSettingFilepath = biosSettingFilepathFromConfig;
    if (multiHost)
    {
        size_t posHost = biosSettingFilepath.find("host");
        if (posHost == std::string::npos)
        {
            BMCWEB_LOG_DEBUG
                << "The BIOS setting file path template is ill-formated"
                << biosSettingFilepath;
            return;
        }
        // Get index
        int systemIdInt = 0;
        try
        {
            systemIdInt = std::stoi(systemId);
            // system1 -> /run/soc_firmware/host0/vmtppr.cfg
            // system2 -> /run/soc_firmware/host1/vmtppr.cfg
            systemIdInt -= 1;
        }
        catch (const std::exception& ex)
        {
            BMCWEB_LOG_DEBUG << "file to parse systemId " << systemId
                             << ":from string to int, exception:" << ex.what();
            return;
        }

        // insert the index right after "host" i.e. pos + 4
        biosSettingFilepath.insert(posHost + 4, std::to_string(systemIdInt));
    }

    asyncResp->res.jsonValue["Oem"]["Google"]["MemTestBlob"] =
        readBiosSettingsIntoBase64(biosSettingFilepath);
}

/**
 * BiosService class supports handle get method for bios.
 */
inline void
    handleBiosServiceGet(crow::App& app, const crow::Request& req,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::string& systemName)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    constexpr std::array<std::string_view, 1> systemInterfaces{
        {"xyz.openbmc_project.Inventory.Item.System"}};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/", 0, systemInterfaces, requestContext,
        [asyncResp, systemName](const boost::system::error_code& ec,
                                const std::vector<std::string>& objects) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error";
            messages::internalError(asyncResp->res);
            return;
        }

        // If there are less than 2 Item.Systems assume singlehost
        if (objects.size() < 2)
        {
            if (systemName != "system")
            {
                messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                           systemName);
                return;
            }
            handleBios(asyncResp, systemName, false);
            return;
        }

        // Otherwise find system, e.g. system1, system2
        for (const auto& object : objects)
        {
            std::string objectName = object.substr(object.rfind('/') + 1);
            // Found system object
            if (systemName == objectName)
            {
                handleBios(asyncResp, systemName, true);
                return;
            }
        }

        // Could not find system object
        messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                   systemName);
    });
}

inline void handleBiosSettingPatch(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& biosSettingFilepath, bool multiHost,
    std::optional<std::string> memTestBlob, int systemId = 0)
{
    asyncResp->res.result(boost::beast::http::status::no_content);

    std::filesystem::path filePath(biosSettingFilepath);
    if (!std::filesystem::exists(filePath.parent_path()))
    {
        BMCWEB_LOG_ERROR
            << "The directory of the BIOS setting file doesn't exist";
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    if (!memTestBlob)
    {
        BMCWEB_LOG_ERROR << "Payload was null";
        redfish::messages::internalError(asyncResp->res);
        return;
    }
    std::string memTestBlobBase64;
    if (crow::utility::base64Decode(memTestBlob.value_or(""),
                                    memTestBlobBase64) == false)
    {
        BMCWEB_LOG_ERROR << "Base64 Decoding unsuccessful";
        redfish::messages::internalError(asyncResp->res);
        return;
    }
    try
    {
        std::ofstream ofs;
        ofs.open(biosSettingFilepath, std::ios::trunc | std::ios::binary);
        ofs.write(reinterpret_cast<char*>(memTestBlobBase64.data()),
                  // Get warning if no cast
                  // " error: conversion to
                  // 'std::streamsize' {aka 'int'} from
                  // 'std::__cxx11::basic_string<char>::size_type' {aka
                  // 'unsigned int'} may change the sign of the result
                  // [-Werror=sign-conversion]"
                  static_cast<int>(memTestBlobBase64.size()));
        ofs.close();
    }
    catch (std::ios_base::failure& fail)
    {
        BMCWEB_LOG_ERROR << "Failed to write the BIOS setting file";
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    // We are using PLDM to transfer the BIOS file out in multi-host machine.
    // Reload the file content is necessary to guarantee the file content in
    // PLDMd cache is up-to-date.
    if (multiHost)
    {
        managedStore::GetManagedObjectStore()
            ->PostDbusCallToIoContextThreadSafe(
                asyncResp->strand_,
                [asyncResp](const boost::system::error_code& ec) {
            if (ec)
            {
                BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
                messages::internalError(asyncResp->res);
                return;
            }
        }, std::string(kPldmServiceName) + std::to_string(systemId),
                std::string(kPldmObjectPath),
                std::string(kPldmControlInterface),
                std::string(kPldmLoadSingleFileMethod),
                static_cast<uint16_t>(BIOS_SETTING_FILE_HANDLE));
    }

    redfish::messages::success(asyncResp->res);
    return;
}

inline void
    patchBiosSettings(crow::App& app, const crow::Request& req,
                      const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                      const std::string& systemName)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    std::optional<std::string> memTestBlob;
    if (!ENABLE_BIOS_PEER_AUTH_BYPASS && !req.peer_authenticated)
    {
        redfish::messages::accessDenied(asyncResp->res, "Bios");
        return;
    }

    if (!redfish::json_util::readJsonPatch(
            req, asyncResp->res, "Oem/Google/MemTestBlob", memTestBlob))
    {
        BMCWEB_LOG_ERROR << "There was no valid patch payload";
        redfish::messages::internalError(asyncResp->res);
        return;
    }

    constexpr std::array<std::string_view, 1> systemInterfaces{
        {"xyz.openbmc_project.Inventory.Item.System"}};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        "/", 0, systemInterfaces, requestContext,
        [asyncResp, systemName,
         memTestBlob](const boost::system::error_code& ec,
                      const std::vector<std::string>& objects) {
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "DBUS response error";
            messages::internalError(asyncResp->res);
            return;
        }

        std::string biosSettingFilepath = biosSettingFilepathFromConfig;
        // If there are less than 2 Item.Systems assume singlehost
        if (objects.size() < 2)
        {
            if (systemName != "system")
            {
                messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                           systemName);
                return;
            }
            handleBiosSettingPatch(asyncResp, biosSettingFilepath, false,
                                   memTestBlob);
            return;
        }

        // Otherwise find system, e.g. system1, system2
        for (const auto& object : objects)
        {
            std::string objectName = object.substr(object.rfind('/') + 1);
            // Found system object
            if (systemName == objectName)
            {
                // Format the actual file path based on systemName
                std::string systemId = resourceIdFromNameString(systemName);
                size_t posHost = biosSettingFilepath.find("host");
                if (posHost == std::string::npos)
                {
                    BMCWEB_LOG_DEBUG
                        << "The BIOS setting file path template is invalid"
                        << biosSettingFilepath;
                    messages::internalError(asyncResp->res);
                    return;
                }
                // Get index
                int systemIdInt = 0;
                try
                {
                    systemIdInt = std::stoi(systemId);
                    // system1 -> /run/soc_firmware/host0/vmtppr.cfg
                    // system2 -> /run/soc_firmware/host1/vmtppr.cfg
                    systemIdInt -= 1;
                }
                catch (const std::exception& ex)
                {
                    BMCWEB_LOG_DEBUG
                        << "file to parse systemId " << systemId
                        << ":from string to int, exception:" << ex.what();
                    messages::internalError(asyncResp->res);
                    return;
                }

                // insert the index right after "host" i.e. pos + 4
                biosSettingFilepath.insert(posHost + 4,
                                           std::to_string(systemIdInt));

                handleBiosSettingPatch(asyncResp, biosSettingFilepath, true,
                                       memTestBlob, systemIdInt);
                return;
            }
        }

        // Could not find system object
        messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                   systemName);
    });
}

inline void requestRoutesBiosService(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Bios/")
        .privileges(redfish::privileges::getBios)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleBiosServiceGet, std::ref(app)));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Bios/")
        .privileges(redfish::privileges::patchBios)
        .methods(boost::beast::http::verb::patch)(
            std::bind_front(patchBiosSettings, std::ref(app)));
}

/**
 * BiosReset class supports handle POST method for Reset bios.
 * The class retrieves and sends data directly to D-Bus.
 *
 * Function handles POST method request.
 * Analyzes POST body message before sends Reset request data to D-Bus.
 */
inline void
    handleBiosResetPost(crow::App& app, const crow::Request& req,
                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                        const std::string& systemName)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    if (systemName != "system")
    {
        messages::resourceNotFound(asyncResp->res, "ComputerSystem",
                                   systemName);
        return;
    }

    managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
        asyncResp->strand_,
        [asyncResp](const boost::system::error_code& ec) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Failed to reset bios: " << ec;
            messages::internalError(asyncResp->res);
            return;
        }
    }, "org.open_power.Software.Host.Updater", "/xyz/openbmc_project/software",
        "xyz.openbmc_project.Common.FactoryReset", "Reset");
}

inline void requestRoutesBiosReset(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/Bios/Actions/Bios.ResetBios/")
        .privileges(redfish::privileges::postBios)
        .methods(boost::beast::http::verb::post)(
            std::bind_front(handleBiosResetPost, std::ref(app)));
}

} // namespace redfish
