#include "external_storer.hpp"

#include <cstddef>
#include <cstdint>
#include <fstream>
#include <sstream>
#include <filesystem>  // NOLINT
#include <string>
#include <vector>
#include <algorithm>
#include <optional>
#include <cstdio>
#include <cstring>
#include <memory>
#include <cerrno>
#include <system_error>  // NOLINT
#include <utility>
#include <functional>
#include <ios>



#include "boost/uuid/uuid.hpp"  // NOLINT
#include "boost/uuid/uuid_generators.hpp"  // NOLINT
#include "boost/uuid/uuid_io.hpp"  // NOLINT
#include "app.hpp"
#include "openbmc_dbus_rest.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "error_messages.hpp"
#include "async_resp.hpp"
#include "logging.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include <nlohmann/json.hpp>

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
