// 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.
//

#ifndef THIRD_PARTY_CREDENTIO_TESTING_FAKE_MANIFEST_STORE_GENERATOR_H_
#define THIRD_PARTY_CREDENTIO_TESTING_FAKE_MANIFEST_STORE_GENERATOR_H_

#include <string>
#include <utility>

#include "absl/functional/any_invocable.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "async/async_context.h"
#include "generator/generator.h"
#include "proto/generator.pb.h"

namespace credentio {

// A fake implementation of ManifestStoreGenerator for testing.
// By default, it returns a fixed magic string as the manifest store.
// Allows configuring custom response protos or injecting error status.
class FakeManifestStoreGenerator : public ManifestStoreGenerator {
 public:
  static constexpr absl::string_view kDefaultManifestStore =
      "fake_manifest_bytes_magic_string";

  explicit FakeManifestStoreGenerator(
      absl::string_view manifest_store = kDefaultManifestStore) {
    set_manifest_store(std::string(manifest_store));
  }

  void set_manifest_store(std::string manifest_store) {
    generate_response_.set_manifest_store(manifest_store);
    template_.set_manifest_store_size(manifest_store.size());
    finalize_response_.set_manifest_store(std::move(manifest_store));
  }

  const std::string& manifest_store() const {
    return finalize_response_.manifest_store();
  }

  void set_generate_manifest_store_response(
      GenerateManifestStoreResponse response) {
    generate_response_ = std::move(response);
  }

  GenerateManifestStoreResponse* mutable_generate_manifest_store_response() {
    return &generate_response_;
  }

  const GenerateManifestStoreResponse& generate_manifest_store_response()
      const {
    return generate_response_;
  }

  void set_manifest_store_template(ManifestStoreTemplate response) {
    template_ = std::move(response);
  }

  ManifestStoreTemplate* mutable_manifest_store_template() {
    return &template_;
  }

  const ManifestStoreTemplate& manifest_store_template() const {
    return template_;
  }

  void set_finalize_manifest_store_response(
      FinalizeManifestStoreResponse response) {
    finalize_response_ = std::move(response);
  }

  FinalizeManifestStoreResponse* mutable_finalize_manifest_store_response() {
    return &finalize_response_;
  }

  const FinalizeManifestStoreResponse& finalize_manifest_store_response()
      const {
    return finalize_response_;
  }

  void set_status(absl::Status status) { status_ = std::move(status); }

  void set_fail_generate_manifest_store(bool fail) {
    if (fail) {
      status_ = absl::InternalError("Manifest generation failed.");
    } else {
      status_ = absl::OkStatus();
    }
  }

  void GenerateManifestStore(
      GenerateManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<GenerateManifestStoreResponse>) &&>
          cb) const override {
    if (!status_.ok()) {
      std::move(cb)(status_);
      return;
    }
    std::move(cb)(generate_response_);
  }

  void GenerateManifestStoreTemplate(
      GenerateManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<ManifestStoreTemplate>) &&> cb)
      const override {
    if (!status_.ok()) {
      std::move(cb)(status_);
      return;
    }
    std::move(cb)(template_);
  }

  void FinalizeManifestStore(
      FinalizeManifestStoreRequest request, AsyncContext context,
      absl::AnyInvocable<void(absl::StatusOr<FinalizeManifestStoreResponse>) &&>
          cb) const override {
    if (!status_.ok()) {
      std::move(cb)(status_);
      return;
    }
    std::move(cb)(finalize_response_);
  }

 private:
  GenerateManifestStoreResponse generate_response_;
  ManifestStoreTemplate template_;
  FinalizeManifestStoreResponse finalize_response_;
  absl::Status status_ = absl::OkStatus();
};

}  // namespace credentio

#endif  // THIRD_PARTY_CREDENTIO_TESTING_FAKE_MANIFEST_STORE_GENERATOR_H_
