// Copyright 2020 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/feedback_data/attachments/system_log.h"

#include <fuchsia/logger/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/fit/result.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <memory>
#include <string>
#include <vector>

#include "src/developer/forensics/feedback_data/archive_accessor_ptr.h"
#include "src/developer/forensics/utils/errors.h"
#include "src/developer/forensics/utils/fit/promise.h"
#include "src/developer/forensics/utils/fit/timeout.h"
#include "src/developer/forensics/utils/log_format.h"
#include "src/lib/diagnostics/stream/cpp/log_message.h"
#include "src/lib/fxl/strings/join_strings.h"

namespace forensics {
namespace feedback_data {
namespace {

// A structured log message and the text errors that will appear after it.
struct LogMessage {
  std::optional<fuchsia::logger::LogMessage> message;
  std::vector<std::string> errors;
};

}  // namespace

::fit::promise<AttachmentValue> CollectSystemLog(async_dispatcher_t* dispatcher,
                                                 std::shared_ptr<sys::ServiceDirectory> services,
                                                 fit::Timeout timeout) {
  auto log_service =
      std::make_unique<ArchiveAccessor>(dispatcher, services, fuchsia::diagnostics::DataType::LOGS,
                                        fuchsia::diagnostics::StreamMode::SNAPSHOT);

  auto log_messages = std::make_shared<std::vector<LogMessage>>();

  // Add a text error to the last LogMessage in |log_messages|.
  auto AddError = [log_messages](const std::string& error) {
    if (log_messages->empty()) {
      log_messages->push_back(LogMessage{.message = std::nullopt, .errors = {}});
    }
    log_messages->back().errors.push_back(error);
  };

  // System log collection task.
  log_service->Collect([log_messages, AddError](fuchsia::diagnostics::FormattedContent chunk) {
    auto chunk_result = diagnostics::stream::ConvertFormattedContentToLogMessages(std::move(chunk));
    if (chunk_result.is_error()) {
      AddError(
          fxl::StringPrintf("!!! Failed to format chunk: %s !!!", chunk_result.error().c_str()));
      return;
    }

    for (auto& log_result : chunk_result.value()) {
      if (log_result.is_error()) {
        AddError(
            fxl::StringPrintf("!!! Failed to format chunk: %s !!!", log_result.error().c_str()));
        continue;
      }

      // Stable-sort |log_messages| by timestamp when adding a new message. If a message in
      // |log_messages| only has errors, assume the new message comes after it. Sorting is stable
      // and done on insertion because log messages are received mostly in order and messages with
      // the same timestamp should not be reordered.
      auto it = log_messages->crbegin();
      while (it != log_messages->crend() && it->message.has_value() &&
             log_result.value().time < it->message.value().time) {
        ++it;
      }
      log_messages->insert(it.base(), LogMessage{.message = log_result.take_value(), .errors = {}});
    }
  });

  // Post-collection task.
  ::fit::promise<AttachmentValue> log_promise =
      log_service->WaitForDone(std::move(timeout))
          .then(
              [log_messages](::fit::result<void, Error>& result) -> ::fit::result<AttachmentValue> {
                if (log_messages->empty()) {
                  FX_LOGS(WARNING) << "Empty system log";
                  AttachmentValue value = (result.is_ok()) ? AttachmentValue(Error::kMissingValue)
                                                           : AttachmentValue(result.error());
                  return ::fit::ok(std::move(value));
                }

                // Format the log messages by converting them to text and appending errors on their
                // own lines.
                std::vector<std::string> formatted_logs;
                for (const auto& log_message : *log_messages) {
                  std::string formatted =
                      (log_message.message.has_value()) ? Format(log_message.message.value()) : "";

                  if (!log_message.errors.empty()) {
                    formatted += fxl::JoinStrings(log_message.errors, "\n") + "\n";
                  }
                  formatted_logs.push_back(std::move(formatted));
                }

                std::string joined_data = fxl::JoinStrings(formatted_logs, "");

                AttachmentValue value =
                    (result.is_ok()) ? AttachmentValue(std::move(joined_data))
                                     : AttachmentValue(std::move(joined_data), result.error());

                return ::fit::ok(std::move(value));
              });

  return fit::ExtendArgsLifetimeBeyondPromise(/*promise=*/std::move(log_promise),
                                              /*args=*/std::move(log_service));
}

}  // namespace feedback_data
}  // namespace forensics
