#include "sessions.hpp"

#include <array>
#include <chrono>
#include <csignal>
#include <cstddef>
#include <memory>
#include <optional>
#include <random>
#include <string>
#include <string_view>
#include <vector>

#include "logging.hpp"
#include "utility.hpp"  // NOLINT
#include "random.hpp"
#include "ip_utils.hpp"
#include <nlohmann/json.hpp>

namespace persistent_data {

std::shared_ptr<UserSession> UserSession::fromJson(const nlohmann::json& j) {
  std::shared_ptr<UserSession> userSession = std::make_shared<UserSession>();
  for (const auto& element : j.items()) {
    const std::string* thisValue =
        element.value().get_ptr<const std::string*>();
    if (thisValue == nullptr) {
      BMCWEB_LOG_ERROR << "Error reading persistent store.  Property "
                       << element.key() << " was not of type string";
      continue;
    }
    if (element.key() == "unique_id") {
      userSession->uniqueId = *thisValue;
    } else if (element.key() == "session_token") {
      userSession->sessionToken = *thisValue;
    } else if (element.key() == "csrf_token") {
      userSession->csrfToken = *thisValue;
    } else if (element.key() == "username") {
      userSession->username = *thisValue;
    } else if (element.key() == "client_id") {
      userSession->clientId = *thisValue;
    } else if (element.key() == "client_ip") {
      userSession->clientIp = *thisValue;
    } else {
      BMCWEB_LOG_ERROR << "Got unexpected property reading persistent file: "
                       << element.key();
      continue;
    }
  }
  // If any of these fields are missing, we can't restore the session, as
  // we don't have enough information.  These 4 fields have been present
  // in every version of this file in bmcwebs history, so any file, even
  // on upgrade, should have these present
  if (userSession->uniqueId.empty() || userSession->username.empty() ||
      userSession->sessionToken.empty() || userSession->csrfToken.empty()) {
    BMCWEB_LOG_DEBUG << "Session missing required security "
                        "information, refusing to restore";
    return nullptr;
  }

  // For now, sessions that were persisted through a reboot get their idle
  // timer reset.  This could probably be overcome with a better
  // understanding of wall clock time and steady timer time, possibly
  // persisting values with wall clock time instead of steady timer, but
  // the tradeoffs of all the corner cases involved are non-trivial, so
  // this is done temporarily
  userSession->lastUpdated = std::chrono::steady_clock::now();
  userSession->persistence = PersistenceType::TIMEOUT;

  return userSession;
}

void AuthConfigMethods::fromJson(const nlohmann::json& j) {
  for (const auto& element : j.items()) {
    const bool* value = element.value().get_ptr<const bool*>();
    if (value == nullptr) {
      continue;
    }

    if (element.key() == "XToken") {
      xtoken = *value;
    } else if (element.key() == "Cookie") {
      cookie = *value;
    } else if (element.key() == "SessionToken") {
      sessionToken = *value;
    } else if (element.key() == "BasicAuth") {
      basic = *value;
    } else if (element.key() == "TLS") {
      tls = *value;
    }
  }
}

std::shared_ptr<UserSession> SessionStore::generateUserSession(
    std::string_view username, const boost::asio::ip::address& clientIp,
    const std::optional<std::string>& clientId, PersistenceType persistence,
    bool isConfigureSelfOnly) {
  // TODO(ed) find a secure way to not generate session identifiers if
  // persistence is set to SINGLE_REQUEST
  static constexpr std::array<char, 62> alphanum = {
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
      'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
      'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
      'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
      'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

  std::string sessionToken;
  sessionToken.resize(sessionTokenSize, '0');
  std::uniform_int_distribution<size_t> dist(0, alphanum.size() - 1);

  bmcweb::OpenSSLGenerator gen;

  for (char& sessionChar : sessionToken) {
    sessionChar = alphanum[dist(gen)];
    if (gen.error()) {
      return nullptr;
    }
  }
  // Only need csrf tokens for cookie based auth, token doesn't matter
  std::string csrfToken;
  csrfToken.resize(sessionTokenSize, '0');
  for (char& csrfChar : csrfToken) {
    csrfChar = alphanum[dist(gen)];
    if (gen.error()) {
      return nullptr;
    }
  }

  std::string uniqueId;
  uniqueId.resize(10, '0');
  for (char& uidChar : uniqueId) {
    uidChar = alphanum[dist(gen)];
    if (gen.error()) {
      return nullptr;
    }
  }

  auto session = std::make_shared<UserSession>(UserSession{
      uniqueId, sessionToken, std::string(username), csrfToken, clientId,
      redfish::ip_util::toString(clientIp), std::chrono::steady_clock::now(),
      persistence, false, isConfigureSelfOnly});
  auto it = authTokens.emplace(sessionToken, session);
  // Only need to write to disk if session isn't about to be destroyed.
  needWrite = persistence == PersistenceType::TIMEOUT;
  return it.first->second;
}

std::shared_ptr<UserSession> SessionStore::loginSessionByToken(
    std::string_view token) {
  applySessionTimeouts();
  if (token.size() != sessionTokenSize) {
    return nullptr;
  }
  auto sessionIt = authTokens.find(std::string(token));
  if (sessionIt == authTokens.end()) {
    return nullptr;
  }
  std::shared_ptr<UserSession> userSession = sessionIt->second;
  userSession->lastUpdated = std::chrono::steady_clock::now();
  return userSession;
}

std::shared_ptr<UserSession> SessionStore::getSessionByUid(
    std::string_view uid) {
  applySessionTimeouts();
  // TODO(Ed) this is inefficient
  auto sessionIt = authTokens.begin();
  while (sessionIt != authTokens.end()) {
    if (sessionIt->second->uniqueId == uid) {
      return sessionIt->second;
    }
    sessionIt++;
  }
  return nullptr;
}

void SessionStore::removeSession(const std::shared_ptr<UserSession>& session) {
  authTokens.erase(session->sessionToken);
  needWrite = true;
}

std::vector<const std::string*> SessionStore::getUniqueIds(
    bool getAll, const PersistenceType& type) {
  applySessionTimeouts();

  std::vector<const std::string*> ret;
  ret.reserve(authTokens.size());
  for (auto& session : authTokens) {
    if (getAll || type == session.second->persistence) {
      ret.push_back(&session.second->uniqueId);
    }
  }
  return ret;
}

void SessionStore::removeSessionsByUsername(std::string_view username) {
  std::erase_if(authTokens, [username](const auto& value) {
    if (value.second == nullptr) {
      return false;
    }
    return value.second->username == username;
  });
}

void SessionStore::updateAuthMethodsConfig(const AuthConfigMethods& config) {
  bool isTLSchanged = (authMethodsConfig.tls != config.tls);
  authMethodsConfig = config;
  needWrite = true;
  if (isTLSchanged) {
    // recreate socket connections with new settings
    std::raise(SIGHUP);
  }
}

void SessionStore::applySessionTimeouts() {
  auto timeNow = std::chrono::steady_clock::now();
  if (timeNow - lastTimeoutUpdate > std::chrono::seconds(1)) {
    lastTimeoutUpdate = timeNow;
    auto authTokensIt = authTokens.begin();
    while (authTokensIt != authTokens.end()) {
      if (timeNow - authTokensIt->second->lastUpdated >= timeoutInSeconds) {
        authTokensIt = authTokens.erase(authTokensIt);

        needWrite = true;
      } else {
        authTokensIt++;
      }
    }
  }
}

}  // namespace persistent_data
