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

#include <memory>
#include <utility>

#include "absl/base/nullability.h"
#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "assertion/assertion_encoder.h"
#include "async/async_context.h"
#include "claim/claim_cbor_encoder.h"
#include "claim/generator.h"
#include "claim/manifest_box_assembler.h"
#include "claim/signer.h"
#include "crypto/hash.h"
#include "generator/generator.h"
#include "generator/generator_impl.h"
#include "generator/generator_options.h"

namespace credentio {
namespace {
// A ManifestStoreGenerator implementation that routes generation requests
// between two underlying generators:
// - `signing_generator`: used for full manifest store generation and
//   finalization with real signatures.
// - `template_generator`: used for manifest store template generation for size
//   estimation.
// Also retains ownership of `template_hash_factory` to guarantee its lifetime.
class DualModeManifestStoreGenerator : public ManifestStoreGenerator {
 public:
  // Constructs a DualModeManifestStoreGenerator with the given signing and
  // template generators, optionally retaining ownership of
  // `template_hash_factory`.
  DualModeManifestStoreGenerator(
      std::unique_ptr<ManifestStoreGenerator> absl_nonnull signing_generator,
      std::unique_ptr<ManifestStoreGenerator> absl_nonnull template_generator,
      std::unique_ptr<HasherFactory> absl_nullable template_hash_factory =
          nullptr)
      : signing_generator_(std::move(signing_generator)),
        template_hash_factory_(std::move(template_hash_factory)),
        template_generator_(std::move(template_generator)) {}

  // Generates a manifest store using the signing generator.
  void GenerateManifestStore(
      GenerateManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<GenerateManifestStoreResponse>) &&>
          cb) const override {
    signing_generator_->GenerateManifestStore(
        std::move(request), std::move(context), std::move(cb));
  }

  // Generates a manifest store template for size estimation using the template
  // generator.
  void GenerateManifestStoreTemplate(
      GenerateManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<ManifestStoreTemplate>) &&> cb)
      const override {
    template_generator_->GenerateManifestStoreTemplate(
        std::move(request), std::move(context), std::move(cb));
  }

  // Finalizes the manifest store using the signing generator.
  void FinalizeManifestStore(
      FinalizeManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<FinalizeManifestStoreResponse>) &&>
          cb) const override {
    signing_generator_->FinalizeManifestStore(
        std::move(request), std::move(context), std::move(cb));
  }

 private:
  std::unique_ptr<ManifestStoreGenerator> signing_generator_;
  // Must be declared before `template_generator_` so it outlives
  // `template_generator_`.
  std::unique_ptr<HasherFactory> template_hash_factory_;
  std::unique_ptr<ManifestStoreGenerator> template_generator_;
};

// Helper function to create an underlying ManifestStoreGeneratorImpl with the
// given options, hash factory, and claim signer.
absl::StatusOr<std::unique_ptr<ManifestStoreGenerator>> CreateGenerator(
    const GeneratorOptions& options,
    const HasherFactory* absl_nonnull hash_factory,
    ClaimSigner* absl_nonnull claim_signer) {
  ABSL_ASSIGN_OR_RETURN(auto manifest_assembler,
                        options.manifest_assembler_factory({
                            .uuid_generator = options.uuid_generator,
                            .hash_factory = hash_factory,
                            .spec_version = options.spec_version,
                        }));
  ABSL_ASSIGN_OR_RETURN(
      auto manifest_encoder,
      CreateManifestEncoder({
          .generator_info = options.generator_info,
          .claim_signer = claim_signer,
          .assertion_cbor_encoder = options.assertion_cbor_encoder
                                        ? options.assertion_cbor_encoder
                                        : &GetAssertionEncoder(),
          .claim_cbor_encoder = options.claim_cbor_encoder
                                    ? options.claim_cbor_encoder
                                    : &GetClaimCborEncoder(),
          .hash_factory = hash_factory,
      }));
  return std::make_unique<ManifestStoreGeneratorImpl>(
      std::move(manifest_assembler), std::move(manifest_encoder),
      options.manifest_store_transformer);
}

// Validates that required options are provided.
absl::Status ValidateOptions(const GeneratorOptions& options) {
  if (options.signing_claim_signer == nullptr) {
    return absl::InvalidArgumentError("signing_claim_signer is required");
  }
  if (options.template_claim_signer == nullptr) {
    return absl::InvalidArgumentError("template_claim_signer is required");
  }
  if (options.uuid_generator == nullptr) {
    return absl::InvalidArgumentError("uuid_generator is required");
  }
  if (options.hash_factory == nullptr) {
    return absl::InvalidArgumentError("hash_factory is required");
  }
  if (options.manifest_assembler_factory == nullptr) {
    return absl::InvalidArgumentError("manifest_assembler_factory is required");
  }
  return absl::OkStatus();
}
}  // namespace

absl::StatusOr<std::unique_ptr<ManifestStoreGenerator>> CreateGenerator(
    GeneratorOptions options) {
  ABSL_RETURN_IF_ERROR(ValidateOptions(options));
  auto template_hash_factory = std::make_unique<TemplatedHasherFactory>(
      options.hash_factory->algorithm());
  ABSL_ASSIGN_OR_RETURN(auto signing_generator,
                        CreateGenerator(options, options.hash_factory,
                                        options.signing_claim_signer));
  ABSL_ASSIGN_OR_RETURN(auto template_generator,
                        CreateGenerator(options, template_hash_factory.get(),
                                        options.template_claim_signer));
  return std::make_unique<DualModeManifestStoreGenerator>(
      std::move(signing_generator), std::move(template_generator),
      std::move(template_hash_factory));
}

}  // namespace credentio
