#include "install/installer.h"

#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <filesystem>  // NOLINT
#include <fstream>
#include <ios>
#include <string>
#include <system_error>  // NOLINT
#include <vector>

#include "absl/cleanup/cleanup.h"
#include "absl/log/log.h"
#include "absl/strings/substitute.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "nlohmann/json.hpp"

namespace bloom_install {

using ::bloom_install::internal::StatusReporter;

// LINT.IfChange
constexpr char kStatusKeyStatus[] = "status";
constexpr char kStatusKeyPercentComplete[] = "percent_complete";
constexpr char kStatusKeyMessage[] = "message";
constexpr char kStatusKeyStartTime[] = "start_time";
constexpr char kStatusKeyLastUpdateTime[] = "last_update_time";
// LINT.ThenChange(//depot/google3/third_party/milotic/external/cc/tlbmc/redfish/routes/task_service.cc)

ProgressLogger::ProgressLogger(const std::string& log_file_path)
    : log_file_path_(log_file_path),
      log_file_(log_file_path_, std::ios_base::app),
      is_healthy_(log_file_.is_open()) {}

bool ProgressLogger::IsHealthy() const { return is_healthy_; }

void ProgressLogger::Log(State state, absl::Duration elapsed_time,
                         const std::string& message, LogCode code,
                         int retries) {
  if (!is_healthy_) {
    return;
  }

  nlohmann::json log_entry;
  log_entry["state"] = StateToString(state);
  log_entry["time"] = absl::ToDoubleSeconds(elapsed_time);
  log_entry["message"] = message;
  log_entry["code"] = LogCodeToString(code);

  if (state == State::kFailureRetry) {
    log_entry["retries"] = retries;
  }

  log_file_ << log_entry.dump() << "\n";
  log_file_.flush();
}

namespace internal {

StatusReporter StatusReporter::Create(const std::string& status_path,
                                      int total_packages) {
  return StatusReporter(status_path, total_packages);
}

StatusReporter::StatusReporter(const std::string& status_path,
                               int total_packages)
    : status_path_(status_path), total_packages_(std::max(total_packages, 1)) {}

void StatusReporter::Start(const std::string& message) {
  status_json_[kStatusKeyStatus] = "New";
  status_json_[kStatusKeyPercentComplete] = 0;
  status_json_[kStatusKeyMessage] = message;
  const std::string now_str = absl::FormatTime(absl::Now());
  status_json_[kStatusKeyStartTime] = now_str;
  status_json_[kStatusKeyLastUpdateTime] = now_str;
  WriteStatus();
}

void StatusReporter::RecordSuccess(const std::string& message) {
  if (packages_completed_ < total_packages_) {
    packages_completed_++;
  }
  UpdateProgress(message);
}

void StatusReporter::UpdateProgress(const std::string& message) {
  status_json_[kStatusKeyPercentComplete] =
      std::round((packages_completed_ * 100.0) / total_packages_);
  status_json_[kStatusKeyMessage] = message;
  status_json_[kStatusKeyLastUpdateTime] = absl::FormatTime(absl::Now());
  WriteStatus();
}

void StatusReporter::Complete(bool success, const std::string& message) {
  status_json_[kStatusKeyStatus] = success ? "Completed" : "Exception";
  if (success) {
    status_json_[kStatusKeyPercentComplete] = 100;
  }
  status_json_[kStatusKeyMessage] = message;
  status_json_[kStatusKeyLastUpdateTime] = absl::FormatTime(absl::Now());
  WriteStatus();
}

void StatusReporter::WriteStatus() {
  const std::string temp_path = status_path_ + ".tmp";
  {
    std::ofstream temp_file(temp_path);
    if (!temp_file.is_open()) {
      return;
    }
    temp_file << status_json_.dump(4);
  }

  std::error_code ec;
  if (std::filesystem::rename(temp_path, status_path_, ec); ec) {
    std::filesystem::remove(temp_path);
  }
}

}  // namespace internal

Installer::Installer(const InstallerOptions& options)
    : options_(options),
      logger_(options.log_path),
      status_reporter_(StatusReporter::Create(
          options.status_path, static_cast<int>(options.packages.size()))) {
  if (options.packages.empty()) {
    LOG(WARNING) << "No packages to install. Post install or activation "
                    "check will succeed with no-op.";
  }
}

bool Installer::PostInstall() {
  absl::Time total_start_time = absl::Now();

  if (options_.packages.empty()) {
    const std::string complete_msg =
        "No packages to install. Process complete.";
    logger_.Log(State::kSuccess, absl::Now() - total_start_time, complete_msg,
                LogCode::kInstallComplete);
    return true;
  }

  const std::string start_msg = "Starting installation process.";
  logger_.Log(State::kStarting, absl::ZeroDuration(), start_msg,
              LogCode::kInitStart);
  status_reporter_.Start(start_msg);

  int packages_completed_for_logging = 0;
  for (const auto& package : options_.packages) {
    if (!InstallPackage(package)) {
      const std::string failure_msg =
          absl::Substitute("Installation failed on package: $0", package.name);
      absl::Duration elapsed = absl::Now() - total_start_time;
      logger_.Log(
          State::kFailureFatal, elapsed,
          absl::Substitute("Installation halted due to failure in package: $0",
                           package.name),
          LogCode::kInstallHalt);
      status_reporter_.Complete(false, failure_msg);
      return false;
    }
    // Persist the activation check script to the activation check directory.
    std::filesystem::path activation_check_script_path =
        options_.activation_check_dir;
    activation_check_script_path /= package.name;
    std::error_code ec;
    if (std::filesystem::create_directories(activation_check_script_path, ec);
        ec) {
      const std::string failure_msg = absl::Substitute(
          "Could not create activation check script directory: $0 with error: "
          "$1",
          activation_check_script_path.c_str(), ec.message());
      logger_.Log(State::kFailureFatal, absl::Now() - total_start_time,
                  failure_msg, LogCode::kInstallHalt);
      status_reporter_.Complete(false, failure_msg);
      return false;
    }
    activation_check_script_path /= "activation_check.sh";
    ec.clear();
    if (std::filesystem::copy(
            package.activation_script_path, activation_check_script_path,
            std::filesystem::copy_options::overwrite_existing, ec);
        ec) {
      const std::string failure_msg = absl::Substitute(
          "Could not copy activation check script: $0 to: $1 with error: $2",
          package.activation_script_path, activation_check_script_path.c_str(),
          ec.message());
      logger_.Log(State::kFailureFatal, absl::Now() - total_start_time,
                  failure_msg, LogCode::kInstallHalt);
      status_reporter_.Complete(false, failure_msg);
      return false;
    }

    packages_completed_for_logging++;
    const std::string progress_msg = absl::Substitute(
        "Successfully completed package $0 ($1 of $2).", package.name,
        packages_completed_for_logging, options_.packages.size());
    status_reporter_.RecordSuccess(progress_msg);
  }

  const std::string success_msg = "All packages installed successfully.";
  absl::Duration elapsed = absl::Now() - total_start_time;
  logger_.Log(State::kSuccess, elapsed, success_msg, LogCode::kInstallComplete);
  status_reporter_.Complete(true, success_msg);
  return true;
}

bool Installer::InstallPackage(const Package& package) {
  absl::Time check_start_time = absl::Now();
  logger_.Log(
      State::kCheckingActivation, absl::ZeroDuration(),
      absl::Substitute("Checking activation for package: $0", package.name),
      LogCode::kPkgActivationCheckStart);

  int activation_return_code =
      std::system(package.activation_script_path.c_str());
  absl::Duration check_elapsed = absl::Now() - check_start_time;

  if (activation_return_code == 0) {
    logger_.Log(
        State::kSkipped, check_elapsed,
        absl::Substitute("Package already active, skipping installation: $0",
                         package.name),
        LogCode::kPkgActivationSkip);
    return true;
  }

  logger_.Log(State::kInstalling, absl::ZeroDuration(),
              absl::Substitute(
                  "Package not active, proceeding with installation for: $0",
                  package.name),
              LogCode::kPkgInstallProceed);

  for (int attempt = 0; attempt <= options_.max_retries; ++attempt) {
    absl::Time attempt_start_time = absl::Now();
    logger_.Log(
        State::kInstalling, absl::ZeroDuration(),
        absl::Substitute("Attempting to install package: $0", package.name),
        LogCode::kPkgInstallStart);
    int return_code = std::system(package.install_script_path.c_str());
    absl::Duration elapsed = absl::Now() - attempt_start_time;

    if (return_code == 0) {
      logger_.Log(
          State::kSuccess, elapsed,
          absl::Substitute("Successfully installed package: $0", package.name),
          LogCode::kPkgInstallSuccess);
      return true;
    }

    if (attempt < options_.max_retries) {
      logger_.Log(State::kFailureRetry, elapsed,
                  absl::Substitute("Failed to install package: $0. Retrying.",
                                   package.name),
                  LogCode::kPkgInstallFailRetry, attempt + 1);
      absl::SleepFor(absl::Seconds(2));
    } else {
      logger_.Log(
          State::kFailureFatal, elapsed,
          absl::Substitute("Fatal error installing package: $0", package.name),
          LogCode::kPkgInstallFailFatal);
      return false;
    }
  }
  return false;
}

void Installer::ActivationCheck() {
  for (const auto& package : options_.packages) {
    // Ignore the return code of the activation script so that all packages are
    // checked.
    std::system(package.activation_script_path.c_str());
  }
}

int ActivationMain(const std::string& activation_check_dir) {
  std::vector<Package> packages;
  std::error_code ec;
  for (const auto& entry :
       std::filesystem::directory_iterator(activation_check_dir, ec)) {
    if (!ec && entry.is_directory() &&
        std::filesystem::exists(entry.path() / "activation_check.sh")) {
      Package package;
      package.name = entry.path().filename().string();
      package.activation_script_path = entry.path() / "activation_check.sh";
      packages.push_back(package);
    }
  }
  InstallerOptions options;
  options.packages = packages;
  Installer installer(options);
  installer.ActivationCheck();
  LOG(INFO) << "Activation check completed successfully.";
  return 0;
}

std::vector<Package> ParsePostInstallPackages(
    const std::string& tar_file_path) {
  std::vector<Package> packages;
  std::filesystem::path untar_dir = tar_file_path;
  untar_dir.remove_filename();
  untar_dir /= "firmware_bundle";
  LOG(INFO) << "Firmware bundle directory: " << untar_dir;
  std::error_code ec;
  for (const auto& entry : std::filesystem::directory_iterator(untar_dir, ec)) {
    if (!ec && entry.is_directory() &&
        std::filesystem::exists(entry.path() / "post_install.sh")) {
      LOG(INFO) << "Found package: " << entry.path().filename().string();
      Package package;
      package.name = entry.path().filename().string();
      package.activation_script_path = entry.path() / "activation_check.sh";
      package.install_script_path = entry.path() / "post_install.sh";
      packages.push_back(package);
    }
  }
  return packages;
}

int PostInstallMain(const std::string& inventory_dir,
                    const std::string& install_lock_file_path,
                    const std::string& bundle_tar_file_path,
                    const std::string& activation_check_dir) {
  std::vector<Package> packages =
      ParsePostInstallPackages(bundle_tar_file_path);
  InstallerOptions options;
  // Check if an installation is already running.
  std::filesystem::path install_lock_file = install_lock_file_path;
  if (std::error_code ec; std::filesystem::exists(install_lock_file, ec)) {
    LOG(ERROR) << "Installation is already in progress. Lock file found: "
               << install_lock_file;
    return 1;
  }
  std::error_code ec;
  if (std::filesystem::create_directories(inventory_dir, ec); ec) {
    LOG(ERROR) << "Error: Could not create installation directory: "
               << inventory_dir << " with error: " << ec.message();
    return 1;
  }
  ec.clear();
  if (std::filesystem::create_directories(install_lock_file.parent_path(), ec);
      ec) {
    LOG(ERROR) << "Error: Could not create installation lock file directory: "
               << install_lock_file.parent_path()
               << " with error: " << ec.message();
    return 1;
  }

  // Create the installation lock file to signal that an install is starting.
  std::ofstream lock_file_stream(install_lock_file);
  if (!lock_file_stream) {
    LOG(ERROR) << "Error: Could not create lock file: " << install_lock_file
               << " with error: " << lock_file_stream.rdstate();
    return 1;
  }
  absl::Cleanup lock_file_cleanup = [install_lock_file] {
    std::error_code ec;
    if (std::filesystem::remove(install_lock_file, ec); ec) {
      LOG(ERROR) << "Error: Could not remove lock file: " << install_lock_file;
    }
    LOG(INFO) << "Successfully removed lock file: " << install_lock_file;
  };
  LOG(INFO) << "Successfully created lock file: " << install_lock_file;

  // Now run install
  std::filesystem::path bundle_tar_file = bundle_tar_file_path;
  std::vector<Package> packages_to_install =
      ParsePostInstallPackages(bundle_tar_file);
  options.packages = packages_to_install;
  options.max_retries = 2;
  std::filesystem::path log_path = inventory_dir;
  log_path.remove_filename();
  log_path /= "progress_internal.log";
  options.log_path = log_path.c_str();
  options.activation_check_dir = activation_check_dir;

  Installer installer(options);
  LOG(INFO) << "Starting installation process...";

  if (!installer.PostInstall()) {
    LOG(ERROR) << "Post install failed. Check log at " << log_path
               << " for details.";
    return 1;
  }

  LOG(INFO) << "Post install completed successfully.";
  return 0;
}

}  // namespace bloom_install
