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

#include <utility>

#include "absl/base/no_destructor.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/cord.h"
#include "absl/strings/string_view.h"
#include "cbor/options.h"
#include "jumbf/box_builder.h"
#include "jumbf/constants.h"
#include "proto/actions_assertion.cbor.h"
#include "proto/actions_assertion.pb.h"
#include "proto/assertion.pb.h"
#include "proto/bmff_based_hash_assertion.cbor.h"
#include "proto/bmff_based_hash_assertion.pb.h"
#include "proto/boxes_hash_assertion.cbor.h"
#include "proto/boxes_hash_assertion.pb.h"
#include "proto/collection_data_hash_assertion.cbor.h"
#include "proto/collection_data_hash_assertion.pb.h"
#include "proto/data_hash_assertion.cbor.h"
#include "proto/data_hash_assertion.pb.h"
#include "proto/ingredient_assertion.cbor.h"
#include "proto/ingredient_assertion.pb.h"
#include "proto/multi_asset_hash_assertion.cbor.h"

namespace credentio {

namespace {

template <typename ProtoType>
absl::StatusOr<absl::Cord> EncodeProtoToCbor(
    const ProtoType& proto, const cbor::FromProtoOptions& options) {
  ABSL_ASSIGN_OR_RETURN(auto cbor, cbor::FromProto(proto, options));
  return absl::Cord(cbor->toString());
}

}  // namespace

absl::StatusOr<absl::Cord> StandardAssertionEncoder::ToCbor(
    const Assertion& assertion) const {
  if (assertion.has_actions()) {
    return EncodeProtoToCbor(assertion.actions(), options_);
  }
  if (assertion.has_bmff_based_hash()) {
    return EncodeProtoToCbor(assertion.bmff_based_hash(), options_);
  }
  if (assertion.has_data_hash()) {
    return EncodeProtoToCbor(assertion.data_hash(), options_);
  }
  if (assertion.has_collection_data_hash()) {
    return EncodeProtoToCbor(assertion.collection_data_hash(), options_);
  }
  if (assertion.has_ingredient_v3()) {
    return EncodeProtoToCbor(assertion.ingredient_v3(), options_);
  }
  if (assertion.has_boxes_hash()) {
    return EncodeProtoToCbor(assertion.boxes_hash(), options_);
  }
  if (assertion.has_multi_asset_hash()) {
    return EncodeProtoToCbor(assertion.multi_asset_hash(), options_);
  }
  return absl::InvalidArgumentError("Assertion not supported.");
}

absl::StatusOr<jumbf::BuiltSuperBox> AssertionEncoder::ToJumbf(
    const Assertion& assertion) const {
  ABSL_ASSIGN_OR_RETURN(absl::Cord cbor_data, ToCbor(assertion));
  jumbf::SuperBoxBuilder assertion_builder(
      jumbf::kCborBoxTypeUuid, {.label = absl::Cord(assertion.label())});
  ABSL_RETURN_IF_ERROR(
      assertion_builder.AddContent(jumbf::kCborBoxType, std::move(cbor_data)));
  return std::move(assertion_builder).Finalize();  // NOLINT: rvalue method call
}

const AssertionEncoder& GetAssertionEncoder(
    bool skip_validity_checks_for_test) {
  static const absl::NoDestructor<StandardAssertionEncoder> encoder_for_test(
      /*skip_validity_checks_for_test=*/true);
  static const absl::NoDestructor<StandardAssertionEncoder> encoder(
      /*skip_validity_checks_for_test=*/false);
  return skip_validity_checks_for_test ? *encoder_for_test : *encoder;
}

}  // namespace credentio
