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

#include <fuchsia/mem/cpp/fidl.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>
#include <zircon/errors.h>

#include <string>

#include "src/developer/forensics/crash_reports/constants.h"
#include "src/developer/forensics/crash_reports/errors.h"
#include "src/developer/forensics/crash_reports/report.h"

namespace forensics {
namespace crash_reports {

std::string Shorten(std::string program_name) {
  // Remove leading whitespace
  const size_t first_non_whitespace = program_name.find_first_not_of(" ");
  if (first_non_whitespace == std::string::npos) {
    return "";
  }
  program_name = program_name.substr(first_non_whitespace);

  // Remove the "fuchsia-pkg://" prefix if present.
  const std::string fuchsia_pkg_prefix("fuchsia-pkg://");
  if (program_name.find(fuchsia_pkg_prefix) == 0) {
    program_name.erase(/*pos=*/0u, /*len=*/fuchsia_pkg_prefix.size());
  }
  std::replace(program_name.begin(), program_name.end(), '/', ':');

  // Remove all repeating ':'.
  for (size_t idx = program_name.find("::"); idx != std::string::npos;
       idx = program_name.find("::")) {
    program_name.erase(idx, 1);
  }

  // Remove trailing white space
  const size_t last_non_whitespace = program_name.find_last_not_of(" ");
  return (last_non_whitespace == std::string::npos)
             ? ""
             : program_name.substr(0, last_non_whitespace + 1);
}

std::string Logname(std::string name) {
  // Normalize |name|.
  name = Shorten(name);

  // Find the last colon in |name|.
  const size_t last_colon = name.find_last_of(":");
  if (last_colon == std::string::npos) {
    return name;
  }

  // Determine if there's a ".cmx" suffix in |name|.
  const size_t cmx_suffix = name.find_last_of(".cmx");
  if (cmx_suffix == std::string::npos || cmx_suffix <= last_colon) {
    return name;
  }

  // Extract the string between the last colon and the ".cmx" suffix.
  return name.substr(last_colon + 1, cmx_suffix - sizeof(".cmx") - last_colon + 1);
}

namespace {

// The crash server expects a specific key for client-provided program uptimes.
const char kProgramUptimeMillisKey[] = "ptime";

// The crash server expects a specific key for client-provided event keys.
const char kEventIdKey[] = "comments";

// The crash server expects a specific key for client-provided crash signatures.
const char kCrashSignatureKey[] = "signature";

// The crash server expects specific key and values for some annotations and attachments for Dart.
const char kDartTypeKey[] = "type";
const char kDartTypeValue[] = "DartError";
const char kDartExceptionMessageKey[] = "error_message";
const char kDartExceptionRuntimeTypeKey[] = "error_runtime_type";
const char kDartExceptionStackTraceKey[] = "DartError";

// The crash server expects a specific key for client-provided report time.
constexpr char kReportTimeMillis[] = "reportTimeMillis";

// The crash server expects a specific key for client-provided information about whether a crash is
// fatal.
const char kIsFatalKey[] = "isFatal";

void ExtractAnnotationsAndAttachments(fuchsia::feedback::CrashReport report,
                                      AnnotationMap* annotations,
                                      std::map<std::string, fuchsia::mem::Buffer>* attachments,
                                      std::optional<fuchsia::mem::Buffer>* minidump,
                                      bool* should_process) {
  // Default annotations common to all crash reports.
  if (report.has_annotations()) {
    annotations->Set(report.annotations());
  }

  if (report.has_program_uptime()) {
    annotations->Set(kProgramUptimeMillisKey, zx::duration(report.program_uptime()).to_msecs());
  }

  if (report.has_event_id()) {
    annotations->Set(kEventIdKey, report.event_id());
  }

  if (report.has_crash_signature()) {
    annotations->Set(kCrashSignatureKey, report.crash_signature());
  }

  if (report.has_is_fatal()) {
    annotations->Set(kIsFatalKey, report.is_fatal());
  }

  // Generic-specific annotations.
  if (report.has_specific_report() && report.specific_report().is_generic()) {
    const auto& generic_report = report.specific_report().generic();
    if (generic_report.has_crash_signature()) {
      annotations->Set(kCrashSignatureKey, generic_report.crash_signature());
    }
  }

  // Dart-specific annotations.
  if (report.has_specific_report() && report.specific_report().is_dart()) {
    annotations->Set(kDartTypeKey, kDartTypeValue);

    const auto& dart_report = report.specific_report().dart();
    if (dart_report.has_exception_type()) {
      annotations->Set(kDartExceptionRuntimeTypeKey, dart_report.exception_type());
    } else {
      FX_LOGS(WARNING) << "no Dart exception type to attach to Crashpad report";
    }

    if (dart_report.has_exception_message()) {
      annotations->Set(kDartExceptionMessageKey, dart_report.exception_message());
    } else {
      FX_LOGS(WARNING) << "no Dart exception message to attach to Crashpad report";
    }
  }

  // Native-specific annotations.
  // TODO(fxbug.dev/6564): add module annotations from minidump.

  // Default attachments common to all crash reports.
  if (report.has_attachments()) {
    for (auto& attachment : *(report.mutable_attachments())) {
      (*attachments)[attachment.key] = std::move(attachment.value);
    }
  }

  // Native-specific attachment (minidump).
  if (report.has_specific_report() && report.specific_report().is_native()) {
    auto& native_report = report.mutable_specific_report()->native();
    if (native_report.has_minidump()) {
      *minidump = std::move(*native_report.mutable_minidump());
      *should_process = true;
    } else {
      FX_LOGS(WARNING) << "no minidump to attach to Crashpad report";
      annotations->Set(kCrashSignatureKey, "fuchsia-no-minidump");
    }
  }

  // Dart-specific attachment (text stack trace).
  if (report.has_specific_report() && report.specific_report().is_dart()) {
    auto& dart_report = report.mutable_specific_report()->dart();
    if (dart_report.has_exception_stack_trace()) {
      (*attachments)[kDartExceptionStackTraceKey] =
          std::move(*dart_report.mutable_exception_stack_trace());
      *should_process = true;
    } else {
      FX_LOGS(WARNING) << "no Dart exception stack trace to attach to Crashpad report";
      annotations->Set(kCrashSignatureKey, "fuchsia-no-dart-stack-trace");
    }
  }
}

void AddSnapshotAnnotations(const SnapshotUuid& snapshot_uuid, const Snapshot& snapshot,
                            AnnotationMap* annotations) {
  if (const auto snapshot_annotations = snapshot.LockAnnotations(); snapshot_annotations) {
    annotations->Set(*snapshot_annotations);
  }
}

void AddCrashServerAnnotations(const std::string& program_name,
                               const std::optional<zx::time_utc>& current_time,
                               const ::fit::result<std::string, Error>& device_id,
                               const Product& product, const bool should_process,
                               AnnotationMap* annotations) {
  // Product.
  annotations->Set("product", product.name)
      .Set("version", product.version)
      .Set("channel", product.channel);

  // Program.
  // We use ptype to benefit from Chrome's "Process type" handling in the crash server UI.
  annotations->Set("ptype", program_name);

  // We set the report time only if we were able to get an accurate one.
  if (current_time.has_value()) {
    annotations->Set(kReportTimeMillis, current_time.value().get() / zx::msec(1).get());
  } else {
    annotations->Set("debug.report-time.set", false);
  }

  // We set the device's global unique identifier only if the device has one.
  if (device_id.is_ok()) {
    annotations->Set("guid", device_id.value());
  } else {
    annotations->Set("debug.guid.set", false).Set("debug.device-id.error", device_id.error());
  }

  // Not all reports need to be processed by the crash server.
  // Typically only reports with a minidump or a Dart stack trace file need to be processed.
  annotations->Set("should_process", should_process);
}

}  // namespace

std::optional<Report> MakeReport(fuchsia::feedback::CrashReport report, const ReportId report_id,
                                 const SnapshotUuid& snapshot_uuid, const Snapshot& snapshot,
                                 const std::optional<zx::time_utc>& current_time,
                                 const ::fit::result<std::string, Error>& device_id,
                                 const AnnotationMap& default_annotations, const Product& product,
                                 const bool is_hourly_report) {
  const std::string program_name = report.program_name();
  const std::string shortname = Shorten(program_name);

  AnnotationMap annotations = default_annotations;
  std::map<std::string, fuchsia::mem::Buffer> attachments;
  std::optional<fuchsia::mem::Buffer> minidump;
  bool should_process = false;

  // Optional annotations and attachments filled by the client.
  ExtractAnnotationsAndAttachments(std::move(report), &annotations, &attachments, &minidump,
                                   &should_process);

  // Snapshot annotations specific to this crash report.
  AddSnapshotAnnotations(snapshot_uuid, snapshot, &annotations);

  // Crash server annotations common to all crash reports.
  AddCrashServerAnnotations(program_name, current_time, device_id, product, should_process,
                            &annotations);

  return Report::MakeReport(report_id, shortname, annotations, std::move(attachments),
                            snapshot_uuid, std::move(minidump), is_hourly_report);
}

}  // namespace crash_reports
}  // namespace forensics
