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

#include <cstdint>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/die_if_null.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 "claim/manifest_box.h"
#include "claim/manifest_store_builder.h"
#include "constants/ingredient_relationships.h"
#include "constants/labels.h"
#include "constants/spec_version.h"
#include "proto/actions_assertion.pb.h"
#include "proto/assertion.pb.h"
#include "proto/bmff_based_hash_assertion.pb.h"
#include "proto/boxes_hash_assertion.pb.h"
#include "proto/collection_data_hash_assertion.pb.h"
#include "proto/data_hash_assertion.pb.h"
#include "proto/generator.pb.h"
#include "proto/generator_info.pb.h"
#include "proto/hashed_uri.pb.h"
#include "proto/ingredient_assertion.pb.h"
#include "proto/ingredient_validation_result.pb.h"
#include "proto/multi_asset_hash_assertion.pb.h"
#include "utils/cbor_padding.h"

namespace credentio {
namespace {

absl::Status ValidateRequest(const GenerateManifestStoreRequest& request) {
  if (request.hard_binding().binding_case() == HardBinding::BINDING_NOT_SET) {
    return absl::InvalidArgumentError(
        "The request does not have a hard binding.");
  }
  for (const auto& gathered : request.gathered_assertions()) {
    if (gathered.label().empty()) {
      return absl::InvalidArgumentError(
          "Gathered assertion must have a non-empty label.");
    }
    if (gathered.content_type() ==
        GatheredAssertion::CONTENT_TYPE_UNSPECIFIED) {
      return absl::InvalidArgumentError(
          "Gathered assertion content type must be specified.");
    }
  }
  return absl::OkStatus();
}

void ConvertActionMetadata(const ActionMetadata& action_metadata,
                           ActionItem* action_item) {
  if (action_metadata.has_software_agent()) {
    *action_item->mutable_software_agent() = action_metadata.software_agent();
  }
  if (action_metadata.has_description()) {
    action_item->set_description(action_metadata.description());
  }
  if (action_metadata.has_multiple_instances()) {
    action_item->mutable_parameters()->set_multiple_instances(
        action_metadata.multiple_instances());
  }
}

absl::StatusOr<Assertion> ConvertIngredientAssertion(
    const IngredientInput& ingredient, absl::string_view label,
    absl::string_view relationship,
    const std::optional<IngredientManifestUris>& ingredient_uris,
    const std::optional<IngredientValidationResults>&
        ingredient_validation_results,
    const std::optional<std::string>& digital_source_type) {
  Assertion assertion;

  // Convert Assertion box fields.
  assertion.set_label(label);
  auto* ingredient_v3 = assertion.mutable_ingredient_v3();

  // Convert Ingredient Assertion V3 fields.
  if (ingredient.metadata().has_title()) {
    ingredient_v3->set_title(ingredient.metadata().title());
  }
  if (ingredient.metadata().has_media_type()) {
    ingredient_v3->set_media_type(ingredient.metadata().media_type());
  } else if (ingredient.ingredient_validation_results().has_media_type()) {
    ingredient_v3->set_media_type(
        ingredient.ingredient_validation_results().media_type());
  }
  ingredient_v3->set_relationship(relationship);
  if (ingredient.metadata().has_instance_id()) {
    ingredient_v3->set_instance_id(ingredient.metadata().instance_id());
  }
  if (ingredient.metadata().has_description()) {
    ingredient_v3->set_description(ingredient.metadata().description());
  }
  if (ingredient.metadata().has_informational_uri()) {
    ingredient_v3->set_informational_uri(
        ingredient.metadata().informational_uri());
  }
  if (ingredient_uris.has_value()) {
    // The ingredient URIs provided by the ManifestStoreBuilder should always
    // have the active manifest and claim signature URIs set.
    if (ingredient_uris->active_manifest.url().empty()) {
      return absl::InternalError(
          "Should not happen. Ingredient URI missing active manifest.");
    }
    *ingredient_v3->mutable_active_manifest() =
        ingredient_uris->active_manifest;
    if (ingredient_uris->claim_signature.url().empty()) {
      return absl::InternalError(
          "Should not happen. Ingredient URI missing claim signature.");
    }
    *ingredient_v3->mutable_claim_signature() =
        ingredient_uris->claim_signature;
  }
  if (ingredient_validation_results.has_value()) {
    *ingredient_v3->mutable_validation_results() =
        ingredient_validation_results.value();
  }
  if (digital_source_type.has_value()) {
    ingredient_v3->set_digital_source_type(*digital_source_type);
  }
  return assertion;
}

// An ingredient listed in a GenerateManifestStoreRequest.
class Ingredient {
 public:
  explicit Ingredient(std::string label, const IngredientInput* input)
      : label_(std::move(label)), input_(*ABSL_DIE_IF_NULL(input)) {}

  absl::Status SetRelationship(absl::string_view relationship) {
    if (relationship_.empty()) {
      relationship_ = relationship;
    } else if (relationship != relationship_) {
      return absl::InvalidArgumentError(
          absl::Substitute("Inconsistent use of ingredient ($0 and $1)",
                           relationship_, relationship));
    }
    return absl::OkStatus();
  }

  absl::string_view label() const { return label_; }
  absl::string_view relationship() const { return relationship_; }
  const IngredientInput& input() const { return input_; }

 private:
  const std::string label_;
  const IngredientInput& input_;
  absl::string_view relationship_;
};

// Creates an assertion label per
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_multiple_instances.
std::string CreateLabel(absl::string_view base_label, int index) {
  if (index == 0) {
    return std::string(base_label);
  }
  return absl::StrCat(base_label, "__", index);
}

class PartLabelProvider {
 public:
  absl::StatusOr<std::string> GetLabel(PartBinding::BindingCase binding_case) {
    absl::string_view base_label;
    switch (binding_case) {
      case PartBinding::kBmffBasedHash:
        base_label = kBmffBasedHashAssertionV3PartLabel;
        break;
      case PartBinding::kBoxHash:
        base_label = kBoxesHashAssertionPartLabel;
        break;
      case PartBinding::kDataHash:
        base_label = kDataHashAssertionPartLabel;
        break;
      default:
        return absl::InvalidArgumentError(
            absl::StrCat("Unsupported assertion type: ", binding_case));
    }
    return CreateLabel(base_label, assertion_type_to_count_[base_label]++);
  }

 private:
  absl::flat_hash_map<absl::string_view, int32_t> assertion_type_to_count_;
};

absl::Status AddMultiAssetHashToManifestBox(
    const GenerateManifestStoreRequest& request, ManifestBox& manifest_box) {
  if (request.hard_binding().part_bindings_size() == 0) {
    // Doesn't have any multi-asset hash assertion information.
    return absl::OkStatus();
  }

  Assertion& multi_asset_hash_assertion =
      manifest_box.multi_part_assertion.emplace();
  multi_asset_hash_assertion.set_label(kMultiAssetHashAssertionLabel);

  PartLabelProvider part_label_provider;
  for (const auto& part : request.hard_binding().part_bindings()) {
    Assertion& part_hash_assertion =
        manifest_box.part_hash_assertions.emplace_back();
    ABSL_ASSIGN_OR_RETURN(std::string label,
                          part_label_provider.GetLabel(part.binding_case()));
    part_hash_assertion.set_label(std::move(label));
    switch (part.binding_case()) {
      case PartBinding::kBmffBasedHash:
        *part_hash_assertion.mutable_bmff_based_hash() = part.bmff_based_hash();
        break;
      case PartBinding::kBoxHash:
        *part_hash_assertion.mutable_boxes_hash() = part.box_hash();
        PadBoxesHashAssertion(*part_hash_assertion.mutable_boxes_hash());
        break;
      case PartBinding::kDataHash:
        *part_hash_assertion.mutable_data_hash() = part.data_hash();
        PadDataHashAssertion(*part_hash_assertion.mutable_data_hash());
        break;
      default:
        return absl::InvalidArgumentError(
            absl::StrCat("Unsupported assertion type: ", part.binding_case()));
    }

    MultiAssetPart& multi_asset_part =
        *multi_asset_hash_assertion.mutable_multi_asset_hash()->add_parts();
    multi_asset_part.mutable_location()->set_byte_offset(
        part.location().byte_offset());
    multi_asset_part.mutable_location()->set_length(part.location().length());
    multi_asset_part.mutable_hash_assertion()->set_url(absl::StrCat(
        "self#jumbf=c2pa.assertions/", part_hash_assertion.label()));
    multi_asset_part.set_is_optional(part.is_optional());
  }

  PadMultiAssetHashAssertion(
      *multi_asset_hash_assertion.mutable_multi_asset_hash());

  return absl::OkStatus();
}

}  // namespace

// A single manifest box assembly operation.
class StandardManifestBoxAssembler::AssembleOp {
 public:
  explicit AssembleOp(const StandardManifestBoxAssembler& assembler,
                      const GenerateManifestStoreRequest& request)
      : assembler_(assembler), request_(request) {
    ingredients_.reserve(request.ingredients_size());
    for (int i = 0; i < request.ingredients_size(); ++i) {
      ingredients_.push_back(
          Ingredient(CreateLabel(kIngredientAssertionV3Label, i),
                     &request.ingredients(i)));
    }
  }

  absl::StatusOr<ManifestBox> Run() {
    ABSL_RETURN_IF_ERROR(ValidateRequest(request_));
    ManifestBox manifest_box = {.manifest_store_builder = ManifestStoreBuilder(
                                    &assembler_.hash_factory_)};
    manifest_box.label = absl::StrCat(
        "urn:c2pa:", assembler_.uuid_generator_.Generate().ToString());
    if (request_.has_instance_id()) {
      manifest_box.instance_id = request_.instance_id();
    } else {
      manifest_box.instance_id =
          assembler_.uuid_generator_.Generate().ToString();
    }

    // Convert hard binding assertion.
    {
      Assertion& hard_binding = manifest_box.hard_binding_assertion;
      if (request_.hard_binding().has_bmff_based_hash()) {
        hard_binding.set_label(kBmffBasedHashAssertionV3Label);
        *hard_binding.mutable_bmff_based_hash() =
            request_.hard_binding().bmff_based_hash();
      } else if (request_.hard_binding().has_box_hash()) {
        hard_binding.set_label(kBoxesHashAssertionLabel);
        *hard_binding.mutable_boxes_hash() = request_.hard_binding().box_hash();
        PadBoxesHashAssertion(*hard_binding.mutable_boxes_hash());
      } else if (request_.hard_binding().has_data_hash()) {
        hard_binding.set_label(kDataHashAssertionLabel);
        *hard_binding.mutable_data_hash() = request_.hard_binding().data_hash();
        PadDataHashAssertion(*hard_binding.mutable_data_hash());
      } else if (request_.hard_binding().has_collection_data_hash()) {
        hard_binding.set_label(kCollectionDataHashAssertionLabel);
        *hard_binding.mutable_collection_data_hash() =
            request_.hard_binding().collection_data_hash();
      }
    }

    ABSL_RETURN_IF_ERROR(
        AddMultiAssetHashToManifestBox(request_, manifest_box));

    // Process inception action.
    Assertion& actions_assertion = manifest_box.actions_assertion;
    ActionsAssertion& actions = *actions_assertion.mutable_actions();
    std::optional<int> opened_ingredient_index = std::nullopt;
    {
      actions_assertion.set_label(kActionsAssertionV2Label);
      if (request_.actions().has_all_actions_included()) {
        actions.set_all_actions_included(
            request_.actions().all_actions_included());
      }
      if (request_.actions().has_created()) {
        ABSL_RETURN_IF_ERROR(ConvertActionWithInputIngredients(
            "c2pa.created", request_.actions().created(),
            actions.add_actions()));
      } else if (request_.actions().has_opened()) {
        OpenedAction opened_action = request_.actions().opened();
        ABSL_RETURN_IF_ERROR(
            ConvertOpenedAction(opened_action, actions.add_actions()));
        opened_ingredient_index = opened_action.ingredient_index();
      } else {
        return absl::InvalidArgumentError(
            "missing inception action (created or opened)");
      }
    }

    // Process remaining actions.
    for (const auto& action : request_.actions().actions()) {
      switch (action.action_case()) {
        case Action::kAddedText:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.addedText", action.added_text(), actions.add_actions()));
          break;
        case Action::kAdjustedColor:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.adjustedColor", action.adjusted_color(),
              actions.add_actions()));
          break;
        case Action::kChangedSpeed:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.changedSpeed", action.changed_speed(),
              actions.add_actions()));
          break;
        case Action::kConverted:
          ABSL_RETURN_IF_ERROR(ConvertSimpleAction(
              "c2pa.converted", action.converted(), actions.add_actions()));
          break;
        case Action::kCropped:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.cropped", action.cropped(), actions.add_actions()));
          break;
        case Action::kDeleted:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.deleted", action.deleted(), actions.add_actions()));
          break;
        case Action::kDrawing:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.drawing", action.drawing(), actions.add_actions()));
          break;
        case Action::kDubbed:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.dubbed", action.dubbed(), actions.add_actions()));
          break;
        case Action::kEdited:
          ABSL_RETURN_IF_ERROR(ConvertActionWithInputIngredients(
              "c2pa.edited", action.edited(), actions.add_actions()));
          break;
        case Action::kEditedMetadata:
          ABSL_RETURN_IF_ERROR(ConvertSimpleAction("c2pa.edited.metadata",
                                                   action.edited_metadata(),
                                                   actions.add_actions()));
          break;
        case Action::kEnhanced:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.enhanced", action.enhanced(), actions.add_actions()));
          break;
        case Action::kFiltered:
          ABSL_RETURN_IF_ERROR(ConvertActionWithInputIngredients(
              "c2pa.filtered", action.filtered(), actions.add_actions()));
          break;
        case Action::kOrientation:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.orientation", action.orientation(), actions.add_actions()));
          break;
        case Action::kPlaced:
          ABSL_RETURN_IF_ERROR(
              ConvertPlacedAction(action.placed(), actions.add_actions()));
          break;
        case Action::kRepackaged:
          ABSL_RETURN_IF_ERROR(ConvertRepackagedAction(
              "c2pa.repackaged", action.repackaged(), actions.add_actions(),
              opened_ingredient_index));
          break;
        case Action::kResized:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.resized", action.resized(), actions.add_actions()));
          break;
        case Action::kTranscoded:
          ABSL_RETURN_IF_ERROR(ConvertTranscodedAction(
              "c2pa.transcoded", action.transcoded(), actions.add_actions(),
              opened_ingredient_index));
          break;
        case Action::kTrimmed:
          ABSL_RETURN_IF_ERROR(ConvertDigitalSourceTypeAction(
              "c2pa.trimmed", action.trimmed(), actions.add_actions()));
          break;
        case Action::kUnknown:
          ABSL_RETURN_IF_ERROR(ConvertSimpleAction(
              "c2pa.unknown", action.unknown(), actions.add_actions()));
          break;
        case Action::ACTION_NOT_SET:
          return absl::InvalidArgumentError("empty action");
      }
    }

    // Add redaction actions from ingredients.
    absl::flat_hash_set<absl::string_view> seen_redaction_uris;
    for (const auto& ingredient : ingredients_) {
      if (ingredient.input().has_ingredient_validation_results()) {
        const IngredientValidationResultProto& result =
            ingredient.input().ingredient_validation_results();
        for (const auto& redaction : result.redactions()) {
          // Currently, duplicate manifests are skipped in order of iteration
          // over `ingredients_`.
          if (!seen_redaction_uris.insert(redaction.uri()).second) {
            continue;
          }
          ActionItem* action = actions.add_actions();
          action->set_action("c2pa.redacted");
          action->set_reason(redaction.reason());
          action->mutable_parameters()->set_redacted_uri(redaction.uri());
        }
      }
    }

    // Import ingredients.
    for (const auto& ingredient : ingredients_) {
      ABSL_RETURN_IF_ERROR(
          ImportIngredient(ingredient, manifest_box.ingredient_assertions,
                           manifest_box.manifest_store_builder));
    }

    // Copy gathered assertions.
    manifest_box.gathered_assertions.assign(
        request_.gathered_assertions().begin(),
        request_.gathered_assertions().end());

    return manifest_box;
  }

 private:
  absl::StatusOr<Ingredient*> GetIngredient(int ingredient_index) {
    if (ingredient_index < 0 || ingredient_index >= ingredients_.size()) {
      return absl::InvalidArgumentError(
          absl::Substitute("ingredient index out of range [0, $0]: $1",
                           ingredients_.size(), ingredient_index));
    }
    return &ingredients_[ingredient_index];
  }

  absl::Status AddIngredientToAction(int ingredient_index,
                                     absl::string_view relationship,
                                     ActionItem* action_item) {
    ABSL_ASSIGN_OR_RETURN(Ingredient * ingredient,
                          GetIngredient(ingredient_index));
    ABSL_RETURN_IF_ERROR(ingredient->SetRelationship(relationship));
    action_item->mutable_parameters()->add_ingredients()->set_url(
        absl::StrCat(kAssertionStoreUrlPrefix, ingredient->label()));
    return absl::OkStatus();
  }

  absl::Status ConvertOpenedAction(const OpenedAction& action,
                                   ActionItem* action_item) {
    ABSL_RETURN_IF_ERROR(
        ConvertSimpleAction("c2pa.opened", action, action_item));
    if (!action.has_ingredient_index()) {
      return absl::InvalidArgumentError(
          "Opened action requires an ingredient index.");
    }
    return AddIngredientToAction(action.ingredient_index(),
                                 kIngredientRelationshipParentOf, action_item);
  }

  absl::Status ConvertPlacedAction(const PlacedAction& action,
                                   ActionItem* action_item) {
    ABSL_RETURN_IF_ERROR(
        ConvertSimpleAction("c2pa.placed", action, action_item));
    if (action.ingredient_indexes_size() == 0) {
      return absl::InvalidArgumentError("missing ingredients in placed action");
    }
    for (int ingredient_index : action.ingredient_indexes()) {
      ABSL_RETURN_IF_ERROR(AddIngredientToAction(
          ingredient_index, kIngredientRelationshipComponentOf, action_item));
    }
    return absl::OkStatus();
  }

  absl::Status ConvertTranscodedAction(
      absl::string_view name, const TranscodedAction& action,
      ActionItem* action_item, std::optional<int> opened_ingredient_index) {
    ABSL_RETURN_IF_ERROR(
        ConvertDigitalSourceTypeAction(name, action, action_item));
    if (opened_ingredient_index.has_value()) {
      // We add this redundant ingredient reference to satisfy 2.1 validators,
      // which require an ingredient reference in c2pa.transcoded and
      // c2pa.repackaged actions.
      return AddIngredientToAction(*opened_ingredient_index,
                                   kIngredientRelationshipParentOf,
                                   action_item);
    }
    return absl::OkStatus();
  }

  absl::Status ConvertRepackagedAction(
      absl::string_view name, const RepackagedAction& action,
      ActionItem* action_item, std::optional<int> opened_ingredient_index) {
    if (!opened_ingredient_index.has_value()) {
      return absl::InvalidArgumentError(
          absl::Substitute("$0 action requires an `opened` action.", name));
    }
    ABSL_RETURN_IF_ERROR(ConvertSimpleAction(name, action, action_item));
    // We add this redundant ingredient reference to satisfy 2.1 validators,
    // which require an ingredient reference in c2pa.transcoded and
    // c2pa.repackaged actions.
    return AddIngredientToAction(*opened_ingredient_index,
                                 kIngredientRelationshipParentOf, action_item);
  }

  // CreatedAction, EditedAction, FilteredAction.
  template <typename T>
  absl::Status ConvertActionWithInputIngredients(absl::string_view name,
                                                 const T& action,
                                                 ActionItem* action_item) {
    ABSL_RETURN_IF_ERROR(
        ConvertDigitalSourceTypeAction(name, action, action_item));
    for (int ingredient_index : action.input_ingredient_indexes()) {
      ABSL_RETURN_IF_ERROR(AddIngredientToAction(
          ingredient_index, kIngredientRelationshipInputTo, action_item));
    }
    return absl::OkStatus();
  }

  template <typename T>
  absl::Status ConvertDigitalSourceTypeAction(absl::string_view name,
                                              const T& action,
                                              ActionItem* action_item) {
    ABSL_RETURN_IF_ERROR(ConvertSimpleAction(name, action, action_item));
    if (action.has_digital_source_type()) {
      action_item->set_digital_source_type(action.digital_source_type());
    }
    return absl::OkStatus();
  }

  template <typename T>
  absl::Status ConvertSimpleAction(absl::string_view name, const T& action,
                                   ActionItem* action_item) {
    action_item->set_action(name);
    if (action.has_action_metadata()) {
      ConvertActionMetadata(action.action_metadata(), action_item);
    }
    return absl::OkStatus();
  }

  // Imports an ingredient's manifest store and creates an ingredient
  // assertion.
  absl::Status ImportIngredient(const Ingredient& ingredient,
                                std::vector<Assertion>& ingredient_assertions,
                                ManifestStoreBuilder& manifest_store_builder) {
    if (ingredient.relationship().empty()) {
      return absl::InvalidArgumentError(
          "ingredient is not referenced by any action.");
    }
    std::optional<IngredientManifestUris> ingredient_manifest_uris;
    std::optional<IngredientValidationResults> ingredient_validation_results;
    std::optional<std::string> digital_source_type;
    if (ingredient.input().has_ingredient_validation_results()) {
      const IngredientValidationResultProto& result =
          ingredient.input().ingredient_validation_results();
      if (result.has_legacy_ingredient_metadata()) {
        // Treat ingredients with unsupported manifests like ingredients without
        // C2PA at all.
      } else if (result.has_manifest_store_bytes()) {
        if (!result.has_ingredient_validation_results()) {
          return absl::InvalidArgumentError(
              "Ingredient manifest store validation results "
              "cannot be empty.");
        }
        ABSL_ASSIGN_OR_RETURN(ingredient_manifest_uris,
                              manifest_store_builder.AddIngredientManifestStore(
                                  result.manifest_store_bytes()),
                              _ << "adding ingredient manifest store");
        ingredient_validation_results = result.ingredient_validation_results();
      } else if (result.has_digital_source_type() &&
                 assembler_.spec_version_ >= SpecVersion::kC2pa_2_4) {
        digital_source_type = result.digital_source_type();
      }
    }

    ABSL_ASSIGN_OR_RETURN(
        Assertion ingredient_assertion,
        ConvertIngredientAssertion(
            ingredient.input(), ingredient.label(), ingredient.relationship(),
            ingredient_manifest_uris, ingredient_validation_results,
            digital_source_type));
    ingredient_assertions.push_back(ingredient_assertion);
    return absl::OkStatus();
  }

  const StandardManifestBoxAssembler& assembler_;
  const GenerateManifestStoreRequest& request_;
  std::vector<Ingredient> ingredients_;
};

absl::StatusOr<ManifestBox> StandardManifestBoxAssembler::Assemble(
    const GenerateManifestStoreRequest& request) const {
  AssembleOp op(*this, request);
  return op.Run();
}
}  // namespace credentio
