#include "external_storer.hpp"

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

#include "boost/uuid/uuid.hpp"  // NOLINT
#include "boost/uuid/uuid_generators.hpp"  // NOLINT
#include "boost/uuid/uuid_io.hpp"  // NOLINT
#include "app.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "async_resp.hpp"
#include "openbmc_dbus_rest.hpp"
#include "error_messages.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
