// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "bindings/validator.h"

#include <algorithm>
#include <cstdint>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <variant>
#include <vector>

#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/functional/function_ref.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "bindings/bmff_hash_hard_binding_validator.h"
#include "bindings/boxes_hash_hard_binding_validator.h"
#include "bindings/collection_data_hash_hard_binding_validator.h"
#include "bindings/data_hash_hard_binding_validator.h"
#include "constants/status_codes.h"
#include "formats/asset_box.h"
#include "formats/bmff/assessor.h"
#include "formats/bmff/box_header.h"
#include "formats/byte_range.h"
#include "formats/format.h"
#include "formats/registry.h"
#include "jumbf/uri.h"
#include "proto/assertion.pb.h"
#include "proto/bmff_based_hash_assertion.pb.h"
#include "proto/hashed_uri.pb.h"
#include "proto/manifest.pb.h"
#include "proto/multi_asset_hash_assertion.pb.h"
#include "proto/validation_result.pb.h"
#include "proto/validation_status.pb.h"
#include "riegeli/bytes/reader.h"
#include "utils/dual_status_tracker.h"
#include "utils/status_tracker.h"
#include "utils/two_stage_status_tracker.h"
#include "utils/uri.h"
#include "validator/result.h"
#include "validator/validation_result_internal.h"

namespace credentio {

namespace {

struct OffsetLocator {
  int64_t offset;
  int64_t length;
};

struct BmffLocator {
  std::string path;
};

absl::StatusOr<std::variant<OffsetLocator, BmffLocator>> GetLocator(
    const MultiAssetPartLocation& part) {
  if (!part.has_byte_offset() && !part.has_length() && !part.has_bmff_box()) {
    return absl::InvalidArgumentError("no location specified");
  }
  if (part.has_bmff_box() && (part.has_byte_offset() || part.has_length())) {
    return absl::InvalidArgumentError(
        "bmff box cannot be used with byte range locator");
  }
  if (part.has_bmff_box()) {
    return BmffLocator{.path = std::string(part.bmff_box())};
  }
  if (!part.has_byte_offset() || !part.has_length()) {
    return absl::InvalidArgumentError(
        "byte range locator must have both offset and length");
  }
  return OffsetLocator{.offset = part.byte_offset(), .length = part.length()};
}

std::unique_ptr<PartialValidationResultProto> CopyManifestLabels(
    const PartialValidationResultProto& source) {
  auto target = std::make_unique<PartialValidationResultProto>();
  target->set_hard_binding_uri(source.hard_binding_uri());
  target->set_multi_asset_hash_uri(source.multi_asset_hash_uri());

  target->mutable_active_manifest()->set_label(
      source.active_manifest().label());
  for (const Manifest& manifest : source.ingredient_manifests()) {
    target->add_ingredient_manifests()->set_label(manifest.label());
  }
  return target;
}

absl::StatusOr<std::unique_ptr<ValidationResultProto>>
CompleteValidationResults(
    std::unique_ptr<PartialValidationResultProto> target,
    std::unique_ptr<PartialValidationResultProto> source) {
  target->mutable_active_manifest()->mutable_validation()->MergeFrom(
      std::move(*source->mutable_active_manifest()->mutable_validation()));

  absl::flat_hash_map<absl::string_view, ValidationStatusSet> source_results;
  for (const Manifest& source_manifest : source->ingredient_manifests()) {
    source_results[source_manifest.label()] =
        std::move(source_manifest.validation());
  }
  for (Manifest& target_manifest : *target->mutable_ingredient_manifests()) {
    if (source_results.contains(target_manifest.label())) {
      target_manifest.mutable_validation()->MergeFrom(
          std::move(source_results[target_manifest.label()]));
    }
  }
  return MakeFullValidationResult(std::move(target));
}

// Validates the parts of a multi-asset hash assertion. This ensures that the
// parts do not overlap and that the total size of the required parts does not
// exceed the size of the asset. Only problems accessing the files return as
// non-OK status, other errors are recorded in the status tracker.
absl::Status ValidateParts(const MultiAssetHashAssertion& assertion,
                           absl::string_view assertion_uri, int64_t asset_size,
                           StatusTracker& tracker) {
  int64_t next_expected_offset = 0;
  int64_t minimum_required_size = 0;
  for (const auto& part : assertion.parts()) {
    absl::StatusOr<std::variant<OffsetLocator, BmffLocator>> locator =
        GetLocator(part.location());
    if (!locator.ok()) {
      tracker.RecordFailure(
          FailureStatusCode::kAssertionMultiAssetHashMalformed,
          {.url = assertion_uri});
      return absl::OkStatus();
    }
    if (std::holds_alternative<BmffLocator>(*locator)) {
      // Contains a BMFF locator, cannot ensure bytes included based on offsets.
      return absl::OkStatus();
    }
    OffsetLocator location = std::get<OffsetLocator>(*locator);
    if (location.offset != next_expected_offset) {
      tracker.RecordFailure(
          FailureStatusCode::kAssertionMultiAssetHashMalformed,
          {.url = assertion_uri});
      return absl::OkStatus();
    }
    next_expected_offset = location.offset + location.length;
    if (!part.is_optional()) {
      minimum_required_size += location.length;
    }
  }
  if (minimum_required_size > asset_size) {
    tracker.RecordFailure(
        FailureStatusCode::kAssertionMultiAssetHashMissingPart,
        {.url = assertion_uri});
  }
  return absl::OkStatus();
}

}  // namespace

absl::StatusOr<ContentBindingValidator::Structure>
ContentBindingValidator::ExtractAssetStructure(riegeli::Reader& contents,
                                               const Format* format,
                                               int64_t end_offset) const {
  ContentBindingValidator::Structure structure{
      .asset = ByteRange{.offset = contents.pos(),
                         .length = end_offset - contents.pos()}};

  absl::StatusOr<const Format*> inferred_format;
  if (format == nullptr) {
    inferred_format = format_registry_->GetFormat(contents);
    if (!inferred_format.ok()) {
      if (structure.asset.offset == 0) {
        // Invalid format on the first asset therefore unsupported format.
        return inferred_format.status();
      }
      return structure;
    }
    format = *inferred_format;
  }

  absl::StatusOr<std::vector<AssetBox>> boxes =
      format->extractor()->ExtractBoxes(contents, {.requires_c2pa = false});
  if (boxes.ok() && !boxes->empty()) {
    ABSL_ASSIGN_OR_RETURN(
        int64_t end_of_asset_offset,
        PopulateStructureFromBoxes(*std::move(boxes), structure));

    // Only assets which contain boxes can support multiple assets (by finding
    // the c2pa.after box). Navigate to the start of the next potential asset
    // and continue to extract the structure.
    if (!contents.Seek(end_of_asset_offset) ||
        contents.pos() != end_of_asset_offset) {
      return contents.StatusOrAnnotate(
          absl::InternalError("failed to seek to end of asset"));
    }
    return structure;
  }

  // The determined format does not support multiple assets at this point,
  // attempt to find the manifest store location and treat the remainder of
  // the file as the last asset.
  absl::StatusOr<std::optional<ByteRange>> manifest_store_location =
      format->extractor()->ExtractManifestStoreLocation(
          contents, {.requires_c2pa = false, .end_offset = end_offset});
  if (manifest_store_location.ok() && manifest_store_location->has_value()) {
    structure.manifest_store_location = *std::move(manifest_store_location);
  }

  return structure;
}

absl::StatusOr<int64_t> ContentBindingValidator::PopulateStructureFromBoxes(
    std::vector<AssetBox> boxes,
    ContentBindingValidator::Structure& structure) const {
  if (boxes.empty()) {
    return absl::InvalidArgumentError("no boxes found");
  }

  structure.boxes = std::move(boxes);

  const AssetBox* last_box = nullptr;
  for (const AssetBox& box : structure.boxes) {
    last_box = &box;

    if (box.identifier == "C2PA") {
      structure.manifest_store_location = ByteRange{
          .offset = box.byte_range.offset, .length = box.byte_range.length};
    }
  }

  if (last_box != nullptr && last_box->identifier == "c2pa.after") {
    structure.asset.length =
        last_box->byte_range.offset - structure.asset.offset;
  }

  return structure.asset.offset + structure.asset.length;
}

absl::StatusOr<std::vector<ContentBindingValidator::Structure>>
ContentBindingValidator::GetStructure(riegeli::Reader& contents,
                                      const Format& format) const {
  std::vector<ContentBindingValidator::Structure> structures;

  if (!contents.SupportsSize() || !contents.Size().has_value()) {
    return absl::InvalidArgumentError("asset does not support size");
  }

  if (contents.Size() == 0) {
    return absl::InvalidArgumentError("asset has no contents");
  }

  if (!contents.Seek(0) || contents.pos() != 0) {
    return contents.StatusOrAnnotate(
        absl::InternalError("failed to seek to start of asset"));
  }

  uint64_t end_offset = *contents.Size();
  bool at_end_of_file = false;
  while (!at_end_of_file) {
    // Format is always inferred for non-first parts.
    const Format* part_format = structures.empty() ? &format : nullptr;
    ABSL_ASSIGN_OR_RETURN(
        ContentBindingValidator::Structure structure,
        ExtractAssetStructure(contents, part_format, end_offset));

    at_end_of_file =
        (structure.asset.offset + structure.asset.length) == end_offset;

    structures.push_back(std::move(structure));
  }

  return structures;
}

absl::StatusOr<std::unique_ptr<ValidationResultProto>>
ContentBindingValidator::Validate(riegeli::Reader& contents,
                                  const Format& format,
                                  std::unique_ptr<PartialValidationResultProto>
                                      partial_validation_result) const {
  std::unique_ptr<PartialValidationResultProto> result =
      CopyManifestLabels(*partial_validation_result);
  ABSL_ASSIGN_OR_RETURN(
      std::unique_ptr<DualStatusTracker> tracker,
      DualStatusTracker::FromPartialValidationResult(&*result));
  bool assertion_in_ingredient_manifest = tracker->WritesToIngredientManifest();
  TwoStageStatusTracker staging_tracker(*tracker);

  ABSL_ASSIGN_OR_RETURN(
      std::vector<ContentBindingValidator::Structure> asset_structure,
      GetStructure(contents, format));
  auto assertion_fetcher = [&](absl::string_view uri) {
    return GetAssertion(partial_validation_result.get(), uri);
  };
  // Getting the structure causes the Tell to be at the end of the file, reset.
  if (!contents.Seek(0) || contents.pos() != 0) {
    return contents.StatusOrAnnotate(
        absl::InternalError("failed to seek to start of asset"));
  }
  ABSL_RETURN_IF_ERROR(ValidateAssertion(
      contents, assertion_fetcher,
      partial_validation_result->hard_binding_uri(), asset_structure,
      /*requires_c2pa=*/true, staging_tracker,
      assertion_in_ingredient_manifest));

  if (!staging_tracker.HasFailuresInStage1() ||
      partial_validation_result->multi_asset_hash_uri().empty()) {
    // Success or no multi-asset hard binding, finished.
    staging_tracker.WriteStage1();
    return CompleteValidationResults(std::move(partial_validation_result),
                                     std::move(result));
  }

  staging_tracker.MoveStage1ToStage2();

  // Validate the multi-asset hard binding assertion.
  if (!contents.Seek(0) || contents.pos() != 0) {
    return contents.StatusOrAnnotate(
        absl::InternalError("failed to seek to start of asset"));
  }
  ABSL_RETURN_IF_ERROR(ValidateAssertion(
      contents, assertion_fetcher,
      partial_validation_result->multi_asset_hash_uri(), asset_structure,
      /*requires_c2pa=*/true, staging_tracker,
      assertion_in_ingredient_manifest));
  if (staging_tracker.HasFailuresInStage1()) {
    // Failed, add all the staged codes to the result.
    staging_tracker.WriteStage2();
  }
  staging_tracker.WriteStage1();
  return CompleteValidationResults(std::move(partial_validation_result),
                                   std::move(result));
}

absl::Status ContentBindingValidator::ValidateAssertion(
    riegeli::Reader& contents, AssertionFetcherRef assertion_fetcher,
    absl::string_view assertion_uri,
    std::vector<ContentBindingValidator::Structure> asset_structure,
    bool requires_c2pa, TwoStageStatusTracker& tracker,
    bool assertion_in_ingredient_manifest, int64_t end_offset) const {
  const Assertion* absl_nullable assertion = assertion_fetcher(assertion_uri);
  if (assertion == nullptr) {
    return absl::InvalidArgumentError(
        absl::StrCat("missing assertion: ", assertion_uri));
  }

  switch (assertion->assertion_case()) {
    case Assertion::kBoxesHash:
      if (asset_structure.empty()) {
        return absl::InvalidArgumentError(
            "asset structure cannot be determined");
      }
      return ValidateBoxesHash(contents, assertion_uri, assertion->boxes_hash(),
                               asset_structure, requires_c2pa, tracker,
                               end_offset);
    case Assertion::kDataHash:
      return ValidateDataHash(
          contents, assertion_uri, assertion->data_hash(),
          asset_structure.empty()
              ? std::nullopt
              : asset_structure.front().manifest_store_location,
          requires_c2pa, tracker, assertion_in_ingredient_manifest, end_offset);
    case Assertion::kCollectionDataHash:
      return ValidateCollectionDataHash(contents, assertion_uri,
                                        assertion->collection_data_hash(),
                                        requires_c2pa, tracker);
    case Assertion::kBmffBasedHash:
      return ValidateBmffHash(contents, assertion_uri,
                              assertion->bmff_based_hash(), requires_c2pa,
                              tracker);
    case Assertion::kMultiAssetHash:
      return ValidateMultiAssetHash(
          contents, assertion_uri, assertion->multi_asset_hash(),
          asset_structure, requires_c2pa, assertion_fetcher, tracker,
          assertion_in_ingredient_manifest);
    default:
      return absl::InvalidArgumentError(
          absl::StrCat("assertion is not a hard binding assertion: ",
                       assertion->assertion_case()));
  }
}

absl::Status ContentBindingValidator::ValidateDataHash(
    riegeli::Reader& contents, absl::string_view assertion_uri,
    const DataHashAssertion& assertion,
    std::optional<ByteRange> manifest_store_location, bool requires_c2pa,
    StatusTracker& tracker, bool assertion_in_ingredient_manifest,
    int64_t end_offset) const {
  DataHashHardBindingValidator().Validate(
      contents, manifest_store_location, assertion, assertion_uri, tracker,
      assertion_in_ingredient_manifest, contents.pos(), end_offset);
  return absl::OkStatus();
}

absl::Status ContentBindingValidator::ValidateCollectionDataHash(
    riegeli::Reader& contents, absl::string_view assertion_uri,
    const CollectionDataHashAssertion& assertion, bool requires_c2pa,
    StatusTracker& tracker) const {
  CollectionDataHashHardBindingValidator().Validate(contents, assertion,
                                                    assertion_uri, tracker);
  return absl::OkStatus();
}

absl::Status ContentBindingValidator::ValidateBoxesHash(
    riegeli::Reader& contents, absl::string_view assertion_uri,
    const BoxesHashAssertion& assertion,
    std::vector<ContentBindingValidator::Structure> remaining_structure,
    bool requires_c2pa, StatusTracker& tracker, int64_t end_offset) const {
  if (assertion.boxes().empty()) {
    // No boxes in assertion.
    tracker.RecordFailure(FailureStatusCode::kAssertionBoxesHashMalformed,
                          {.url = assertion_uri});
    return absl::OkStatus();
  }
  for (const auto& box : assertion.boxes()) {
    if (box.names().empty()) {
      // Boxes Assertion has no names.
      tracker.RecordFailure(FailureStatusCode::kAssertionBoxesHashMalformed,
                            {.url = assertion_uri});
      return absl::OkStatus();
    }
  }
  bool assertion_has_c2pa_after =
      *assertion.boxes().rbegin()->names().rbegin() == "c2pa.after";

  if (remaining_structure.empty()) {
    // No Asset Data.
    tracker.RecordFailure(FailureStatusCode::kAssertionBoxesHashMismatch,
                          {.url = assertion_uri});
    return absl::OkStatus();
  }
  std::vector<AssetBox> asset_boxes = remaining_structure.front().boxes;
  if (asset_boxes.empty()) {
    // No boxes in asset.
    tracker.RecordFailure(FailureStatusCode::kAssertionBoxesHashMismatch,
                          {.url = assertion_uri});
    return absl::OkStatus();
  }
  bool extraction_has_c2pa_after =
      asset_boxes.back().identifier == "c2pa.after";

  if (!assertion_has_c2pa_after && extraction_has_c2pa_after) {
    int64_t part_idx = 1;
    while (part_idx < remaining_structure.size() &&
           !remaining_structure[part_idx].boxes.empty()) {
      // Remove the c2pa.after box.
      asset_boxes.pop_back();

      // Add the boxes from the next asset.
      Structure& next_asset = remaining_structure[part_idx];
      asset_boxes.reserve(asset_boxes.size() + next_asset.boxes.size());
      asset_boxes.insert(asset_boxes.end(), next_asset.boxes.begin(),
                         next_asset.boxes.end());

      // Increment the index to the next asset.
      ++part_idx;
    }
  }

  BoxesHashHardBindingValidator().Validate(contents, asset_boxes, assertion,
                                           assertion_uri, tracker);
  return absl::OkStatus();
}

absl::Status ContentBindingValidator::ValidateBmffHash(
    riegeli::Reader& contents, absl::string_view assertion_uri,
    const BmffBasedHashAssertion& assertion, bool requires_c2pa,
    StatusTracker& tracker) const {
  BmffHashHardBindingValidator().Validate(contents, assertion, assertion_uri,
                                          tracker);
  return absl::OkStatus();
}

absl::Status ContentBindingValidator::ValidateMultiAssetHash(
    riegeli::Reader& contents, absl::string_view assertion_uri,
    const MultiAssetHashAssertion& assertion,
    std::vector<ContentBindingValidator::Structure> asset_structure,
    bool requires_c2pa, AssertionFetcherRef assertion_fetcher,
    TwoStageStatusTracker& tracker,
    bool assertion_in_ingredient_manifest) const {
  bool recorded_multi_asset_failure = false;
  int64_t max_offset_validated = 0;

  if (!contents.SupportsSize() || !contents.Size().has_value()) {
    return absl::InvalidArgumentError(
        "multi-asset hash requires an asset with a known size");
  }
  uint64_t asset_size = *contents.Size();

  // multi-asset hash should drop all `c2pa.after` boxes
  for (auto& structure : asset_structure) {
    if (!structure.boxes.empty()) {
      if (structure.boxes.back().identifier == "c2pa.after") {
        structure.boxes.pop_back();
      }
    }
  }

  ABSL_RETURN_IF_ERROR(
      ValidateParts(assertion, assertion_uri, asset_size, tracker));
  if (tracker.HasFailuresInStage1()) {
    // No need to validate if we already have failures.
    return absl::OkStatus();
  }

  TwoStageStatusTracker multi_asset_tracker(
      *static_cast<StatusTracker*>(&tracker));

  for (int part_index = 0; part_index < assertion.parts_size(); ++part_index) {
    const auto& part = assertion.parts(part_index);
    ABSL_ASSIGN_OR_RETURN(auto locator, GetLocator(part.location()));

    std::optional<int64_t> offset = std::nullopt;
    std::optional<int64_t> length = std::nullopt;

    if (std::holds_alternative<OffsetLocator>(locator)) {
      OffsetLocator location = std::get<OffsetLocator>(locator);
      offset = location.offset;
      length = location.length;
    } else {
      BmffLocator location = std::get<BmffLocator>(locator);

      if (!contents.Seek(0) || contents.pos() != 0) {
        return contents.StatusOrAnnotate(
            absl::InternalError("failed to seek to start of asset"));
      }
      ABSL_ASSIGN_OR_RETURN(bool is_supported,
                            BmffAssessor().IsSupported(contents));
      if (!is_supported) {
        return absl::InvalidArgumentError(
            "Uses a BMFF locator, but file is not a BMFF file");
      }
      ABSL_RETURN_IF_ERROR(IterateOverBmffBoxes(
          contents, [&location, &offset, &length](const BmffBoxHeader& header) {
            if (header.xpath == location.path) {
              offset = header.start;
              length = header.box_size;
              return false;  // Terminate loop
            }
            return true;  // Continue
          }));
      if (!offset.has_value()) {
        // Did not find the location
        multi_asset_tracker.RecordFailure(
            FailureStatusCode::kAssertionMultiAssetHashMalformed,
            {.url = assertion_uri});
        recorded_multi_asset_failure = true;
      }
    }

    if (!offset.has_value() || !length.has_value()) {
      multi_asset_tracker.RecordFailure(
          FailureStatusCode::kAssertionMultiAssetHashMissingPart,
          {.url = assertion_uri,
           .explanation =
               absl::Substitute("missing location for part $0 of $1",
                                part_index + 1, assertion.parts_size())});
      recorded_multi_asset_failure = true;
      if (part.is_optional()) {
        multi_asset_tracker.MoveStage1ToStage2();
      } else {
        multi_asset_tracker.WriteStage1();
      }
      requires_c2pa = false;
      continue;
    }

    if (!contents.Seek(*offset) || contents.pos() != *offset ||
        (*offset + *length) > asset_size) {
      multi_asset_tracker.RecordFailure(
          FailureStatusCode::kAssertionMultiAssetHashMissingPart,
          {.url = assertion_uri,
           .explanation =
               absl::Substitute("missing data for part $0 of $1",
                                part_index + 1, assertion.parts_size())});
      if (part.is_optional()) {
        multi_asset_tracker.MoveStage1ToStage2();
      } else {
        multi_asset_tracker.WriteStage1();
      }
      requires_c2pa = false;
      continue;
    }

    ABSL_ASSIGN_OR_RETURN(absl::string_view manifest_label,
                          GetManifestLabelFromAbsoluteUri(assertion_uri));
    ABSL_ASSIGN_OR_RETURN(std::string part_hash_assertion_path,
                          jumbf::UriResolver::GetAbsolutePathFromUri(
                              part.hash_assertion().url(),
                              absl::StrCat("/c2pa/", manifest_label)));
    std::string part_hash_assertion_uri =
        absl::StrCat("self#jumbf=", part_hash_assertion_path);

    std::vector<ContentBindingValidator::Structure> part_structure =
        (asset_structure.size() - 1) < part_index
            ? std::vector<ContentBindingValidator::Structure>{}
            : std::vector<ContentBindingValidator::Structure>(
                  asset_structure.begin() + part_index, asset_structure.end());
    ABSL_RETURN_IF_ERROR(
        ValidateAssertion(contents, assertion_fetcher, part_hash_assertion_uri,
                          part_structure, requires_c2pa, multi_asset_tracker,
                          assertion_in_ingredient_manifest, *offset + *length));

    if (part.is_optional()) {
      if (multi_asset_tracker.HasFailuresInStage1()) {
        // Optional, but failed, move to stage 2.
        multi_asset_tracker.MoveStage1ToStage2();
      } else {
        // Optional, but succeeded, write.
        multi_asset_tracker.WriteStage1();
        max_offset_validated =
            std::max(max_offset_validated, *offset + *length);
      }
    } else {
      if (multi_asset_tracker.HasFailuresInStage1()) {
        // Encountered a failure, but not optional, write all status codes.
        multi_asset_tracker.WriteStage2();
      }
      multi_asset_tracker.WriteStage1();
      max_offset_validated = std::max(max_offset_validated, *offset + *length);
    }

    // We only need to ensure C2PA exists on the first part.
    requires_c2pa = false;
  }

  if (!recorded_multi_asset_failure && max_offset_validated != asset_size) {
    // Less than the whole file was validated, if the whole file was read it's
    // a mismatch, otherwise it's malformed.
    multi_asset_tracker.RecordFailure(
        contents.pos() == asset_size
            ? FailureStatusCode::kAssertionMultiAssetHashMismatch
            : FailureStatusCode::kAssertionMultiAssetHashMalformed,
        {.url = assertion_uri});
    recorded_multi_asset_failure = true;
  }

  // Write all status codes to the tracker.
  multi_asset_tracker.WriteStage1();
  if (tracker.HasFailuresInStage1()) {
    // Failures were added during validation, write all stage two codes.
    multi_asset_tracker.WriteStage2();
    if (!recorded_multi_asset_failure) {
      tracker.RecordFailure(FailureStatusCode::kAssertionMultiAssetHashMismatch,
                            {.url = assertion_uri});
    }
  } else {
    tracker.RecordSuccess(SuccessStatusCode::kAssertionMultiAssetHashMatch,
                          {.url = assertion_uri});
  }
  return absl::OkStatus();
}

}  // namespace credentio
