// 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_cbor_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"
#include "salt/salt_generator.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
                                        : &GetAssertionCborEncoder(),
          .claim_cbor_encoder = options.claim_cbor_encoder
                                    ? options.claim_cbor_encoder
                                    : &GetClaimCborEncoder(),
          .hash_factory = hash_factory,
          .salt_generator = options.salt_generator,
      }));
  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.salt_generator == nullptr) {
    return absl::InvalidArgumentError("salt_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
