// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/local_aggregation_1_1/local_aggregate_storage/immediate_local_aggregate_storage.h"

#include <memory>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "src/lib/statusor/statusor.h"
#include "src/lib/util/testing/test_with_files.h"
#include "src/local_aggregation_1_1/local_aggregate_storage/local_aggregate_storage.h"
#include "src/local_aggregation_1_1/testing/test_registry.cb.h"
#include "src/logger/project_context_factory.h"
#include "src/logging.h"
#include "src/registry/cobalt_registry.pb.h"

namespace cobalt::local_aggregation {
using lib::statusor::StatusOr;
using ::testing::Contains;
using ::testing::Not;
using MetricAggregateRef = LocalAggregateStorage::MetricAggregateRef;

namespace {

std::unique_ptr<CobaltRegistry> GetRegistry() {
  std::string bytes;
  if (!absl::Base64Unescape(kCobaltRegistryBase64, &bytes)) {
    LOG(ERROR) << "Unable to decode Base64 String";
    return nullptr;
  }

  auto registry = std::make_unique<CobaltRegistry>();
  if (!registry->ParseFromString(bytes)) {
    LOG(ERROR) << "Unable to parse registry from bytes";
    return nullptr;
  }

  return registry;
}

}  // namespace

class ImmediateLocalAggregateStorageTest : public util::testing::TestWithFiles {
 private:
  void SetUp() override {
    MakeTestFolder();
    ReplaceRegistry();
  }

 public:
  void ReplaceRegistry(std::unique_ptr<CobaltRegistry> registry = GetRegistry()) {
    global_project_context_factory_ =
        std::make_unique<logger::ProjectContextFactory>(std::move(registry));
    storage_ = std::make_unique<ImmediateLocalAggregateStorage>(
        test_folder(), fs(), global_project_context_factory_.get());
  }

 protected:
  std::unique_ptr<logger::ProjectContextFactory> global_project_context_factory_;
  std::unique_ptr<ImmediateLocalAggregateStorage> storage_;
};

TEST_F(ImmediateLocalAggregateStorageTest, MakesExpectedFiles) {
  // Root directory should contain expected customer_id: 123
  ASSERT_THAT(fs()->ListFiles(test_folder()).ConsumeValueOrDie(), Contains("123"));

  // Customer 123 directory should contain expected project: 100
  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_folder(), "/123")).ConsumeValueOrDie(),
              Contains("100"));

  // Customer 123 Project 100 directory should *not* contain the metric file: 1
  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_folder(), "/123/100")).ConsumeValueOrDie(),
              Not(Contains("1")));

  StatusOr<MetricAggregateRef> agg_or = storage_->GetMetricAggregate(123, 100, 1);
  ASSERT_TRUE(agg_or.ok());
  agg_or.ConsumeValueOrDie().Save();

  // Customer 123 Project 100 directory should contain the metric file: 1
  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_folder(), "/123/100")).ConsumeValueOrDie(),
              Contains("1"));
}

TEST_F(ImmediateLocalAggregateStorageTest, CanReadAlreadyWrittenFiles) {
  {
    StatusOr<MetricAggregateRef> agg_or = storage_->GetMetricAggregate(123, 100, 1);
    ASSERT_TRUE(agg_or.ok());

    MetricAggregateRef agg = agg_or.ConsumeValueOrDie();
    agg.aggregate()->set_version(100);
    ASSERT_TRUE(agg.Save().ok());
  }

  ReplaceRegistry();

  StatusOr<MetricAggregateRef> agg_or = storage_->GetMetricAggregate(123, 100, 1);
  ASSERT_TRUE(agg_or.ok());
  ASSERT_TRUE(agg_or.ConsumeValueOrDie().Save().ok());
}

TEST_F(ImmediateLocalAggregateStorageTest, CleansUpOldMetrics) {
  StatusOr<MetricAggregateRef> agg_or = storage_->GetMetricAggregate(123, 100, 1);
  ASSERT_TRUE(agg_or.ok());
  agg_or.ConsumeValueOrDie().Save();

  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_folder(), "/123/100")).ConsumeValueOrDie(),
              Contains("1"));

  auto registry = GetRegistry();
  google::protobuf::RepeatedPtrField<MetricDefinition>* metrics =
      registry->mutable_customers(0)->mutable_projects(0)->mutable_metrics();
  metrics->erase(metrics->begin() + kOccurrenceMetricMetricIndex);
  ReplaceRegistry(std::move(registry));

  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_folder(), "/123/100")).ConsumeValueOrDie(),
              Not(Contains("1")));
}

TEST_F(ImmediateLocalAggregateStorageTest, CleansUpOldProjects) {
  StatusOr<MetricAggregateRef> agg_or = storage_->GetMetricAggregate(123, 100, 1);
  ASSERT_TRUE(agg_or.ok());
  agg_or.ConsumeValueOrDie().Save();

  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_folder(), "/123")).ConsumeValueOrDie(),
              Contains("100"));
  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_folder(), "/123/100")).ConsumeValueOrDie(),
              Contains("1"));

  auto registry = GetRegistry();
  registry->mutable_customers(0)->mutable_projects()->RemoveLast();
  ReplaceRegistry(std::move(registry));

  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_folder(), "/123")).ConsumeValueOrDie(),
              Not(Contains("100")));
}

TEST_F(ImmediateLocalAggregateStorageTest, DeleteDataWorks) {
  StatusOr<MetricAggregateRef> agg_or = storage_->GetMetricAggregate(123, 100, 1);
  ASSERT_TRUE(agg_or.ok());
  agg_or.ConsumeValueOrDie().Save();

  ASSERT_THAT(fs()->ListFiles(test_folder()).ConsumeValueOrDie(), Contains("123"));
  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_folder(), "/123")).ConsumeValueOrDie(),
              Contains("100"));
  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_folder(), "/123/100")).ConsumeValueOrDie(),
              Contains("1"));

  storage_->DeleteData();

  ASSERT_THAT(fs()->ListFiles(test_folder()).ConsumeValueOrDie(), Not(Contains("123")));
}

class ImmediateLocalAggregateStorageMissingDirectoryTest : public util::testing::TestWithFiles {
 private:
  void SetUp() override {
    MakeTestFolder();
    ReplaceRegistry();
  }

 public:
  void ReplaceRegistry(std::unique_ptr<CobaltRegistry> registry = GetRegistry()) {
    global_project_context_factory_ =
        std::make_unique<logger::ProjectContextFactory>(std::move(registry));
    storage_ = std::make_unique<ImmediateLocalAggregateStorage>(
        test_subfolder(), fs(), global_project_context_factory_.get());
  }

 protected:
  std::string test_subfolder() { return absl::StrCat(test_folder(), "/sub"); }

  std::unique_ptr<logger::ProjectContextFactory> global_project_context_factory_;
  std::unique_ptr<ImmediateLocalAggregateStorage> storage_;
};

TEST_F(ImmediateLocalAggregateStorageMissingDirectoryTest, DontAssumeDirectoryExists) {
  // Root directory should contain expected customer_id: 123
  ASSERT_THAT(fs()->ListFiles(test_subfolder()).ConsumeValueOrDie(), Contains("123"));

  // Customer 123 directory should contain expected project: 100
  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_subfolder(), "/123")).ConsumeValueOrDie(),
              Contains("100"));

  // Customer 123 Project 100 directory should *not* contain the metric file: 1
  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_subfolder(), "/123/100")).ConsumeValueOrDie(),
              Not(Contains("1")));

  StatusOr<MetricAggregateRef> agg_or = storage_->GetMetricAggregate(123, 100, 1);
  ASSERT_TRUE(agg_or.ok());
  agg_or.ConsumeValueOrDie().Save();

  // Customer 123 Project 100 directory should contain the metric file: 1
  ASSERT_THAT(fs()->ListFiles(absl::StrCat(test_subfolder(), "/123/100")).ConsumeValueOrDie(),
              Contains("1"));
}

}  // namespace cobalt::local_aggregation
