#include "external_storer.hpp"

#include "app.hpp"
#include "error_messages.hpp"
#include "openbmc_dbus_rest.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <cmath>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <sstream>

namespace external_storer
{

std::filesystem::path safeAppend(const std::filesystem::path& a,
                                 const std::filesystem::path& b)
{
    std::filesystem::path result{a};

    // Unfortunately, a / b returns surprising/wrong results if b is absolute
    if (b.is_absolute())
    {
        // The absolute path already starts with necessary directory separator
        result += b;
        return result;
    }

    result /= b;
    return result;
}

std::filesystem::path Hook::locBase() const
{
    return safeAppend(redfishPrefix, pathBase);
}

std::filesystem::path Hook::locInstance(const std::string& instance) const
{
    return safeAppend(locBase(), instance);
}

std::filesystem::path Hook::locMiddle(const std::string& instance) const
{
    // The middle component is optional, some schemas might not need it
    if (pathMiddle.empty())
    {
        return locInstance(instance);
    }

    return safeAppend(locInstance(instance), pathMiddle);
}

std::filesystem::path Hook::locEntry(const std::string& instance,
                                     const std::string& entry) const
{
    return safeAppend(locMiddle(instance), entry);
}

std::filesystem::path Hook::locToFileDir(const std::filesystem::path& loc) const
{
    return safeAppend(pathPrefix, loc);
}

std::filesystem::path
    Hook::locToFileJson(const std::filesystem::path& loc) const
{
    // Safe to use / operator here, jsonFilename constant always relative
    return locToFileDir(loc) / jsonFilename;
}

// Helper function to get size of an open file, also rewinds file
// Uses the C library (not C++) to be called from fileToString
std::optional<size_t> fileToSize(FILE* f)
{
    int ret = std::fseek(f, 0L, SEEK_END);
    if (ret != 0)
    {
        int err = errno;
        BMCWEB_LOG_ERROR << "File failed to seek: " << std::strerror(err);
        return std::nullopt;
    }

    // Assumes file has been opened in binary mode
    int64_t rawSize = ftell(f);
    if (rawSize < 0)
    {
        int err = errno;
        BMCWEB_LOG_ERROR << "File failed to tell: " << std::strerror(err);
        return std::nullopt;
    }

    ret = std::fseek(f, 0L, SEEK_SET);
    if (ret != 0)
    {
        int err = errno;
        BMCWEB_LOG_ERROR << "File failed to seek: " << std::strerror(err);
        return std::nullopt;
    }

    // Historical C library API legacy: long versus size_t
    auto size = static_cast<size_t>(rawSize);

    BMCWEB_LOG_DEBUG << "File open success: " << size << " bytes";
    return {size};
}

// Use the C library (not C++) to read entire file into a C++ string first
// Tested earlier to be faster than nlohmann::json::parse() of std::ifstream
std::optional<std::string> fileToString(FILE* f)
{
    auto sizeOpt = fileToSize(f);
    if (!sizeOpt.has_value())
    {
        // Helper function has already printed an error message
        return std::nullopt;
    }

    size_t fileSize = *sizeOpt;

    if (fileSize == 0)
    {
        BMCWEB_LOG_ERROR << "File is empty";
        return std::nullopt;
    }
    if (fileSize > maxFileSize)
    {
        BMCWEB_LOG_ERROR << "File is too large: " << fileSize << "/"
                         << maxFileSize;
        return std::nullopt;
    }

    std::string empty;
    std::optional<std::string> contentOpt{empty};

    // Avoid making expensive copies of string after it gets larger
    std::string& content = *contentOpt;

    // Preallocate the buffer to fit the file size
    content.resize(fileSize);

    // Read the whole file in one go
    // C++11 no longer disallows data() from being written to
    size_t readSize = fread(content.data(), 1, fileSize, f);

    // Read of 0 must be error, because empty file already excluded earlier
    if (readSize == 0)
    {
        int err = errno;
        BMCWEB_LOG_ERROR << "File read error: " << std::strerror(err);
        return std::nullopt;
    }

    // Consider a short read to also be an error
    if (readSize != fileSize)
    {
        BMCWEB_LOG_ERROR << "File read size mismatch: " << readSize << "/"
                         << fileSize;
        return std::nullopt;
    }

    BMCWEB_LOG_DEBUG << "File read success: " << readSize << " bytes";
    return contentOpt;
}

std::optional<nlohmann::json>
    readJsonFile(const std::filesystem::path& filename)
{
    // Open in binary mode to ensure accurate size measurement
    FILE* f = std::fopen(filename.c_str(), "rb");
    if (f == nullptr)
    {
        int err = errno;
        BMCWEB_LOG_ERROR << "File " << filename
                         << " failed to open: " << std::strerror(err);
        return std::nullopt;
    }

    // While we have the file open, use helper function to read it
    auto bufferOpt = fileToString(f);

    int ret = std::fclose(f);
    if (ret != 0)
    {
        int err = errno;
        BMCWEB_LOG_ERROR << "File " << filename
                         << " failed to close: " << std::strerror(err);
        return std::nullopt;
    }

    // All further error checking takes place after the close
    if (!bufferOpt.has_value())
    {
        // Helper function has already printed an error message
        return std::nullopt;
    }

    const std::string& buffer = *bufferOpt;

    // Must supply 3rd argument to avoid throwing exceptions
    nlohmann::json content = nlohmann::json::parse(buffer, nullptr, false);

    if (content.is_discarded())
    {
        BMCWEB_LOG_ERROR << "File " << filename << " not valid JSON";
        return std::nullopt;
    }

    if (!(content.is_object()))
    {
        BMCWEB_LOG_ERROR << "File " << filename << " not JSON dictionary";
        return std::nullopt;
    }

    BMCWEB_LOG_DEBUG << "File JSON success: " << filename;
    return {content};
}

std::optional<std::size_t> writeJsonFile(const std::filesystem::path& filename,
                                         const nlohmann::json& content)
{
    std::stringstream stream;

    // Must supply 4th argument to avoid throwing exceptions
    stream << content.dump(-1, ' ', false,
                           nlohmann::json::error_handler_t::replace);

    std::string buffer = stream.str();
    size_t fileSize = buffer.size();
    if (fileSize > maxFileSize)
    {
        BMCWEB_LOG_ERROR << "File is too large: " << fileSize << "/"
                         << maxFileSize;
        return std::nullopt;
    }

    BMCWEB_LOG_DEBUG << "Output write size: " << fileSize << " bytes";

    std::ofstream output;
    output.open(filename, std::ofstream::trunc);
    if (!output)
    {
        int err = errno;
        BMCWEB_LOG_ERROR << "Error opening " << filename
                         << " output: " << strerror(err);
        return std::nullopt;
    }

    output.write(buffer.data(), static_cast<std::streamsize>(fileSize));

    bool writeGood = output.good();

    if (!writeGood)
    {
        // Do not return here, need to defer until after the close
        int err = errno;
        BMCWEB_LOG_ERROR << "Error writing " << filename
                         << " output: " << strerror(err);
    }

    // Always do this, no matter what, even if write failed
    output.close();

    bool closeGood = output.good();

    // This is the deferred error return from write() above
    if (!writeGood)
    {
        // The errno from write() already printed
        return std::nullopt;
    }

    if (!closeGood)
    {
        int err = errno;
        BMCWEB_LOG_ERROR << "Error closing " << filename
                         << " output: " << strerror(err);
        return std::nullopt;
    }

    BMCWEB_LOG_DEBUG << "Output write success: " << filename;
    return {fileSize};
}

// The "proposedName" should be a basename, with no directory separators
// Conservative filename rules to begin with, can relax later if needed
bool validateFilename(const std::filesystem::path& proposedName)
{
    if (!(crow::openbmc_mapper::validateFilename(proposedName)))
    {
        BMCWEB_LOG_ERROR << "Filename contains invalid characters";
        return false;
    }

    return true;
}

bool validateFilename(const std::filesystem::path& name,
                      const std::vector<std::string>& denyList)
{
    if (!(validateFilename(name)))
    {
        // Error message has already been printed
        return false;
    }

    // Must not be within the denylist
    if (std::find(denyList.begin(), denyList.end(), name) != denyList.end())
    {
        BMCWEB_LOG_ERROR << "Filename " << name << " is reserved";
        return false;
    }

    return true;
}

std::string extractId(const nlohmann::json& content)
{
    std::string id;

    if (content.is_object())
    {
        auto foundId = content.find("Id");
        if (foundId != content.end())
        {
            if (foundId->is_string())
            {
                id = foundId.value();
                if (!(id.empty()))
                {
                    return id;
                }
            }
        }
    }

    boost::uuids::random_generator gen;

    // Roll a random UUID for server-assigned ID
    id = boost::uuids::to_string(gen());
    BMCWEB_LOG_INFO << "Generated UUID " << id;

    return id;
}

void stripFieldsId(nlohmann::json& content)
{
    if (!(content.is_object()))
    {
        return;
    }

    // No need, this is already implied by the filename on disk
    auto foundId = content.find("Id");
    if (foundId != content.end())
    {
        content.erase(foundId);
    }

    // No need, this will be dynamically built when output to user
    auto foundOdataId = content.find("@odata.id");
    if (foundOdataId != content.end())
    {
        content.erase(foundOdataId);
    }
}

void stripFieldsMembers(nlohmann::json& content)
{
    if (!(content.is_object()))
    {
        return;
    }

    // Entries must be added one at a time, using separate POST commands
    auto foundMembers = content.find("Members");
    if (foundMembers != content.end())
    {
        content.erase(foundMembers);
    }

    // No need, this will be dynamically built when output to user
    auto foundCount = content.find("Members@odata.count");
    if (foundCount != content.end())
    {
        content.erase(foundCount);
    }
}

void insertResponseLocation(crow::Response& response,
                            const std::string& location)
{
    // Add Location to header
    response.addHeader(boost::beast::http::field::location, location);

    // Add Location to body, but must dig through schema first
    if (!(response.jsonValue.is_object()))
    {
        BMCWEB_LOG_ERROR << "No Location because not object";
        return;
    }

    // ExtendedInfo must already be an array of at least 1 element (object)
    auto ei = response.jsonValue.find("@Message.ExtendedInfo");
    if (ei == response.jsonValue.end())
    {
        BMCWEB_LOG_ERROR << "No Location because no ExtendedInfo";
        return;
    }
    if (!(ei->is_array()))
    {
        BMCWEB_LOG_ERROR << "No Location because ExtendedInfo not array";
        return;
    }
    if (ei->empty())
    {
        BMCWEB_LOG_ERROR << "No Location because ExtendedInfo empty";
        return;
    }
    if (!((*ei)[0].is_object()))
    {
        BMCWEB_LOG_ERROR
            << "No Location because ExtendedInfo element not object";
        return;
    }

    // MessageArgs must be an array, create if it does not already exist
    auto ma = (*ei)[0].find("MessageArgs");
    if (ma == (*ei)[0].end())
    {
        (*ei)[0]["MessageArgs"] = nlohmann::json::array();
        ma = (*ei)[0].find("MessageArgs");
    }
    if (!(ma->is_array()))
    {
        BMCWEB_LOG_ERROR << "No Location because MessageArgs not array";
        return;
    }

    ma->emplace_back(location);
}

void Hook::handleCreateInstance(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    nlohmann::json content;
    content = nlohmann::json::parse(req.body(), nullptr, false);
    if (content.is_discarded())
    {
        BMCWEB_LOG_ERROR << "Uploaded content not JSON";
        redfish::messages::malformedJSON(asyncResp->res);
        return;
    }
    if (!(content.is_object()))
    {
        BMCWEB_LOG_ERROR << "Uploaded JSON type not a dictionary";
        redfish::messages::unrecognizedRequestBody(asyncResp->res);
        return;
    }

    std::string idInstance = extractId(content);
    stripFieldsId(content);

    auto innerContent = nlohmann::json::object();

    if (!(pathMiddle.empty()))
    {
        // Promote the inner layer to its own JSON object
        auto foundMiddle = content.find(pathMiddle);
        if (foundMiddle != content.end())
        {
            innerContent = foundMiddle.value();
            content.erase(foundMiddle);

            if (!(innerContent.is_object()))
            {
                BMCWEB_LOG_ERROR << "Interior JSON type not a dictionary";
                redfish::messages::unrecognizedRequestBody(asyncResp->res);
                return;
            }

            // Also trim "Id" and "@odata.id" from the inner layer
            stripFieldsId(innerContent);

            // Trim "Members" as well, user not allowed bulk upload yet
            stripFieldsMembers(innerContent);
        }
    }

    if (!(validateFilename(idInstance, denyList)))
    {
        BMCWEB_LOG_ERROR << "Uploaded instance ID not acceptable";
        redfish::messages::actionParameterValueFormatError(
            asyncResp->res, idInstance, "Id", "POST");
        return;
    }

    std::filesystem::path outerUrl = locInstance(idInstance);
    std::filesystem::path outerDir = locToFileDir(outerUrl);

    std::filesystem::path outerFilename = locToFileJson(outerUrl);

    std::filesystem::path innerUrl = locMiddle(idInstance);
    std::filesystem::path innerDir = locToFileDir(innerUrl);

    std::filesystem::path innerFilename = locToFileJson(innerUrl);

    // If no middle keyword, then no need to create multiple layers
    if (pathMiddle.empty())
    {
        innerDir = outerDir;
    }

    std::error_code ec;

    BMCWEB_LOG_DEBUG << "Create instance " << idInstance << " checking "
                     << outerDir;

    bool outerExists = std::filesystem::exists(outerFilename, ec);
    if (ec)
    {
        BMCWEB_LOG_ERROR << "Problem checking for " << outerFilename
                         << " duplicate: " << ec.message();
        redfish::messages::operationFailed(asyncResp->res);
        return;
    }

    // If no middle keyword, only outer file necessary to declare dupe
    bool innerExists = true;
    if (!pathMiddle.empty())
    {
        innerExists = std::filesystem::exists(innerFilename, ec);
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Problem checking for " << innerFilename
                             << " duplicate: " << ec.message();
            redfish::messages::operationFailed(asyncResp->res);
            return;
        }
    }

    // It is only considered a dupe error if both files already exist
    if (outerExists && innerExists)
    {
        BMCWEB_LOG_ERROR << "Uploaded instance ID already exists on system";
        redfish::messages::resourceAlreadyExists(asyncResp->res, "String", "Id",
                                                 idInstance);
        return;
    }

    BMCWEB_LOG_DEBUG << "Create instance " << idInstance << " making "
                     << innerDir;

    std::filesystem::create_directories(innerDir, ec);
    if (ec)
    {
        BMCWEB_LOG_ERROR << "Problem making " << innerDir
                         << " directories: " << ec.message();
        redfish::messages::operationFailed(asyncResp->res);
        return;
    }

    BMCWEB_LOG_DEBUG << "Create instance " << idInstance << " writing "
                     << outerFilename;
    if (!(writeJsonFile(outerFilename, content).has_value()))
    {
        BMCWEB_LOG_ERROR << "Problem writing file " << outerFilename;
        redfish::messages::operationFailed(asyncResp->res);
        return;
    }

    if (!(pathMiddle.empty()))
    {
        BMCWEB_LOG_DEBUG << "Create instance " << idInstance << "/"
                         << pathMiddle << " writing " << innerFilename;
        if (!(writeJsonFile(innerFilename, innerContent).has_value()))
        {
            BMCWEB_LOG_ERROR << "Problem writing file " << innerFilename;
            redfish::messages::operationFailed(asyncResp->res);
            return;
        }
    }

    redfish::messages::created(asyncResp->res);

    insertResponseLocation(asyncResp->res, outerUrl);
}

void Hook::handleCreateMiddle(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& idInstance)
{
    // Before doing anything with filesystem, validate naming restrictions
    if (!(validateFilename(idInstance, denyList)))
    {
        BMCWEB_LOG_ERROR << "Instance ID within URL is not acceptable";
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    nlohmann::json content;

    // Keep this in sync with post-I/O validation in readJsonFile()
    content = nlohmann::json::parse(req.body(), nullptr, false);
    if (content.is_discarded())
    {
        BMCWEB_LOG_ERROR << "Uploaded content not JSON";
        redfish::messages::malformedJSON(asyncResp->res);
        return;
    }
    if (!(content.is_object()))
    {
        BMCWEB_LOG_ERROR << "Uploaded JSON type not a dictionary";
        redfish::messages::unrecognizedRequestBody(asyncResp->res);
        return;
    }

    std::string idEntry = extractId(content);

    // Unlike instance, no need to do a second layer of trimming underneath
    stripFieldsId(content);

    // Unlike instance, names on denyList are perfectly OK for entry
    if (!(validateFilename(idEntry)))
    {
        BMCWEB_LOG_ERROR << "Uploaded entry ID not acceptable";
        redfish::messages::actionParameterValueFormatError(
            asyncResp->res, idEntry, "Id", "POST");
        return;
    }

    std::filesystem::path outerUrl = locInstance(idInstance);
    std::filesystem::path outerDir = locToFileDir(outerUrl);

    std::filesystem::path entryUrl = locEntry(idInstance, idEntry);
    std::filesystem::path entryDir = locToFileDir(entryUrl);

    std::filesystem::path entryFilename = locToFileJson(entryUrl);

    std::error_code ec;

    // The instance must already have been created earlier
    BMCWEB_LOG_DEBUG << "Create entry " << idInstance << " checking "
                     << outerDir;
    if (!(std::filesystem::exists(outerDir, ec)))
    {
        BMCWEB_LOG_ERROR << "Cannot add entry to nonexistent instance "
                         << idInstance;
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }
    if (ec)
    {
        BMCWEB_LOG_ERROR << "Problem checking for " << outerDir
                         << " existence: " << ec.message();
        redfish::messages::operationFailed(asyncResp->res);
        return;
    }

    BMCWEB_LOG_DEBUG << "Create entry " << idInstance << " making " << entryDir;
    std::filesystem::create_directories(entryDir, ec);

    if (ec)
    {
        BMCWEB_LOG_ERROR << "Problem making " << entryDir
                         << " directories: " << ec.message();
        redfish::messages::operationFailed(asyncResp->res);
        return;
    }

    BMCWEB_LOG_DEBUG << "Create entry " << idInstance << " writing "
                     << entryFilename;
    if (std::filesystem::exists(entryFilename, ec))
    {
        BMCWEB_LOG_ERROR << "Uploaded entry ID already exists within instance";
        redfish::messages::resourceAlreadyExists(asyncResp->res, "String", "Id",
                                                 idEntry);
        return;
    }
    if (ec)
    {
        BMCWEB_LOG_ERROR << "Problem checking for " << entryFilename
                         << " duplicate: " << ec.message();
        redfish::messages::operationFailed(asyncResp->res);
        return;
    }

    if (!(writeJsonFile(entryFilename, content).has_value()))
    {
        BMCWEB_LOG_ERROR << "Problem writing file " << entryFilename;
        redfish::messages::operationFailed(asyncResp->res);
        return;
    }

    redfish::messages::created(asyncResp->res);

    insertResponseLocation(asyncResp->res, entryUrl);
}

void Hook::handleCreateEntry(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& idInstance, const std::string& keywordMiddle)
{
    // Validate the middle path component in URL is the expected constant
    if (keywordMiddle != pathMiddle)
    {
        BMCWEB_LOG_ERROR << "URL middle path component is not " << pathMiddle;
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    // This handler has the same function as if the middle were omitted
    handleCreateMiddle(req, asyncResp, idInstance);
}

// Given a dir, list its subdirs, but only those subdirs which are themselves
// directories, and contain an "index.json" file within them.
// Those "index.json" files are only checked for existence, nothing more.
std::vector<std::filesystem::path>
    listJsonDirs(const std::filesystem::path& dir)
{
    std::vector<std::filesystem::path> files;
    std::error_code ec;

    // If containing directory not found, there can be no subdirectories
    if (!(std::filesystem::exists(dir, ec)))
    {
        BMCWEB_LOG_INFO << "Location " << dir << " nonexistent";
        return files;
    }
    if (ec)
    {
        BMCWEB_LOG_ERROR << "Problem checking for " << dir
                         << " existence: " << ec.message();
        return files;
    }

    // Old-style C++ iter loop, to get error checking, not using ranged for
    for (auto entries = std::filesystem::directory_iterator{dir};
         entries != std::filesystem::end(entries); entries.increment(ec))
    {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Problem with " << dir
                             << " iterating: " << ec.message();
            break;
        }

        const auto& entry = *entries;

        // Only match directories
        if (!(entry.is_directory()))
        {
            continue;
        }

        auto dirBasename = entry.path().filename();

        // Validating against denyList not needed for entry, only for instance
        if (!(validateFilename(dirBasename)))
        {
            continue;
        }

        // Safe to use / operator here, jsonFilename constant always relative
        auto jsonWithin = entry.path() / jsonFilename;

        // The directory must contain the special JSON filename
        if (!(std::filesystem::exists(jsonWithin, ec)))
        {
            continue;
        }
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Problem checking for " << jsonWithin
                             << " existence: " << ec.message();
            continue;
        }

        files.emplace_back(dirBasename);
    }

    return files;
}

// Returns all existing instances under this hook, as a list of basenames
std::vector<std::string> Hook::listInstances() const
{
    auto instanceDirs = listJsonDirs(locToFileDir(locBase()));

    std::vector<std::string> result;
    for (const auto& instanceDir : instanceDirs)
    {
        if (!(validateFilename(instanceDir, denyList)))
        {
            continue;
        }

        result.emplace_back(instanceDir.string());
    }

    return result;
}

void Hook::handleGetInstance(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& idInstance)
{
    // If optional middle keyword not in use, instance same as middle
    if (pathMiddle.empty())
    {
        return handleGetMiddle(asyncResp, idInstance, pathMiddle);
    }

    // Before doing anything with filesystem, validate naming restrictions
    if (!(validateFilename(idInstance, denyList)))
    {
        BMCWEB_LOG_ERROR << "Instance ID within URL is not acceptable";
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    auto outerUrl = locInstance(idInstance);
    auto outerFilename = locToFileJson(outerUrl);

    std::error_code ec;

    BMCWEB_LOG_DEBUG << "Get instance " << idInstance << " checking "
                     << outerFilename;
    if (!(std::filesystem::exists(outerFilename, ec)))
    {
        BMCWEB_LOG_ERROR << "Instance not found with ID " << idInstance;
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }
    if (ec)
    {
        BMCWEB_LOG_ERROR << "Problem checking for " << outerFilename
                         << " existence: " << ec.message();
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    auto contentOpt = readJsonFile(outerFilename);
    if (!(contentOpt.has_value()))
    {
        BMCWEB_LOG_ERROR << "Problem reading file " << outerFilename;
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    auto& content = *contentOpt;

    // Regenerate these, as they were intentionally trimmed before storage
    content["Id"] = idInstance;
    content["@odata.id"] = outerUrl;

    auto innerUrl = locMiddle(idInstance);

    // Synthesize a correct link to middle layer
    auto middleObject = nlohmann::json::object();
    middleObject["@odata.id"] = innerUrl;
    content[pathMiddle] = middleObject;

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

    asyncResp->res.jsonValue = std::move(content);
}

void Hook::handleGetMiddle(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                           const std::string& idInstance,
                           const std::string& keywordMiddle)
{
    // Before doing anything with filesystem, validate naming restrictions
    if (!(validateFilename(idInstance, denyList)))
    {
        BMCWEB_LOG_ERROR << "Instance ID within URL is not acceptable";
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    // Validate the middle path component in URL is the expected constant
    if (keywordMiddle != pathMiddle)
    {
        BMCWEB_LOG_ERROR << "URL middle path component is not " << pathMiddle;
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    auto innerUrl = locMiddle(idInstance);
    auto innerDir = locToFileDir(innerUrl);
    auto innerFilename = locToFileJson(innerUrl);

    std::error_code ec;

    BMCWEB_LOG_DEBUG << "Get middle " << idInstance
                     << (keywordMiddle.empty() ? "" : "/") << keywordMiddle
                     << " checking " << innerFilename;
    if (!(std::filesystem::exists(innerFilename, ec)))
    {
        BMCWEB_LOG_ERROR << "Instance not found with ID " << idInstance;
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }
    if (ec)
    {
        BMCWEB_LOG_ERROR << "Problem checking for " << idInstance
                         << " existence: " << ec.message();
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    auto contentOpt = readJsonFile(innerFilename);
    if (!(contentOpt.has_value()))
    {
        BMCWEB_LOG_ERROR << "Problem reading file " << innerFilename;
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    auto& content = *contentOpt;

    // Regenerate these, as they were intentionally trimmed before storage
    content["Id"] = pathMiddle;
    content["@odata.id"] = innerUrl;

    // Do not pass denylist in here, it is only for instance, not entry
    auto files = listJsonDirs(innerDir);

    // Synthesize special "Members" array with links to all our entries
    auto membersArray = nlohmann::json::array();
    for (const auto& file : files)
    {
        // Safe to use / operator here, "file" already known to be relative
        std::filesystem::path entryUrl = innerUrl / file;

        auto fileObject = nlohmann::json::object();
        fileObject["@odata.id"] = entryUrl;
        fileObject["Id"] = file;

        // Automatically expand only the fields listed in expandList
        if (!(expandList.empty()))
        {
            std::filesystem::path entryFilename = locToFileJson(entryUrl);
            auto entryContentOpt = readJsonFile(entryFilename);
            if (entryContentOpt.has_value())
            {
                auto entryContent = *entryContentOpt;

                for (const auto& key : expandList)
                {
                    auto valueIter = entryContent.find(key);
                    if (valueIter != entryContent.end())
                    {
                        fileObject[key] = *valueIter;
                    }
                }
            }
        }

        membersArray += fileObject;
    }

    // Finish putting the pieces together
    content["Members"] = membersArray;
    content["Members@odata.count"] = files.size();

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

    asyncResp->res.jsonValue = std::move(content);
}

void Hook::handleGetEntry(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                          const nlohmann::json::json_pointer& jsonPtr,
                          const std::string& idInstance,
                          const std::string& keywordMiddle,
                          const std::string& idEntry)
{
    // Before doing anything with filesystem, validate naming restrictions
    if (!(validateFilename(idInstance, denyList)))
    {
        BMCWEB_LOG_ERROR << "Instance ID within URL is not acceptable";
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    // Validate the middle path component in URL is the expected constant
    if (keywordMiddle != pathMiddle)
    {
        BMCWEB_LOG_ERROR << "URL middle path component is not " << pathMiddle;
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    // Unlike instance, names on denyList are perfectly OK at this layer
    if (!(validateFilename(idEntry)))
    {
        BMCWEB_LOG_ERROR << "Entry ID within URL not acceptable";
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    auto entryUrl = locEntry(idInstance, idEntry);
    auto entryFilename = locToFileJson(entryUrl);

    std::error_code ec;

    BMCWEB_LOG_DEBUG << "Get entry " << idInstance
                     << (keywordMiddle.empty() ? "" : "/") << keywordMiddle
                     << "/" << idEntry << " checking " << entryFilename;
    const auto doesExist = (std::filesystem::exists(entryFilename, ec));
    if (!doesExist)
    {
        BMCWEB_LOG_ERROR << "Entry not found with ID " << idEntry;
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }
    if (ec)
    {
        BMCWEB_LOG_ERROR << "Problem checking for " << idEntry
                         << " existence: " << ec.message();
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    auto contentOpt = readJsonFile(entryFilename);
    if (!(contentOpt.has_value()))
    {
        BMCWEB_LOG_ERROR << "Problem reading file " << entryFilename;
        asyncResp->res.result(boost::beast::http::status::not_found);
        return;
    }

    auto& content = *contentOpt;

    // Regenerate these, as they were intentionally trimmed before storage
    content["Id"] = idEntry;
    content["@odata.id"] = entryUrl;

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

    asyncResp->res.jsonValue[jsonPtr] = std::move(content);
}

void Hook::deleteAll()
{
    std::error_code ec;

    auto count = std::filesystem::remove_all(pathPrefix, ec);

    if (ec)
    {
        BMCWEB_LOG_ERROR << "Problem with " << pathPrefix
                         << " deleting: " << ec.message();
    }

    if (count > 0)
    {
        BMCWEB_LOG_INFO << "Deleted all " << count << " files/dirs from "
                        << pathPrefix;
    }
}

void Hook::setPathPrefix(const std::filesystem::path& newPrefix)
{
    // This function is only for testing, loudly warn if used
    BMCWEB_LOG_WARNING << "Changing path prefix to " << newPrefix;

    pathPrefix = newPrefix;
}

// Constructs a hook with known-good settings for usage with LogServices
Hook makeLogServices()
{
    const std::string pathBase{"Systems/system/LogServices"};
    const std::string midWord{"Entries"};

    // These names come from requestRoutesSystemLogServiceCollection()
    std::vector<std::string> denyList{"EventLog", "Dump", "Crashdump",
                                      "HostLogger"};

    // These names come from the "required" field of LogEntry JSON schema
    std::vector<std::string> expandList{"EntryType", "@odata.id", "@odata.type",
                                        "Id", "Name"};

    // Additional useful names to pre-expand
    expandList.emplace_back("Created");

    return {pathBase, midWord, denyList, expandList};
}

std::shared_ptr<Hook>
    rememberLogServices(const std::shared_ptr<Hook>& hookIncoming)
{
    static std::shared_ptr<Hook> hookLogServices = nullptr;

    // If incoming pointer is valid, remember it for next time
    if (hookIncoming)
    {
        hookLogServices = hookIncoming;
    }

    return hookLogServices;
}

} // namespace external_storer

namespace redfish
{

inline void handleLogServiceInstancePost(
    App& app, const std::shared_ptr<external_storer::Hook>& hook,
    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;
    }

    hook->handleCreateInstance(req, asyncResp);
}

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

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

    hook->handleCreateMiddle(req, asyncResp, instance);
}

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

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

    hook->handleCreateEntry(req, asyncResp, instance, middle);
}

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

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

    hook->handleGetInstance(asyncResp, instance);
}

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

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

    hook->handleGetMiddle(asyncResp, instance, middle);
}

inline void handleLogServiceEntryGet(
    App& app, const std::shared_ptr<external_storer::Hook>& hook,
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& systemName, const std::string& instance,
    const std::string& middle, const std::string& entry)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

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

    hook->handleGetEntry(asyncResp, ""_json_pointer, instance, middle, entry);
}

void requestRoutesExternalStorerLogServices(
    App& app, const std::shared_ptr<external_storer::Hook>& hook)
{
    // Only 0-argument, 1-argument, and 2-argument POST routes exist
    // There intentionally is no 3-argument POST handler
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/")
        .privileges(redfish::privileges::postLogService)
        .methods(boost::beast::http::verb::post)(
            std::bind_front(handleLogServiceInstancePost, std::ref(app), hook));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/<str>/")
        .privileges(redfish::privileges::postLogService)
        .methods(boost::beast::http::verb::post)(
            std::bind_front(handleLogServiceMiddlePost, std::ref(app), hook));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/<str>/<str>/")
        .privileges(redfish::privileges::postLogService)
        .methods(boost::beast::http::verb::post)(
            std::bind_front(handleLogServiceEntryPost, std::ref(app), hook));

    // Only 1-argument, 2-argument, and 3-argument GET routes are here
    // The 0-argument GET route is already handled by the integration point
    // It is at log_services.hpp requestRoutesSystemLogServiceCollection()
    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/<str>/")
        .privileges(redfish::privileges::getLogService)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleLogServiceInstanceGet, std::ref(app), hook));

    BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/LogServices/<str>/<str>/")
        .privileges(redfish::privileges::getLogService)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleLogServiceMiddleGet, std::ref(app), hook));

    BMCWEB_ROUTE(app,
                 "/redfish/v1/Systems/<str>/LogServices/<str>/<str>/<str>/")
        .privileges(redfish::privileges::getLogService)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleLogServiceEntryGet, std::ref(app), hook));

    // The integration point also needs to access the correct hook
    external_storer::rememberLogServices(hook);
}

void requestRoutesExternalStorer(App& app)
{
    auto hookLogServices = std::make_shared<external_storer::Hook>(
        external_storer::makeLogServices());

    // The shared_ptr will be copied, stretching out its lifetime
    requestRoutesExternalStorerLogServices(app, hookLogServices);
}

} // namespace redfish
