#ifndef THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_MOCK_MANAGED_STORE_TEST_H_
#define THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_MOCK_MANAGED_STORE_TEST_H_

#include <unistd.h>

#include <chrono>  //NOLINT
#include <memory>
#include <thread>  //NOLINT
#include <utility>

#include <gtest/gtest.h>
#include "absl/log/log.h"
#include "boost/asio/detail/exception.hpp"
#include "boost/asio/io_context.hpp"  // NOLINT
#include "boost/beast/http/message.hpp"  //NOLINT
#include "boost/beast/http/string_body.hpp"  //NOLINT
#include "boost/system/detail/error_code.hpp"
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "test/g3/mock_managed_store.hpp"

namespace managedStore {

class MockManagedStoreTest : public ::testing::Test {
 public:
  template <typename ValueTypeInput>
  static std::shared_ptr<ValueType> CreateValueType(ValueTypeInput&& value) {
    auto value_type = std::make_shared<ValueType>(
        std::forward<ValueTypeInput>(value), boost::system::error_code(),
        std::chrono::steady_clock::now(), std::chrono::steady_clock::now());
    LOG(INFO) << "Creating ValueType of type: "
              << ManagedTypeToString(value_type->getManagedType());
    return std::move(value_type);
  }

  template <typename ValueTypeInput>
  static std::shared_ptr<ValueType> CreateErrorValueType(
      ValueTypeInput&& value, boost::system::error_code&& ec) {
    LOG(INFO) << "Creating ValueType with error code: " << ec.what();
    auto value_type = std::make_shared<ValueType>(
        std::forward<ValueTypeInput>(value),
        std::forward<boost::system::error_code>(ec),
        std::chrono::steady_clock::now(), std::chrono::steady_clock::now());
    LOG(INFO) << "ValueType of type: "
              << ManagedTypeToString(value_type->getManagedType());
    return std::move(value_type);
  }

  // This should be a blocking call that returns when io context finishes its
  // queue.
  // Since there is no work guard, it will terminate once work is done.
  static void RunIoUntilDone() {
    // Once an io context is stopped, it must be restarted before running again.
    GetStaticIoContext().restart();
    while (!GetStaticIoContext().stopped()) {
      GetStaticIoContext().run_one();
    }
  }

 protected:
  static void SetUpTestSuite() {
    // We have to only initialize the managed store once.
    managedStore::InitializeManagedStore(
        &GetStaticConfig(), &GetStaticIoContext(), nullptr, nullptr,
        MockManagedObjectStore::
            GetBadPointerToSystemBusWhichShouldNeverBeUsedOtherThanInitializeManagedStoreForUnitTests());  // NOLINT
  }

  void SetUp() override {
    mock_managed_store_instance_ = std::make_shared<
        managedStore::MockSerializedManagedObjectStore>(
        GetStaticConfig(), GetStaticIoContext(), std::this_thread::get_id(),
        nullptr, nullptr,
        MockManagedObjectStore::
            GetBadPointerToSystemBusWhichShouldNeverBeUsedOtherThanInitializeManagedStoreForUnitTests());  // NOLINT
  }

  // We require these static variables as we need to initialize the global
  // managed store before the test fixture is created.
  static boost::asio::io_context& GetStaticIoContext() {
    // NOLINTNEXTLINE(google3-runtime-global-variables)
    static boost::asio::io_context io;
    return io;
  }

  static managedStore::ManagedObjectStoreConfig& GetStaticConfig() {
    static managedStore::ManagedObjectStoreConfig config(
        true,                   /*isEnabled*/
        5,                      /*pendingDbusResponsesMax*/
        std::chrono::years(10), /*tfixedThreshold*/
        std::chrono::years(10), /*tgraceThreshold*/
        std::chrono::years(10), /*tLRUThreshold*/
        true,                   /*timetrace*/
        100,                    /*timetrace_size_max*/
        true /*snap_shot_mode*/);
    return config;
  }

  std::shared_ptr<managedStore::MockSerializedManagedObjectStore>
      mock_managed_store_instance_;
};
}  // namespace managedStore
#endif  // THIRD_PARTY_MILOTIC_INTERNAL_CC_BMCWEB_MOCK_MANAGED_STORE_TEST_H_
