// Copyright 2022 The Pigweed Authors
//
// 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 "pw_transfer/atomic_file_transfer_handler.h"

#include <cinttypes>
#include <filesystem>
#include <fstream>
#include <random>
#include <string>
#include <string_view>

#include "pw_random/xor_shift.h"
#include "pw_result/result.h"
#include "pw_status/status.h"
#include "pw_string/string_builder.h"
#include "pw_transfer/transfer.h"
#include "pw_transfer_private/filename_generator.h"
#include "pw_unit_test/framework.h"

namespace pw::transfer {

namespace {

// Copied from go/pw-src/+/main:pw_stream/std_file_stream_test.cc;l=75
class TempDir {
 public:
  TempDir(std::string_view prefix) : rng_(GetSeed()) {
    temp_dir_ = std::filesystem::temp_directory_path();
    temp_dir_ /= std::string(prefix) + GetRandomSuffix();
    PW_ASSERT(std::filesystem::create_directory(temp_dir_));
  }

  ~TempDir() { PW_ASSERT(std::filesystem::remove_all(temp_dir_)); }

  std::filesystem::path GetTempFileName() {
    return temp_dir_ / GetRandomSuffix();
  }

 private:
  std::string GetRandomSuffix() {
    StringBuffer<9> random_suffix_str;
    uint32_t random_suffix_int = 0;
    rng_.GetInt(random_suffix_int);
    PW_ASSERT(random_suffix_str.Format("%08" PRIx32, random_suffix_int).ok());
    return std::string(random_suffix_str.view());
  }

  // Generate a 64-bit random from system entropy pool. This is used to seed a
  // pseudo-random number generator for individual file names.
  static uint64_t GetSeed() {
    std::random_device sys_rand;
    uint64_t seed = 0;
    for (size_t seed_bytes = 0; seed_bytes < sizeof(seed);
         seed_bytes += sizeof(std::random_device::result_type)) {
      std::random_device::result_type val = sys_rand();
      seed = seed << 8 * sizeof(std::random_device::result_type);
      seed |= val;
    }
    return seed;
  }

  random::XorShiftStarRng64 rng_;
  std::filesystem::path temp_dir_;
};

class AtomicFileTransferHandlerTest : public ::testing::Test {
 public:
  TempDir temp_dir_{"atomic_file_transfer_handler_test"};
  std::string test_data_location_pass_ = temp_dir_.GetTempFileName();
  std::string transfer_temp_file_ = GetTempFilePath(test_data_location_pass_);

 protected:
  static constexpr auto test_data_location_fail = "not/a/directory/no_data.txt";
  static constexpr auto temp_file_content = "Temp File Success.";
  static constexpr auto test_data_content = "Test File Success.";

  bool WriteContentFile(std::string_view path, std::string_view value) {
    std::ofstream file(path);
    if (!file.is_open()) {
      return false;
    }
    file << value;
    return true;
  }

  Result<std::string> ReadFile(std::string_view path) {
    std::ifstream file(path);
    if (!file.is_open()) {
      return Status::NotFound();
    }
    std::string return_value;
    std::getline(file, return_value);
    return return_value;
  }

  void ClearContent(std::string_view path) {
    std::ofstream ofs(path, std::ofstream::out | std::ofstream::trunc);
  }

  void check_finalize(Status status) {
    EXPECT_EQ(status, OkStatus());
    // Temp file does not exist after finalize.
    EXPECT_TRUE(!std::filesystem::exists(transfer_temp_file_));
    // Test path does exist, file has been created.
    EXPECT_TRUE(std::filesystem::exists(test_data_location_pass_));
    // File content is the same as expected.
    const auto file_content = ReadFile(test_data_location_pass_);
    ASSERT_TRUE(file_content.ok());

    EXPECT_EQ(file_content.value(), temp_file_content);
  }

  void SetUp() override {
    // Write content file and check correct.
    ASSERT_TRUE(WriteContentFile(test_data_location_pass_, test_data_content));
    const auto file_content_data = ReadFile(test_data_location_pass_);
    ASSERT_TRUE(file_content_data.ok());
    ASSERT_EQ(file_content_data.value(), test_data_content);

    // Write temp file and check content is correct
    ASSERT_TRUE(WriteContentFile(transfer_temp_file_, temp_file_content));
    const auto file_content_tmp = ReadFile(transfer_temp_file_);
    ASSERT_TRUE(file_content_tmp.ok());
    ASSERT_EQ(file_content_tmp.value(), temp_file_content);
  }

  void TearDown() override {
    // Ensure temp file is deleted.
    ASSERT_TRUE(!std::filesystem::exists(transfer_temp_file_) ||
                std::filesystem::remove(transfer_temp_file_));
    // Ensure test file is deleted.
    ASSERT_TRUE(!std::filesystem::exists(test_data_location_pass_) ||
                std::filesystem::remove(test_data_location_pass_));
  }
};

TEST_F(AtomicFileTransferHandlerTest, PrepareReadPass) {
  AtomicFileTransferHandler test_handler{/*resource_id = */ 0,
                                         test_data_location_pass_};
  EXPECT_EQ(test_handler.PrepareRead(), OkStatus());
}

TEST_F(AtomicFileTransferHandlerTest, PrepareReadFail) {
  AtomicFileTransferHandler test_handler{/*resource_id = */ 0,
                                         test_data_location_fail};
  EXPECT_EQ(test_handler.PrepareRead(), Status::NotFound());
}

TEST_F(AtomicFileTransferHandlerTest, PrepareWritePass) {
  AtomicFileTransferHandler test_handler{/*resource_id = */ 0,
                                         test_data_location_pass_};
  // Open a file for write returns OkStatus.
  EXPECT_EQ(test_handler.PrepareWrite(), OkStatus());
}

TEST_F(AtomicFileTransferHandlerTest, PrepareWriteFail) {
  AtomicFileTransferHandler test_handler{/*resource_id = */ 0,
                                         test_data_location_fail};
  // Open a file with non existing path pass.
  // No access to underlying stream
  // so rely on the write during transfer to catch the error.
  EXPECT_EQ(test_handler.PrepareWrite(), OkStatus());
}

TEST_F(AtomicFileTransferHandlerTest, FinalizeWriteRenameExisting) {
  ASSERT_TRUE(std::filesystem::exists(transfer_temp_file_));
  ASSERT_TRUE(std::filesystem::exists(test_data_location_pass_));
  AtomicFileTransferHandler test_handler{/*resource_id = */
                                         0,
                                         test_data_location_pass_};
  // Prepare Write to open the stream. should be closed during Finalize.
  ASSERT_EQ(test_handler.PrepareWrite(), OkStatus());
  WriteContentFile(transfer_temp_file_, temp_file_content);
  auto status = test_handler.FinalizeWrite(OkStatus());
  check_finalize(status);
}

TEST_F(AtomicFileTransferHandlerTest, FinalizeWriteNoExistingFile) {
  AtomicFileTransferHandler test_handler{/*resource_id = */
                                         0,
                                         test_data_location_pass_};
  // Remove file test file and test creation.
  ASSERT_TRUE(std::filesystem::remove(test_data_location_pass_));
  ASSERT_EQ(test_handler.PrepareWrite(), OkStatus());
  WriteContentFile(transfer_temp_file_, temp_file_content);
  auto status = test_handler.FinalizeWrite(OkStatus());
  check_finalize(status);
}

TEST_F(AtomicFileTransferHandlerTest, FinalizeWriteExpectErr) {
  AtomicFileTransferHandler test_handler{/*resource_id = */
                                         0,
                                         test_data_location_pass_};
  ASSERT_EQ(test_handler.PrepareWrite(), OkStatus());
  // Simulate write fails, file is empty, No write here.
  ClearContent(transfer_temp_file_);
  ASSERT_TRUE(std::filesystem::is_empty(transfer_temp_file_));
  ASSERT_TRUE(std::filesystem::exists(test_data_location_pass_));
  EXPECT_EQ(test_handler.FinalizeWrite(Status::DataLoss()), Status::DataLoss());
}

}  // namespace

}  // namespace pw::transfer
