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

#include <memory>
#include <utility>

#include "absl/functional/any_invocable.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "async/async_context.h"
#include "claim/local_signer.h"
#include "crypto/crypto_write_handler.h"
#include "crypto/default/hasher.h"
#include "crypto/hash.h"
#include "crypto/templated_crypto_write_handler.h"
#include "generator/generator.h"
#include "generator/generator_factory.h"
#include "generator/generator_options.h"
#include "proto/generator.pb.h"
#include "proto/generator_info.pb.h"
#include "testing/create_test_crypto_write_handler.h"

namespace credentio {
namespace {

class NonProdManifestStoreGenerator : public ManifestStoreGenerator {
 public:
  NonProdManifestStoreGenerator(
      std::unique_ptr<CryptoWriteHandler> signing_handler,
      std::unique_ptr<TemplatedHasherFactory> template_hash_factory,
      std::unique_ptr<TemplatedCryptoWriteHandler>
          template_crypto_write_handler,
      std::unique_ptr<LocalClaimSigner> template_claim_signer,
      std::unique_ptr<LocalClaimSigner> signing_claim_signer,
      std::unique_ptr<ManifestStoreGenerator> generator)
      : signing_handler_(std::move(signing_handler)),
        template_hash_factory_(std::move(template_hash_factory)),
        template_crypto_write_handler_(
            std::move(template_crypto_write_handler)),
        template_claim_signer_(std::move(template_claim_signer)),
        signing_claim_signer_(std::move(signing_claim_signer)),
        generator_(std::move(generator)) {}

  void GenerateManifestStore(
      GenerateManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<GenerateManifestStoreResponse>) &&>
          cb) const override {
    generator_->GenerateManifestStore(std::move(request), std::move(context),
                                      std::move(cb));
  }

  void GenerateManifestStoreTemplate(
      GenerateManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<ManifestStoreTemplate>) &&> cb)
      const override {
    generator_->GenerateManifestStoreTemplate(
        std::move(request), std::move(context), std::move(cb));
  }

  void FinalizeManifestStore(
      FinalizeManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<FinalizeManifestStoreResponse>) &&>
          cb) const override {
    generator_->FinalizeManifestStore(std::move(request), std::move(context),
                                      std::move(cb));
  }

 private:
  std::unique_ptr<CryptoWriteHandler> signing_handler_;
  std::unique_ptr<TemplatedHasherFactory> template_hash_factory_;
  std::unique_ptr<TemplatedCryptoWriteHandler> template_crypto_write_handler_;
  std::unique_ptr<LocalClaimSigner> template_claim_signer_;
  std::unique_ptr<LocalClaimSigner> signing_claim_signer_;
  std::unique_ptr<ManifestStoreGenerator> generator_;
};

}  // namespace

absl::StatusOr<std::unique_ptr<ManifestStoreGenerator>>
CreateNonProdManifestStoreGenerator(
    const NonProdManifestStoreGeneratorOptions& options) {
  ABSL_ASSIGN_OR_RETURN(
      std::unique_ptr<CryptoWriteHandler> crypto_write_handler,
      CreateTestCryptoWriteHandler({
          .clock = options.clock,
          .disable_timestamping = options.disable_timestamping,
      }));

  const HasherFactory& hash_factory = DefaultHasherFactory();
  auto template_hash_factory =
      std::make_unique<TemplatedHasherFactory>(hash_factory.algorithm());
  auto template_crypto_write_handler =
      std::make_unique<TemplatedCryptoWriteHandler>(crypto_write_handler.get());
  auto template_claim_signer = std::make_unique<LocalClaimSigner>(
      template_crypto_write_handler.get(), template_hash_factory.get());
  auto signing_claim_signer = std::make_unique<LocalClaimSigner>(
      crypto_write_handler.get(), &hash_factory);

  GeneratorOptions generator_options;
  if (options.generator_info.has_value()) {
    generator_options.generator_info = *options.generator_info;
  } else {
    generator_options.generator_info.set_name("Google NonProd C2PA Generator");
  }
  generator_options.signing_claim_signer = signing_claim_signer.get();
  generator_options.template_claim_signer = template_claim_signer.get();
  generator_options.hash_factory = &hash_factory;
  if (options.uuid_generator != nullptr) {
    generator_options.uuid_generator = options.uuid_generator;
  }

  ABSL_ASSIGN_OR_RETURN(std::unique_ptr<ManifestStoreGenerator> generator,
                        CreateGenerator(std::move(generator_options)));
  return std::make_unique<NonProdManifestStoreGenerator>(
      std::move(crypto_write_handler), std::move(template_hash_factory),
      std::move(template_crypto_write_handler),
      std::move(template_claim_signer), std::move(signing_claim_signer),
      std::move(generator));
}

}  // namespace credentio
