// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/forensics/crash_reports/queue.h"

#include <lib/async/cpp/task.h>
#include <lib/fit/defer.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>
#include <zircon/errors.h>

#include "src/developer/forensics/crash_reports/constants.h"
#include "src/developer/forensics/crash_reports/info/queue_info.h"
#include "src/lib/fxl/strings/join_strings.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace forensics {
namespace crash_reports {

Queue::Queue(async_dispatcher_t* dispatcher, std::shared_ptr<sys::ServiceDirectory> services,
             std::shared_ptr<InfoContext> info_context, LogTags* tags, CrashServer* crash_server,
             SnapshotManager* snapshot_manager)
    : dispatcher_(dispatcher),
      services_(services),
      tags_(tags),
      store_(tags_, info_context, /*temp_root=*/Store::Root{kStoreTmpPath, kStoreMaxTmpSize},
             /*persistent_root=*/Store::Root{kStoreCachePath, kStoreMaxCacheSize}),
      crash_server_(crash_server),
      snapshot_manager_(snapshot_manager),
      info_(std::move(info_context)) {
  FX_CHECK(dispatcher_);
  FX_CHECK(crash_server_);

  upload_all_every_fifteen_minutes_task_.set_handler([this]() { UploadAllEveryFifteenMinutes(); });

  // Note: The upload attempt data is lost when the component stops and all reports start with
  // upload attempts of 0.
  pending_reports_ = store_.GetReports();
  std::sort(pending_reports_.begin(), pending_reports_.end());

  if (!pending_reports_.empty()) {
    std::vector<std::string> report_id_strs;
    for (const auto& report_id : pending_reports_) {
      report_id_strs.push_back(std::to_string(report_id));
    }
    FX_LOGS(INFO) << "Initializing queue with reports: " << fxl::JoinStrings(report_id_strs, " ");
  }
}

uint64_t Queue::Size() const {
  return pending_reports_.size() + (uint64_t)hourly_report_.has_value();
}
bool Queue::IsEmpty() const { return pending_reports_.empty() && !hourly_report_.has_value(); }

bool Queue::Contains(const ReportId report_id) const {
  return std::find(pending_reports_.begin(), pending_reports_.end(), report_id) !=
             pending_reports_.end() ||
         (hourly_report_.has_value() && hourly_report_.value() == report_id);
}

void Queue::StopUploading() {
  stop_uploading_ = true;
  upload_all_every_fifteen_minutes_task_.Cancel();
}

bool Queue::Add(Report report) {
  if (reporting_policy_ == ReportingPolicy::kDoNotFileAndDelete) {
    info_.MarkReportAsDeleted(0u);
    return true;
  }

  // Attempt to upload a report before putting it in the store.
  if (reporting_policy_ == ReportingPolicy::kUpload && !stop_uploading_) {
    if (Upload(report)) {
      return true;
    }
  }

  const auto report_id = report.Id();
  const auto is_hourly_report = report.IsHourlyReport();

  // If an hourly report is already present, don't delete it and don't store a new one. This is
  // done to preserve the data from the first hourly report that wasn't successfully uploaded and
  // will have the best chance of containing data on why.
  if (report.IsHourlyReport() && hourly_report_.has_value()) {
    Delete(report.Id());
    return true;
  }

  std::vector<ReportId> garbage_collected_reports;
  const bool success = store_.Add(std::move(report), &garbage_collected_reports);

  for (const auto& id : garbage_collected_reports) {
    GarbageCollect(id);
  }

  if (!success) {
    FreeResources(report_id);
    return false;
  }

  if (reporting_policy_ == ReportingPolicy::kArchive) {
    Archive(report_id);
    return true;
  }

  if (!is_hourly_report) {
    pending_reports_.push_back(report_id);
  } else {
    hourly_report_ = report_id;
  }

  return true;
}

bool Queue::Upload(const Report& report) {
  upload_attempts_[report.Id()]++;
  info_.RecordUploadAttemptNumber(upload_attempts_[report.Id()]);

  std::string server_report_id;
  const auto response = crash_server_->MakeRequest(report, &server_report_id);

  switch (response) {
    case CrashServer::UploadStatus::kSuccess:
      FX_LOGST(INFO, tags_->Get(report.Id()))
          << "Successfully uploaded report at https://crash.corp.google.com/" << server_report_id;
      info_.MarkReportAsUploaded(server_report_id, upload_attempts_[report.Id()]);
      FreeResources(report);
      return true;
    case CrashServer::UploadStatus::kThrottled:
      info_.MarkReportAsThrottledByServer(upload_attempts_[report.Id()]);
      FreeResources(report);
      return true;
    case CrashServer::UploadStatus::kFailure:
      return false;
  }
}

void Queue::Archive(const ReportId report_id) {
  FX_LOGST(INFO, tags_->Get(report_id)) << "Archiving local report under /tmp/reports";
  info_.MarkReportAsArchived();
  // In Archive mode, the report is never placed in |pending_| nor |upload_attemps_|.
}

void Queue::GarbageCollect(const ReportId report_id) {
  FX_LOGST(INFO, tags_->Get(report_id)) << "Garbage collected local report";
  info_.MarkReportAsGarbageCollected(upload_attempts_[report_id]);
  FreeResources(report_id);
  pending_reports_.erase(std::find(pending_reports_.begin(), pending_reports_.end(), report_id));
}

void Queue::FreeResources(const ReportId report_id) {
  if (const auto report = store_.Get(report_id); report != std::nullopt) {
    FreeResources(std::move(report.value()));
    return;
  }

  // The report no longer exists in the store.
  tags_->Unregister(report_id);
  upload_attempts_.erase(report_id);
}

void Queue::FreeResources(const Report& report) {
  snapshot_manager_->Release(report.SnapshotUuid());
  tags_->Unregister(report.Id());
  upload_attempts_.erase(report.Id());
  store_.Remove(report.Id());
}

size_t Queue::UploadAll() {
  std::vector<ReportId> new_pending_reports;
  for (const auto& report_id : pending_reports_) {
    std::optional<Report> report = store_.Get(report_id);
    if (!report.has_value()) {
      // |pending_reports_| is kept in sync with |store_| so Get should only ever fail if the
      // report is deleted from the store by an external influence, e.g., the filesystem flushes
      // /cache.
      FreeResources(report_id);
      continue;
    }

    if (!Upload(report.value())) {
      new_pending_reports.push_back(report_id);
    }
  }

  pending_reports_.swap(new_pending_reports);

  bool uploaded_hourly_report{false};
  if (hourly_report_.has_value()) {
    const auto report_id = hourly_report_.value();
    std::optional<Report> report = store_.Get(report_id);
    if (!report.has_value()) {
      // This should only happen if the report is deleted from the store by an external influence,
      // e.g., the filesystem flushes /cache.
      FreeResources(report_id);
    } else if (Upload(report.value())) {
      hourly_report_ = std::nullopt;
      uploaded_hourly_report = true;
    }
  }

  // |new_pending_reports| now contains the pending reports before attempting to upload them.
  return new_pending_reports.size() - pending_reports_.size() + (size_t)uploaded_hourly_report;
}

void Queue::Delete(const ReportId report_id) {
  info_.MarkReportAsDeleted(upload_attempts_[report_id]);
  FreeResources(report_id);
}

void Queue::DeleteAll() {
  FX_LOGS(INFO) << fxl::StringPrintf("Deleting all %zu pending reports", Size());
  for (const auto& report_id : pending_reports_) {
    Delete(report_id);
  }
  pending_reports_.clear();

  if (hourly_report_.has_value()) {
    Delete(hourly_report_.value());
  }
  hourly_report_ = std::nullopt;

  store_.RemoveAll();
}

// The queue is inheritly conservative with uploading crash reports meaning that a report that is
// forbidden from being uploaded will never be uploaded while crash reports that are permitted to
// be uploaded may later be considered to be forbidden. This is due to the fact that when uploads
// are disabled all reports are immediately archived after having been added to the queue, thus we
// never have to worry that a report that shouldn't be uploaded ends up being uploaded when the
// reporting policy changes.
void Queue::WatchReportingPolicy(ReportingPolicyWatcher* watcher) {
  auto OnReportingPolicyChange = [this](const ReportingPolicy policy) {
    reporting_policy_ = policy;
    switch (reporting_policy_) {
      case ReportingPolicy::kDoNotFileAndDelete:
        upload_all_every_fifteen_minutes_task_.Cancel();
        DeleteAll();
        break;
      case ReportingPolicy::kUpload:
        UploadAllEveryFifteenMinutes();
        break;
      case ReportingPolicy::kArchive:
        // The reporting policy shouldn't change to Archive outside of tests.
        break;
      case ReportingPolicy::kUndecided:
        upload_all_every_fifteen_minutes_task_.Cancel();
        break;
    }
  };

  OnReportingPolicyChange(watcher->CurrentPolicy());
  watcher->OnPolicyChange([=](const ReportingPolicy policy) { OnReportingPolicyChange(policy); });
}

void Queue::WatchNetwork(NetworkWatcher* network_watcher) {
  network_watcher->Register([this](const bool network_is_reachable) {
    if (!stop_uploading_ && network_is_reachable) {
      // Save the size of |pending_reports_| because UploadAll mutates |pending_reports_|.
      if (const auto pending = Size();
          reporting_policy_ == ReportingPolicy::kUpload && pending > 0) {
        const auto uploaded = UploadAll();
        if (uploaded > 0) {
          FX_LOGS(INFO) << fxl::StringPrintf(
              "Successfully uploaded %zu of %zu pending crash reports on network reachable ",
              uploaded, pending);
        } else {
          FX_LOGS(INFO) << fxl::StringPrintf(
              "Failed to upload any of the %zu pending crash reports on network reachable ",
              pending);
        }
      }
    }
  });
}

void Queue::UploadAllEveryFifteenMinutes() {
  if (stop_uploading_) {
    return;
  }

  // Save the size of |pending_reports_| because UploadAll mutates |pending_reports_|.
  if (const auto pending = Size(); reporting_policy_ == ReportingPolicy::kUpload && pending > 0) {
    const auto uploaded = UploadAll();
    if (uploaded > 0) {
      FX_LOGS(INFO) << fxl::StringPrintf(
          "Successfully uploaded %zu of %zu pending crash reports as part of the "
          "15-minute periodic upload",
          uploaded, pending);
    } else {
      FX_LOGS(INFO) << fxl::StringPrintf(
          "Failed to upload any of the %zu pending crash reports as part of the "
          "15-minute periodic upload",
          pending);
    }
  }
  if (const auto status =
          upload_all_every_fifteen_minutes_task_.PostDelayed(dispatcher_, zx::min(15));
      status != ZX_OK) {
    FX_PLOGS(ERROR, status) << "Error posting periodic upload task to async loop. Won't retry.";
  }
}

}  // namespace crash_reports
}  // namespace forensics
