/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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
 *
 *   http://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 <config/config.h>
#include <gtest/gtest.h>
#include <status.h>
#include <storage/storage.h>
#include <unistd.h>

#include <filesystem>
#include <fstream>
#include <string>
#include <vector>

TEST(Storage, CreateBackup) {
  std::error_code ec;

  Config config;
  config.db_dir = "test_backup_dir";
  config.slot_id_encoded = false;

  std::filesystem::remove_all(config.db_dir, ec);
  ASSERT_TRUE(!ec);

  auto storage = std::make_unique<engine::Storage>(&config);
  auto s = storage->Open();
  ASSERT_TRUE(s.IsOK());

  auto ctx = engine::Context(storage.get());

  constexpr int cnt = 10;
  for (int i = 0; i < cnt; i++) {
    rocksdb::WriteBatch batch;
    batch.Put("k", "v");
    ASSERT_TRUE(storage->Write(ctx, rocksdb::WriteOptions(), &batch).ok());
  }
  uint64_t sequence_number = 0;
  s = storage->CreateBackup(&sequence_number);
  ASSERT_TRUE(s.IsOK());
  ASSERT_EQ(cnt, sequence_number);
  // check if backup success without caring about the sequence number
  s = storage->CreateBackup();
  ASSERT_TRUE(s.IsOK());

  std::filesystem::remove_all(config.db_dir, ec);
  ASSERT_TRUE(!ec);
}

TEST(Storage, ReadOnlyTransactions) {
  std::error_code ec;

  Config config;
  config.db_dir = "test_backup_dir";
  config.slot_id_encoded = false;

  std::filesystem::remove_all(config.db_dir, ec);
  ASSERT_TRUE(!ec);

  // Populate a DB with some test data so opening the read-only snapshot succeeds
  {
    auto storage = std::make_unique<engine::Storage>(&config);
    auto s = storage->Open();
    ASSERT_TRUE(s.IsOK());

    auto ctx = engine::Context(storage.get());
    rocksdb::WriteBatch batch;
    batch.Put("k", "v");
    ASSERT_TRUE(storage->Write(ctx, rocksdb::WriteOptions(), &batch).ok());
  }

  // Now load that DB in in read-only mode and try to write to it
  {
    auto storage = std::make_unique<engine::Storage>(&config);
    auto s = storage->Open(DBOpenMode::kDBOpenModeForReadOnly);
    std::cout << s.Msg() << std::endl;
    ASSERT_TRUE(s.IsOK());

    auto ctx = engine::Context(storage.get());

    // An empty write batch should not cause any error, even if the storage is opened in
    // read-only mode
    rocksdb::WriteBatch readonly_batch;
    ASSERT_TRUE(storage->Write(ctx, rocksdb::WriteOptions(), &readonly_batch).ok());

    rocksdb::WriteBatch read_write_batch;
    read_write_batch.Put("k", "v");
    ASSERT_FALSE(storage->Write(ctx, rocksdb::WriteOptions(), &read_write_batch).ok());
  }

  std::filesystem::remove_all(config.db_dir, ec);
  ASSERT_TRUE(!ec);
}

TEST(Storage, RocksDBDictionaryCompressionOptions) {
  const char *path = "test_storage_options.conf";
  unlink(path);

  std::ofstream output_file(path, std::ios::out);
  output_file << "rocksdb.compression_max_dict_bytes 16384\n";
  output_file << "rocksdb.compression_zstd_max_train_bytes 262144\n";
  output_file.close();

  Config config;
  ASSERT_TRUE(config.Load(CLIOptions(path)).IsOK());
  config.db_dir = "test_storage_options_dir";

  auto storage = std::make_unique<engine::Storage>(&config);
  auto s = storage->Open();
  ASSERT_TRUE(s.IsOK());

  const auto options = storage->GetDB()->GetOptions();
  EXPECT_EQ(options.compression_opts.max_dict_bytes, 16384U);
  EXPECT_EQ(options.compression_opts.zstd_max_train_bytes, 262144U);

  unlink(path);
}

TEST(Storage, ReplDataManagerRejectsUnsafeFilenames) {
  Config config;
  config.db_dir = "test_repl_file_validation_dir/db";
  config.checkpoint_dir = "test_repl_file_validation_dir/checkpoint";
  config.slot_id_encoded = false;

  std::error_code ec;
  std::filesystem::remove_all("test_repl_file_validation_dir", ec);
  ASSERT_FALSE(ec);

  engine::Storage storage(&config);
  auto base_dir = std::string("test_repl_file_validation_dir/sync_checkpoint");

  auto valid_file = engine::Storage::ReplDataManager::NewTmpFile(&storage, base_dir, "meta/1");
  ASSERT_TRUE(valid_file);
  ASSERT_TRUE(valid_file->Close().ok());
  ASSERT_TRUE(engine::Storage::ReplDataManager::SwapTmpFile(&storage, base_dir, "meta/1").IsOK());
  EXPECT_TRUE(std::filesystem::exists("test_repl_file_validation_dir/sync_checkpoint/meta/1"));

  const std::vector<std::string> unsafe_files = {
      "../escape", "a/../../escape", "/tmp/escape", "a//b",      "a/",
      ".",         "a/..",           "a\\b",        "C:/escape", std::string("bad\0name", 8),
  };
  for (const auto &file : unsafe_files) {
    EXPECT_FALSE(engine::Storage::ReplDataManager::ValidateReplFileName(file).IsOK()) << file;
    EXPECT_FALSE(engine::Storage::ReplDataManager::NewTmpFile(&storage, base_dir, file)) << file;
    EXPECT_FALSE(engine::Storage::ReplDataManager::SwapTmpFile(&storage, base_dir, file).IsOK()) << file;
    EXPECT_FALSE(engine::Storage::ReplDataManager::FileExists(&storage, base_dir, file, 0)) << file;
    uint64_t file_size = 0;
    EXPECT_LT(engine::Storage::ReplDataManager::OpenDataFile(&storage, file, &file_size), 0) << file;
  }

  EXPECT_FALSE(std::filesystem::exists("test_repl_file_validation_dir/escape.tmp"));
  EXPECT_FALSE(std::filesystem::exists("test_repl_file_validation_dir/escape"));

  std::filesystem::remove_all("test_repl_file_validation_dir", ec);
  ASSERT_FALSE(ec);
}
