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

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>

#include "absl/functional/any_invocable.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 "absl/strings/substitute.h"
#include "async/async_context.h"
#include "cbor/options.h"
#include "claim/manifest_box.h"
#include "claim/manifest_box_encoder.h"
#include "claim/manifest_store_view.h"
#include "cose/sig_structure.h"
#include "generator/manifest_store_transformer.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/generator.pb.h"
#include "utils/cbor_padding.h"

namespace credentio {

namespace {

// Current default limit on manifest store size in our validator is 10 MiB.
// Some PNG parsing code elsewhere fails if the manifest store is > 7.6 MiB.
constexpr int64_t kDefaultMaxManifestStoreSizeBytes = 7 * 1024 * 1024;  // 7 MiB

template <typename T>
absl::StatusOr<size_t> GetCborSize(const T& proto,
                                   const cbor::FromProtoOptions& options) {
  ABSL_ASSIGN_OR_RETURN(auto cbor, cbor::FromProto(proto, options));
  return cbor->toString().size();
}

absl::Status CheckIfPartBindingByteSizesMatched(
    const PartBinding& template_part_binding,
    const PartBinding& finalize_part_binding,
    const cbor::FromProtoOptions& proto_to_cbor_options) {
  size_t template_size;
  size_t finalize_size;
  switch (template_part_binding.binding_case()) {
    case PartBinding::kBmffBasedHash: {
      ABSL_ASSIGN_OR_RETURN(template_size,
                            GetCborSize(template_part_binding.bmff_based_hash(),
                                        proto_to_cbor_options));
      ABSL_ASSIGN_OR_RETURN(finalize_size,
                            GetCborSize(finalize_part_binding.bmff_based_hash(),
                                        proto_to_cbor_options));
      break;
    }
    case PartBinding::kBoxHash: {
      BoxesHashAssertion template_boxes_hash = template_part_binding.box_hash();
      BoxesHashAssertion finalize_boxes_hash = finalize_part_binding.box_hash();
      PadBoxesHashAssertion(template_boxes_hash);
      PadBoxesHashAssertion(finalize_boxes_hash);
      ABSL_ASSIGN_OR_RETURN(template_size, GetCborSize(template_boxes_hash,
                                                       proto_to_cbor_options));
      ABSL_ASSIGN_OR_RETURN(finalize_size, GetCborSize(finalize_boxes_hash,
                                                       proto_to_cbor_options));
      break;
    }
    case PartBinding::kDataHash: {
      DataHashAssertion template_data_hash = template_part_binding.data_hash();
      DataHashAssertion finalize_data_hash = finalize_part_binding.data_hash();
      PadDataHashAssertion(template_data_hash);
      PadDataHashAssertion(finalize_data_hash);
      ABSL_ASSIGN_OR_RETURN(template_size, GetCborSize(template_data_hash,
                                                       proto_to_cbor_options));
      ABSL_ASSIGN_OR_RETURN(finalize_size, GetCborSize(finalize_data_hash,
                                                       proto_to_cbor_options));
      break;
    }
    case PartBinding::BINDING_NOT_SET:
      return absl::InvalidArgumentError(
          "A part binding in the finalize request must be set");
  }
  if (template_size != finalize_size) {
    return absl::InvalidArgumentError(
        "The part binding differs from template in unsupported ways.");
  }
  return absl::OkStatus();
}

absl::Status CheckIfHardBindingByteSizesMatched(
    const HardBinding& template_hard_binding,
    const HardBinding& finalize_hard_binding,
    const cbor::FromProtoOptions& proto_to_cbor_options) {
  size_t template_size;
  size_t finalize_size;
  switch (template_hard_binding.binding_case()) {
    case HardBinding::kBmffBasedHash: {
      ABSL_ASSIGN_OR_RETURN(template_size,
                            GetCborSize(template_hard_binding.bmff_based_hash(),
                                        proto_to_cbor_options));
      ABSL_ASSIGN_OR_RETURN(finalize_size,
                            GetCborSize(finalize_hard_binding.bmff_based_hash(),
                                        proto_to_cbor_options));
      break;
    }
    case HardBinding::kBoxHash: {
      BoxesHashAssertion template_boxes_hash = template_hard_binding.box_hash();
      BoxesHashAssertion finalize_boxes_hash = finalize_hard_binding.box_hash();
      PadBoxesHashAssertion(template_boxes_hash);
      PadBoxesHashAssertion(finalize_boxes_hash);
      ABSL_ASSIGN_OR_RETURN(template_size, GetCborSize(template_boxes_hash,
                                                       proto_to_cbor_options));
      ABSL_ASSIGN_OR_RETURN(finalize_size, GetCborSize(finalize_boxes_hash,
                                                       proto_to_cbor_options));
      break;
    }
    case HardBinding::kDataHash: {
      DataHashAssertion template_data_hash = template_hard_binding.data_hash();
      DataHashAssertion finalize_data_hash = finalize_hard_binding.data_hash();
      PadDataHashAssertion(template_data_hash);
      PadDataHashAssertion(finalize_data_hash);
      ABSL_ASSIGN_OR_RETURN(template_size, GetCborSize(template_data_hash,
                                                       proto_to_cbor_options));
      ABSL_ASSIGN_OR_RETURN(finalize_size, GetCborSize(finalize_data_hash,
                                                       proto_to_cbor_options));
      break;
    }
    case HardBinding::kCollectionDataHash: {
      ABSL_ASSIGN_OR_RETURN(
          template_size,
          GetCborSize(template_hard_binding.collection_data_hash(),
                      proto_to_cbor_options));
      ABSL_ASSIGN_OR_RETURN(
          finalize_size,
          GetCborSize(finalize_hard_binding.collection_data_hash(),
                      proto_to_cbor_options));
      break;
    }
    case HardBinding::BINDING_NOT_SET:
      return absl::InvalidArgumentError(
          "The hard binding in the finalize request must be set");
  }
  if (template_size != finalize_size) {
    return absl::InvalidArgumentError(
        "The final hard binding differs from template in unsupported ways.");
  }

  if (template_hard_binding.part_bindings_size() !=
      finalize_hard_binding.part_bindings_size()) {
    return absl::InvalidArgumentError(
        "The number of part bindings differs between template and finalize.");
  }

  for (int i = 0; i < template_hard_binding.part_bindings_size(); ++i) {
    ABSL_RETURN_IF_ERROR(CheckIfPartBindingByteSizesMatched(
        template_hard_binding.part_bindings(i),
        finalize_hard_binding.part_bindings(i), proto_to_cbor_options));
  }
  return absl::OkStatus();
}

absl::StatusOr<bool> HasActiveClaimTimestamp(absl::string_view manifest_store) {
  ABSL_ASSIGN_OR_RETURN(ManifestStoreView view,
                        ManifestStoreView::Create(manifest_store));
  ABSL_ASSIGN_OR_RETURN(ManifestView manifest, view.GetActiveManifest());
  ABSL_ASSIGN_OR_RETURN(ClaimSignatureView claim_signature,
                        manifest.GetClaimSignature());
  ABSL_ASSIGN_OR_RETURN(CoseSign1TaggedStructure cose_sign1,
                        claim_signature.GetStruct());
  return cose_sign1.unprotected_header.sig_tst2.has_value();
}

}  // namespace

void ManifestStoreGeneratorImpl::GenerateManifestStore(
    GenerateManifestStoreRequest request, AsyncContext context,
    absl::AnyInvocable<void(absl::StatusOr<GenerateManifestStoreResponse>) &&>
        cb) const {
  int64_t max_manifest_store_size_bytes =
      request.options().max_manifest_store_size_bytes();
  if (max_manifest_store_size_bytes < 0) {
    AsyncResolver<GenerateManifestStoreResponse>(std::move(context),
                                                 std::move(cb))
        .Return(absl::InvalidArgumentError(
            "max_manifest_store_size_bytes must be non-negative"));
    return;
  }
  if (request.options().has_max_bytes_to_shift() &&
      request.options().max_bytes_to_shift() < 0) {
    AsyncResolver<GenerateManifestStoreResponse>(std::move(context),
                                                 std::move(cb))
        .Return(absl::InvalidArgumentError(
            "max_bytes_to_shift must be non-negative"));
    return;
  }
  if (max_manifest_store_size_bytes == 0) {
    max_manifest_store_size_bytes = kDefaultMaxManifestStoreSizeBytes;
  }
  auto request_ptr =
      std::make_shared<GenerateManifestStoreRequest>(std::move(request));
  auto manifest_or = manifest_assembler_->Assemble(*request_ptr);
  if (!manifest_or.ok()) {
    AsyncResolver<GenerateManifestStoreResponse>(std::move(context),
                                                 std::move(cb))
        .Return(manifest_or.status());
    return;
  }
  auto manifest_box = std::make_shared<ManifestBox>(std::move(*manifest_or));
  manifest_encoder_->Encode(
      manifest_box.get(), request_ptr->options(), context,
      [request_ptr, manifest_box, max_manifest_store_size_bytes,
       manifest_store_transformer = manifest_store_transformer_,
       cb = std::move(cb)](
          absl::StatusOr<ManifestEncoderResult> res_or) mutable {
        if (!res_or.ok()) {
          std::move(cb)(res_or.status());
          return;
        }
        absl::Cord encoded_store = res_or->box.Peek();
        absl::StatusOr<bool> is_timestamped =
            HasActiveClaimTimestamp(encoded_store.Flatten());
        if (!is_timestamped.ok()) {
          std::move(cb)(is_timestamped.status());
          return;
        }
        if (manifest_store_transformer != nullptr) {
          absl::Status transform_status =
              manifest_store_transformer->Transform(&res_or->box);
          if (!transform_status.ok()) {
            std::move(cb)(transform_status);
            return;
          }
        }
        absl::Cord manifest_store_cord = std::move(res_or->box).AsCord();
        if (manifest_store_cord.size() >
            static_cast<uint64_t>(max_manifest_store_size_bytes)) {
          std::move(cb)(absl::FailedPreconditionError(absl::Substitute(
              "Generated manifest store too large ($0 > $1)",
              manifest_store_cord.size(), max_manifest_store_size_bytes)));
          return;
        }
        GenerateManifestStoreResponse response;
        response.set_manifest_store(std::string(manifest_store_cord));
        response.set_is_timestamped(*is_timestamped);
        std::move(cb)(std::move(response));
      });
}

void ManifestStoreGeneratorImpl::GenerateManifestStoreTemplate(
    GenerateManifestStoreRequest request, AsyncContext context,
    absl::AnyInvocable<void(absl::StatusOr<ManifestStoreTemplate>) &&> cb)
    const {
  std::string generator_context = request.SerializeAsString();
  GenerateManifestStore(
      std::move(request), context,
      [generator_context = std::move(generator_context), cb = std::move(cb)](
          absl::StatusOr<GenerateManifestStoreResponse> generated_or) mutable {
        if (!generated_or.ok()) {
          std::move(cb)(generated_or.status());
          return;
        }
        ManifestStoreTemplate response;
        response.set_generator_context(std::move(generator_context));
        response.set_manifest_store_size(generated_or->manifest_store().size());
        std::move(cb)(std::move(response));
      });
}

void ManifestStoreGeneratorImpl::FinalizeManifestStore(
    FinalizeManifestStoreRequest request, AsyncContext context,
    absl::AnyInvocable<void(absl::StatusOr<FinalizeManifestStoreResponse>) &&>
        cb) const {
  if (request.manifest_store_template().generator_context().empty()) {
    AsyncResolver<FinalizeManifestStoreResponse>(std::move(context),
                                                 std::move(cb))
        .Return(absl::InvalidArgumentError(
            "The generator_context in the manifest store template is empty"));
    return;
  }
  if (request.manifest_store_template().manifest_store_size() < 0) {
    AsyncResolver<FinalizeManifestStoreResponse>(std::move(context),
                                                 std::move(cb))
        .Return(absl::InvalidArgumentError(
            "manifest_store_size in template must be non-negative"));
    return;
  }
  GenerateManifestStoreRequest generate_request;
  if (!generate_request.ParseFromString(
          request.manifest_store_template().generator_context())) {
    AsyncResolver<FinalizeManifestStoreResponse>(std::move(context),
                                                 std::move(cb))
        .Return(absl::InvalidArgumentError(
            "Failed to parse the generator_context in the manifest store "
            "template"));
    return;
  }
  if (generate_request.hard_binding().binding_case() !=
      request.hard_binding().binding_case()) {
    AsyncResolver<FinalizeManifestStoreResponse>(std::move(context),
                                                 std::move(cb))
        .Return(absl::InvalidArgumentError(
            "The hard binding in the finalize request must match the original "
            "request"));
    return;
  }
  absl::Status check_status = CheckIfHardBindingByteSizesMatched(
      generate_request.hard_binding(), request.hard_binding(),
      proto_to_cbor_options_);
  if (!check_status.ok()) {
    AsyncResolver<FinalizeManifestStoreResponse>(std::move(context),
                                                 std::move(cb))
        .Return(check_status);
    return;
  }
  generate_request.mutable_hard_binding()->Swap(request.mutable_hard_binding());

  size_t template_manifest_store_size =
      request.manifest_store_template().manifest_store_size();
  GenerateManifestStore(
      std::move(generate_request), context,
      [template_manifest_store_size, cb = std::move(cb)](
          absl::StatusOr<GenerateManifestStoreResponse> generated_or) mutable {
        if (!generated_or.ok()) {
          std::move(cb)(generated_or.status());
          return;
        }
        if (generated_or->manifest_store().size() !=
            template_manifest_store_size) {
          std::move(cb)(absl::InternalError(absl::Substitute(
              "The generated manifest store size ($0) does not "
              "match the estimated size ($1), even though the hard binding "
              "sizes match. This is an internal error.",
              generated_or->manifest_store().size(),
              template_manifest_store_size)));
          return;
        }
        FinalizeManifestStoreResponse response;
        response.mutable_manifest_store()->swap(
            *generated_or->mutable_manifest_store());
        response.set_is_timestamped(generated_or->is_timestamped());
        std::move(cb)(std::move(response));
      });
}

}  // namespace credentio
