#include "tlbmc/redfish/routes/trust_bundle_manager.h"

#include <cstdlib>
#include <filesystem>  // NOLINT
#include <fstream>
#include <iterator>
#include <string>
#include <system_error>  // NOLINT
#include <thread>        // NOLINT
#include <utility>
#include <vector>

#include "absl/cleanup/cleanup.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "g3/macros.h"

namespace milotic_tlbmc::certificate_service {
namespace {

constexpr absl::string_view kTempTrustBundlePath = "/tmp/trust_bundle_XXXXXX";
constexpr absl::string_view kTempSignaturePath = "/tmp/signature_XXXXXX";
constexpr absl::string_view kTempOutputFile = "/tmp/openssl_output_XXXXXX";
constexpr absl::string_view kBloomCaCertPath =
    "/var/google/ca-store/bloom-ca.crt";

// The command to verify the trust bundle signature and verify the signer
// certificate with the CA file to make sure the signer is trusted.
constexpr absl::string_view kTrustBundleVerifyWithCaCommand =
    "openssl smime -verify -binary -inform PEM -in '%s' -content '%s' "
    "-CApath '%s' -purpose any -out /dev/null 2> '%s'";

// The command to verify the trust bundle signature without the CA file. Just
// blindly trust the signer certificate bundle in the PKCS#7 signature.
constexpr absl::string_view kTrustBundleVerifyNoCaCommand =
    "openssl smime -verify -binary -inform PEM -in '%s' -content '%s' "
    "-noverify -purpose any -out /dev/null 2> '%s'";

// The command to install the trust bundle and restart bmcweb. The command will
// be executed in a subprocess. And the subprocess will get SIGTERM as bmcweb
// service kill mode is group. Here as we use --no-block, it is fine that
// the restart command get terminated, it is still better to trap the SIGTERM.
constexpr absl::string_view kInstallAndRestartBmcWebCommand =
    "trap '' TERM; mv %s %s && /usr/bin/systemctl restart --no-block bmcweb";

// The path to the trust bundle file.
constexpr absl::string_view kTrustBundlePath =
    "/var/google/trust_bundle/trust_bundle.pem";

}  // namespace

void TrustBundleManager::SetCaller(
    absl::AnyInvocable<int(const char*) const>&& caller) {
  system_caller_ = std::move(caller);
}

absl::Status TrustBundleManager::RestartGrpcServer(
    absl::string_view staged_temp_file_path) {
  if (staged_temp_file_path.empty()) {
    return absl::InvalidArgumentError("Staged temp file path is empty.");
  }

  int result =
      system_caller_(absl::StrFormat(kInstallAndRestartBmcWebCommand,
                                     staged_temp_file_path, kTrustBundlePath)
                         .c_str());
  if (result != 0) {
    return absl::InternalError(
        "Issuing restart command failed. The installed trust bundle will "
        "be applied in next restart.");
  }
  return absl::OkStatus();
}

absl::StatusOr<StagedTempFile> VerifyAndStageTrustBundle(
    absl::string_view trust_bundle, absl::string_view signature,
    absl::string_view ca_file_path) {
  ECCLESIA_ASSIGN_OR_RETURN(
      StagedTempFile trust_bundle_file,
      StagedTempFile::Create(trust_bundle, kTempTrustBundlePath));
  ECCLESIA_ASSIGN_OR_RETURN(
      StagedTempFile signature_file,
      StagedTempFile::Create(signature, kTempSignaturePath));
  ECCLESIA_ASSIGN_OR_RETURN(StagedTempFile output_file,
                            StagedTempFile::Create("", kTempOutputFile));

  std::string command;
  std::error_code ec;
  if (std::filesystem::exists(ca_file_path, ec)) {
    command = absl::StrFormat(
        kTrustBundleVerifyWithCaCommand, signature_file.path(),
        trust_bundle_file.path(),
        std::filesystem::path(std::string(ca_file_path)).parent_path().string(),
        output_file.path());
  } else {
    command =
        absl::StrFormat(kTrustBundleVerifyNoCaCommand, signature_file.path(),
                        trust_bundle_file.path(), output_file.path());
  }

  int result = std::system(command.c_str());
  std::string output;
  if (std::filesystem::exists(output_file.path(), ec)) {
    std::ifstream ifs(output_file.path());
    if (ifs) {
      output.assign((std::istreambuf_iterator<char>(ifs)),
                    (std::istreambuf_iterator<char>()));
    }
  }
  LOG(WARNING) << "Trust bundle verify result: " << output;
  if (result != 0) {
    return absl::InvalidArgumentError(
        absl::StrFormat("Failed to verify trust bundle signature. %s", output));
  }
  return trust_bundle_file;
}

// A simple implementation of File::TempFile that creates a temporary file with
// the given content and name template. The file will be deleted when the object
// is destroyed.
absl::StatusOr<StagedTempFile> StagedTempFile::Create(
    absl::string_view content, absl::string_view temp_name_template) {
  std::vector<char> tmpname(temp_name_template.begin(),
                            temp_name_template.end());
  tmpname.push_back('\0');
  int fd = mkstemp(&tmpname[0]);
  if (fd == -1) {
    return absl::InternalError("Failed creating staged temp file");
  }

  absl::Cleanup file_unlink = [&] { unlink(&tmpname[0]); };
  absl::Cleanup closefd = [&] { close(fd); };

  ssize_t bytes_written = write(fd, content.data(), content.size());
  if (bytes_written < 0 ||
      static_cast<size_t>(bytes_written) != content.size()) {
    return absl::InternalError("Failed writing staged temp file");
  }
  // successfully create the temp file, the staged temp file will be kept so
  // cancel unlink cleanup.
  std::move(file_unlink).Cancel();
  return StagedTempFile(&tmpname[0]);
}

StagedTempFile::~StagedTempFile() {
  if (!path_.empty()) {
    unlink(path_.c_str());
  }
}

StagedTempFile::StagedTempFile(StagedTempFile&& other) noexcept
    : path_(std::move(other.path_)) {
  other.path_.clear();
}

StagedTempFile& StagedTempFile::operator=(StagedTempFile&& other) noexcept {
  if (this != &other) {
    if (!path_.empty()) {
      unlink(path_.c_str());
    }
    path_ = std::move(other.path_);
    other.path_.clear();
  }
  return *this;
}

StagedTempFile::StagedTempFile(absl::string_view path) : path_(path) {}

absl::Status TrustBundleManager::InstallTrustBundle(
    absl::string_view trust_bundle, absl::string_view signature) {
  absl::MutexLock lock(mutex_);
  if (last_install_time_ != absl::InfinitePast() &&
      absl::Now() - last_install_time_ <
          absl::Seconds(kTrustBundleRetryDelaySeconds)) {
    std::string error_message = absl::StrFormat(
        "A trust bundle, installed at %s, is pending to be applied at %s. "
        "Retry after %s.",
        absl::FormatTime(last_install_time_),
        absl::FormatTime(last_install_time_ +
                         absl::Seconds(kTrustBundleRestartDelaySeconds)),
        absl::FormatTime(last_install_time_ +
                         absl::Seconds(kTrustBundleRetryDelaySeconds)));
    LOG(ERROR) << error_message;
    return absl::UnavailableError(error_message);
  }

#ifdef BLOOM_CA_CERT_PATH
  absl::string_view ca_file_path = BLOOM_CA_CERT_PATH;
#else
  absl::string_view ca_file_path = kBloomCaCertPath;
#endif
  ECCLESIA_ASSIGN_OR_RETURN(
      StagedTempFile staged_trust_bundle,
      VerifyAndStageTrustBundle(trust_bundle, signature, ca_file_path));

  last_install_time_ = absl::Now();

  std::thread([this, staged_temp_file = std::move(staged_trust_bundle)]() {
    absl::SleepFor(absl::Seconds(kTrustBundleRestartDelaySeconds));
    absl::Status status = RestartGrpcServer(staged_temp_file.path());
    if (!status.ok()) {
      LOG(ERROR) << status;
    }
  }).detach();

  return absl::OkStatus();
}

}  // namespace milotic_tlbmc::certificate_service
