// 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 <string>
#include <utility>

#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/notification.h"
#include "async/async_context.h"
#include "claim/generator.h"
#include "claim/manifest_box.h"
#include "claim/manifest_box_assembler.h"
#include "claim/signer.h"
#include "crypto/hash.h"
#include "generator/generator.h"
#include "generator/generator_options.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "proto/generator.pb.h"
#include "proto/generator_info.pb.h"

namespace credentio {
namespace {

using ::absl_testing::StatusIs;
using ::testing::HasSubstr;
using ::testing::NotNull;

class FakeClaimSigner : public ClaimSigner {
 public:
  void Sign(absl::string_view claim, Options options,
            absl::AnyInvocable<void(absl::StatusOr<SignResult>) &&> cb)
      const override {
    std::move(cb)(SignResult{.signature = "fake_sig"});
  }
};

class TrackingManifestBoxAssembler : public ManifestBoxAssembler {
 public:
  explicit TrackingManifestBoxAssembler(std::string name, int* call_count)
      : name_(std::move(name)), call_count_(call_count) {}

  absl::StatusOr<ManifestBox> Assemble(
      const GenerateManifestStoreRequest& request) const override {
    (*call_count_)++;
    return absl::InternalError(name_);
  }

 private:
  std::string name_;
  int* call_count_;
};

TEST(GeneratorFactoryTest, ValidateOptionsRejectsNullSigningClaimSigner) {
  FakeClaimSigner template_signer;
  GeneratorOptions options;
  options.signing_claim_signer = nullptr;
  options.template_claim_signer = &template_signer;

  EXPECT_THAT(CreateGenerator(std::move(options)),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("signing_claim_signer is required")));
}

TEST(GeneratorFactoryTest, ValidateOptionsRejectsNullTemplateClaimSigner) {
  FakeClaimSigner signing_signer;
  GeneratorOptions options;
  options.signing_claim_signer = &signing_signer;
  options.template_claim_signer = nullptr;

  EXPECT_THAT(CreateGenerator(std::move(options)),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("template_claim_signer is required")));
}

TEST(GeneratorFactoryTest, ValidateOptionsRejectsNullUuidGenerator)
__attribute__((no_sanitize("nullability"))) {
  FakeClaimSigner signing_signer;
  FakeClaimSigner template_signer;
  GeneratorOptions options;
  options.signing_claim_signer = &signing_signer;
  options.template_claim_signer = &template_signer;
  options.uuid_generator = nullptr;

  EXPECT_THAT(CreateGenerator(std::move(options)),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("uuid_generator is required")));
}

TEST(GeneratorFactoryTest, ValidateOptionsRejectsNullHashFactory)
__attribute__((no_sanitize("nullability"))) {
  FakeClaimSigner signing_signer;
  FakeClaimSigner template_signer;
  GeneratorOptions options;
  options.signing_claim_signer = &signing_signer;
  options.template_claim_signer = &template_signer;
  options.hash_factory = nullptr;

  EXPECT_THAT(CreateGenerator(std::move(options)),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("hash_factory is required")));
}

TEST(GeneratorFactoryTest, ValidateOptionsRejectsNullManifestAssemblerFactory) {
  FakeClaimSigner signing_signer;
  FakeClaimSigner template_signer;
  GeneratorOptions options;
  options.signing_claim_signer = &signing_signer;
  options.template_claim_signer = &template_signer;
  options.manifest_assembler_factory = nullptr;

  EXPECT_THAT(CreateGenerator(std::move(options)),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("manifest_assembler_factory is required")));
}

TEST(GeneratorFactoryTest, CreateGeneratorSuccess) {
  FakeClaimSigner signing_signer;
  FakeClaimSigner template_signer;
  GeneratorOptions options;
  options.generator_info.set_name("TestGenerator");
  options.generator_info.set_spec_version("2.2.0");
  options.signing_claim_signer = &signing_signer;
  options.template_claim_signer = &template_signer;

  auto generator_or = CreateGenerator(std::move(options));
  ABSL_ASSERT_OK(generator_or);
  EXPECT_THAT(*generator_or, NotNull());
}

TEST(GeneratorFactoryTest, DualModeGeneratorDelegation) {
  FakeClaimSigner signing_signer;
  FakeClaimSigner template_signer;
  int signing_assemble_count = 0;
  int template_assemble_count = 0;

  GeneratorOptions options;
  options.generator_info.set_name("TestGenerator");
  options.generator_info.set_spec_version("2.2.0");
  options.signing_claim_signer = &signing_signer;
  options.template_claim_signer = &template_signer;
  options.manifest_assembler_factory =
      [&](const CreateManifestAssemblerOptions& opts)
      -> absl::StatusOr<std::unique_ptr<ManifestBoxAssembler>> {
    if (dynamic_cast<const TemplatedHasherFactory*>(opts.hash_factory) !=
        nullptr) {
      return std::make_unique<TrackingManifestBoxAssembler>(
          "template_assembler", &template_assemble_count);
    }
    return std::make_unique<TrackingManifestBoxAssembler>(
        "signing_assembler", &signing_assemble_count);
  };

  auto generator_or = CreateGenerator(std::move(options));
  ABSL_ASSERT_OK(generator_or);
  auto generator = std::move(*generator_or);

  // GenerateManifestStore should delegate to the signing generator.
  GenerateManifestStoreRequest gen_request;
  absl::Notification gen_done;
  absl::Status gen_status;
  generator->GenerateManifestStore(
      gen_request, AsyncContext(),
      [&](absl::StatusOr<GenerateManifestStoreResponse> res) {
        gen_status = res.status();
        gen_done.Notify();
      });
  gen_done.WaitForNotification();
  EXPECT_THAT(gen_status, StatusIs(absl::StatusCode::kInternal,
                                   HasSubstr("signing_assembler")));
  EXPECT_EQ(signing_assemble_count, 1);
  EXPECT_EQ(template_assemble_count, 0);

  // GenerateManifestStoreTemplate should delegate to the template generator.
  absl::Notification template_done;
  absl::Status template_status;
  generator->GenerateManifestStoreTemplate(
      gen_request, AsyncContext(),
      [&](absl::StatusOr<ManifestStoreTemplate> res) {
        template_status = res.status();
        template_done.Notify();
      });
  template_done.WaitForNotification();
  EXPECT_THAT(template_status, StatusIs(absl::StatusCode::kInternal,
                                        HasSubstr("template_assembler")));
  EXPECT_EQ(signing_assemble_count, 1);
  EXPECT_EQ(template_assemble_count, 1);

  // FinalizeManifestStore should delegate to the signing generator.
  FinalizeManifestStoreRequest fin_request;
  absl::Notification fin_done;
  absl::Status fin_status;
  generator->FinalizeManifestStore(
      fin_request, AsyncContext(),
      [&](absl::StatusOr<FinalizeManifestStoreResponse> res) {
        fin_status = res.status();
        fin_done.Notify();
      });
  fin_done.WaitForNotification();
  EXPECT_THAT(fin_status, StatusIs(absl::StatusCode::kInvalidArgument,
                                   HasSubstr("generator_context")));
}

}  // namespace
}  // namespace credentio
