// 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/metadata.h"

#include <lib/zx/clock.h>
#include <lib/zx/time.h>
#include <zircon/utc.h>

#include <optional>
#include <set>

#include "src/developer/forensics/feedback_data/constants.h"
#include "src/developer/forensics/feedback_data/errors.h"
#include "src/developer/forensics/utils/cobalt/metrics.h"
#include "src/developer/forensics/utils/errors.h"
#include "src/lib/fxl/strings/split_string.h"
#include "third_party/rapidjson/include/rapidjson/document.h"
#include "third_party/rapidjson/include/rapidjson/prettywriter.h"
#include "third_party/rapidjson/include/rapidjson/rapidjson.h"
#include "third_party/rapidjson/include/rapidjson/stringbuffer.h"

namespace forensics {
namespace feedback_data {
namespace {

using namespace rapidjson;

std::set<std::string> kUtcMonotonicDifferenceAllowlist = {
    kAttachmentInspect,
    kAttachmentLogKernel,
    kAttachmentLogSystem,
};

std::set<std::string> kPreviousBootUtcMonotonicDifferenceAllowlist = {
    kAttachmentLogSystemPrevious,
};

std::string ToString(const enum AttachmentValue::State state) {
  switch (state) {
    case AttachmentValue::State::kComplete:
      return "complete";
    case AttachmentValue::State::kPartial:
      return "partial";
    case AttachmentValue::State::kMissing:
      return "missing";
  }
}

// Create a complete list set of annotations from the collected annotations and the allowlist.
Annotations AllAnnotations(const AnnotationKeys& allowlist,
                           const ::fpromise::result<Annotations>& annotations_result) {
  Annotations all_annotations;
  if (annotations_result.is_ok()) {
    all_annotations.insert(annotations_result.value().cbegin(), annotations_result.value().cend());
  }

  for (const auto& key : allowlist) {
    if (all_annotations.find(key) == all_annotations.end()) {
      // There is an annotation in the allowlist that was not produced by any provider. This
      // indicates a logical error on the Feedback-side.
      all_annotations.insert({key, Error::kLogicError});
    }
  }

  return all_annotations;
}

// Create a complete list set of attachments from the collected attachments and the allowlist.
Attachments AllAttachments(const AttachmentKeys& allowlist,
                           const ::fpromise::result<Attachments>& attachments_result) {
  Attachments all_attachments;
  if (attachments_result.is_ok()) {
    // Because attachments can contain large blobs of text and we only care about the state of the
    // attachment and its associated error, we don't copy the value of the attachment.
    for (const auto& [k, v] : attachments_result.value()) {
      switch (v.State()) {
        case AttachmentValue::State::kComplete:
          all_attachments.insert({k, AttachmentValue("")});
          break;
        case AttachmentValue::State::kPartial:
          all_attachments.insert({k, AttachmentValue("", v.Error())});
          break;
        case AttachmentValue::State::kMissing:
          all_attachments.insert({k, v});
          break;
      }
    }
  }

  for (const auto& key : allowlist) {
    if (all_attachments.find(key) == all_attachments.end()) {
      all_attachments.insert({key, AttachmentValue(Error::kLogicError)});
    }
  }

  return all_attachments;
}

void AddUtcMonotonicDifference(const std::optional<zx::duration>& utc_monotonic_difference,
                               Value* file, Document::AllocatorType& allocator) {
  if (!utc_monotonic_difference.has_value() || !file->IsObject() ||
      file->HasMember("utc_monotonic_difference_nanos") ||
      (file->HasMember("state") && (*file)["state"].IsString() &&
       (*file)["state"].GetString() == ToString(AttachmentValue::State::kMissing))) {
    return;
  }

  file->AddMember("utc_monotonic_difference_nanos",
                  Value().SetInt64(utc_monotonic_difference.value().get()), allocator);
}

void AddUtcMonotonicDifferences(
    const std::optional<zx::duration> utc_monotonic_difference,
    const std::optional<zx::duration> previous_boot_utc_monotonic_difference,
    Document* metadata_json) {
  if (!metadata_json->HasMember("files")) {
    return;
  }

  for (auto& file : (*metadata_json)["files"].GetObject()) {
    if (kUtcMonotonicDifferenceAllowlist.find(file.name.GetString()) !=
        kUtcMonotonicDifferenceAllowlist.end()) {
      AddUtcMonotonicDifference(utc_monotonic_difference, &file.value,
                                metadata_json->GetAllocator());
    }

    if (kPreviousBootUtcMonotonicDifferenceAllowlist.find(file.name.GetString()) !=
        kPreviousBootUtcMonotonicDifferenceAllowlist.end()) {
      AddUtcMonotonicDifference(previous_boot_utc_monotonic_difference, &file.value,
                                metadata_json->GetAllocator());
    }
  }
}

void AddAttachments(const AttachmentKeys& attachment_allowlist,
                    const ::fpromise::result<Attachments>& attachments_result,
                    Document* metadata_json) {
  if (attachment_allowlist.empty()) {
    return;
  }

  auto& allocator = metadata_json->GetAllocator();
  auto MakeValue = [&allocator](const std::string& v) { return Value(v, allocator); };

  for (const auto& [name, v] : AllAttachments(attachment_allowlist, attachments_result)) {
    Value file(kObjectType);

    file.AddMember("state", MakeValue(ToString(v.State())), allocator);
    if (v.HasError()) {
      file.AddMember("error", MakeValue(ToReason(v.Error())), allocator);
    }

    (*metadata_json)["files"].AddMember(MakeValue(name), file, allocator);
  }
}

void AddAnnotationsJson(const AnnotationKeys& annotation_allowlist,
                        const ::fpromise::result<Annotations>& annotations_result,
                        const bool missing_non_platform_annotations, Document* metadata_json) {
  const Annotations all_annotations = AllAnnotations(annotation_allowlist, annotations_result);

  bool has_non_platform = all_annotations.size() > annotation_allowlist.size();
  if (annotation_allowlist.empty() && !(has_non_platform || missing_non_platform_annotations)) {
    return;
  }

  auto& allocator = metadata_json->GetAllocator();
  auto MakeValue = [&allocator](const std::string& v) { return Value(v, allocator); };

  Value present(kArrayType);
  Value missing(kObjectType);

  size_t num_present_platform = 0u;
  size_t num_missing_platform = 0u;
  for (const auto& [k, v] : all_annotations) {
    if (annotation_allowlist.find(k) == annotation_allowlist.end()) {
      continue;
    }

    Value key(MakeValue(k));
    if (v.HasValue()) {
      present.PushBack(key, allocator);
      ++num_present_platform;
    } else {
      missing.AddMember(key, MakeValue(ToReason(v.Error())), allocator);
      ++num_missing_platform;
    }
  }

  if (has_non_platform || missing_non_platform_annotations) {
    if (!missing_non_platform_annotations) {
      present.PushBack("non-platform annotations", allocator);
    } else {
      missing.AddMember("non-platform annotations", "too many non-platfrom annotations added",
                        allocator);
    }
  }

  Value state;
  if (num_present_platform == annotation_allowlist.size() && !missing_non_platform_annotations) {
    state = "complete";
  } else if (num_missing_platform == annotation_allowlist.size() && !has_non_platform &&
             missing_non_platform_annotations) {
    state = "missing";
  } else {
    state = "partial";
  }

  Value annotations_json(kObjectType);
  annotations_json.AddMember("state", state, allocator);
  annotations_json.AddMember("missing annotations", missing, allocator);
  annotations_json.AddMember("present annotations", present, allocator);

  (*metadata_json)["files"].AddMember("annotations.json", annotations_json, allocator);
}

void AddLogRedactionCanary(const std::string& log_redaction_canary, Document* metadata_json) {
  auto& allocator = metadata_json->GetAllocator();
  Value lines(kArrayType);
  for (const std::string& line :
       fxl::SplitStringCopy(log_redaction_canary, "\n", fxl::WhiteSpaceHandling::kTrimWhitespace,
                            fxl::SplitResult::kSplitWantNonEmpty)) {
    lines.PushBack(Value(line, allocator), allocator);
  }

  metadata_json->AddMember("log_redaction_canary", lines, allocator);
}

}  // namespace

Metadata::Metadata(async_dispatcher_t* dispatcher, timekeeper::Clock* clock, RedactorBase* redactor,
                   const bool is_first_instance, const AnnotationKeys& annotation_allowlist,
                   const AttachmentKeys& attachment_allowlist)
    : log_redaction_canary_(redactor->UnredactedCanary()),
      annotation_allowlist_(annotation_allowlist),
      attachment_allowlist_(attachment_allowlist),
      utc_provider_(dispatcher, zx::unowned_clock(zx_utc_reference_get()), clock,
                    PreviousBootFile::FromCache(is_first_instance, kUtcMonotonicDifferenceFile)) {
  redactor->Redact(log_redaction_canary_);
}

std::string Metadata::MakeMetadata(const ::fpromise::result<Annotations>& annotations_result,
                                   const ::fpromise::result<Attachments>& attachments_result,
                                   const std::string& snapshot_uuid,
                                   bool missing_non_platform_annotations) {
  Document metadata_json(kObjectType);
  auto& allocator = metadata_json.GetAllocator();

  auto MetadataString = [&metadata_json]() {
    StringBuffer buffer;
    PrettyWriter<StringBuffer> writer(buffer);

    metadata_json.Accept(writer);

    return std::string(buffer.GetString());
  };

  // Insert all top-level fields
  metadata_json.AddMember("snapshot_version", Value(SnapshotVersion::kString, allocator),
                          allocator);
  metadata_json.AddMember("metadata_version", Value(Metadata::kVersion, allocator), allocator);
  metadata_json.AddMember("snapshot_uuid", Value(snapshot_uuid, allocator), allocator);
  metadata_json.AddMember("files", Value(kObjectType), allocator);
  AddLogRedactionCanary(log_redaction_canary_, &metadata_json);

  const bool has_non_platform_annotations =
      annotations_result.is_ok() &&
      annotations_result.value().size() > annotation_allowlist_.size();

  if (annotation_allowlist_.empty() && attachment_allowlist_.empty() &&
      !has_non_platform_annotations && !missing_non_platform_annotations) {
    return MetadataString();
  }

  AddAttachments(attachment_allowlist_, attachments_result, &metadata_json);
  AddAnnotationsJson(annotation_allowlist_, annotations_result, missing_non_platform_annotations,
                     &metadata_json);
  AddUtcMonotonicDifferences(utc_provider_.CurrentUtcMonotonicDifference(),
                             utc_provider_.PreviousBootUtcMonotonicDifference(), &metadata_json);

  return MetadataString();
}

}  // namespace feedback_data
}  // namespace forensics
