// Copyright 2023 The Bazel Authors. All rights reserved.
//
// 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
//
//    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 <stdlib.h>

#include <vector>

#include "file/base/helpers.h"
#include "file/base/path.h"
#include "file/util/temp_path.h"
#include "file/zipfile/zipfilewriter.h"
#include "src/main/cpp/archive_utils.h"
#include "src/main/cpp/bazel_startup_options.h"
#include "googlemock/include/gmock/gmock.h"
#include "googletest/include/gtest/gtest.h"
#include "src/main/cpp/blaze.h"
#include "src/main/cpp/blaze_util_platform.h"
#include "src/main/cpp/util/file_platform.h"

using ::testing::Gt;
using ::testing::status::IsOkAndHolds;

namespace blaze {

static std::vector<std::pair<std::string, std::string>>
get_archive_path_to_contents(std::string expected_install_md5) {
  std::vector<std::pair<std::string, std::string>> archive_path_to_contents;
  archive_path_to_contents.push_back(std::make_pair("foo", "foo content"));
  archive_path_to_contents.push_back(std::make_pair("bar", "bar content"));
  archive_path_to_contents.push_back(
      std::make_pair("path/to/subdir/baz", "baz content"));
  archive_path_to_contents.push_back(
      std::make_pair("install_base_key", expected_install_md5));
  return archive_path_to_contents;
}

static std::vector<std::string> get_archive_paths() {
  std::vector<std::string> archive_paths;
  archive_paths.push_back("foo");
  archive_paths.push_back("bar");
  archive_paths.push_back("path/to/subdir/baz");
  return archive_paths;
}

static absl::StatusOr<std::string> MakeZipAndReturnInstallBase(
    absl::string_view path, std::vector<std::pair<std::string, std::string>>
                                blaze_zip_file_to_contents) {
  ASSIGN_OR_RETURN(auto writer,
                   file_zipfile::ZipfileWriter::Create(path, file::Defaults()));
  for (const auto file_and_contents : blaze_zip_file_to_contents) {
    writer->AddFileFromString(file_and_contents.first,
                              file_and_contents.second);
  }
  RETURN_IF_ERROR(writer->CloseWithStatus(file::Defaults()));
  return "install_base";
}

static void set_startup_options(BazelStartupOptions &startup_options,
                                std::string blaze_path,
                                std::string output_dir) {
  std::string error;
  const std::string install_base_flag = "--install_base=" + output_dir;
  const std::vector<RcStartupFlag> flags{
      RcStartupFlag("somewhere", install_base_flag)};
  const blaze_exit_code::ExitCode ec =
      startup_options.ProcessArgs(flags, &error);
  ASSERT_EQ(ec, blaze_exit_code::SUCCESS)
      << "ProcessArgs failed with error " << error;
}

auto get_mtime = [](absl::string_view path) -> absl::StatusOr<absl::Time> {
  ASSIGN_OR_RETURN(
      const auto stat,
      file::Stat(path, file::StatMask(tech::file::STAT_MTIME_NSECS)));
  return absl::FromUnixNanos(stat.mtime_nsecs());
};

class BlazeArchiveTest : public ::testing::Test {
 protected:
  BlazeArchiveTest() {}

  virtual ~BlazeArchiveTest() {}

  void SetUp() override {
    expected_install_md5 = "expected_install_md5";
    blaze_zip_file_to_contents =
        get_archive_path_to_contents(expected_install_md5);
    archive_contents = get_archive_paths();
    blaze_path = file::JoinPath(temp_.path(), "blaze");
    ASSERT_OK_AND_ASSIGN(
        install_base,
        MakeZipAndReturnInstallBase(blaze_path, blaze_zip_file_to_contents));
    output_dir = file::JoinPath(temp_.path(), install_base);
  }

  const TempPath temp_{TempPath::Local};

  std::vector<std::pair<std::string, std::string>> blaze_zip_file_to_contents;
  std::vector<std::string> archive_contents;

  std::string expected_install_md5;
  std::string blaze_path;
  std::string install_base;
  std::string output_dir;
};

TEST_F(BlazeArchiveTest, TestZipExtractionAndFarOutMTimes) {
  std::unique_ptr<blaze::WorkspaceLayout> workspace_layout(
      new blaze::WorkspaceLayout());
  BazelStartupOptions startup_options(workspace_layout.get());
  set_startup_options(startup_options, blaze_path, output_dir);
  LoggingInfo logging_info(blaze_path, blaze::GetMillisecondsMonotonic());

  ExtractionDurationMillis extraction_time =
      ExtractData(blaze_path, archive_contents, expected_install_md5,
                  startup_options, &logging_info);

  ASSERT_TRUE(extraction_time.archive_extracted);

  const std::string foo_path = file::JoinPath(output_dir, "foo");
  const std::string bar_path = file::JoinPath(output_dir, "bar");
  const std::string baz_path = file::JoinPath(output_dir, "path/to/subdir/baz");

  EXPECT_THAT(file::GetContents(foo_path, file::Defaults()),
              IsOkAndHolds("foo content"));
  EXPECT_THAT(file::GetContents(bar_path, file::Defaults()),
              IsOkAndHolds("bar content"));
  EXPECT_THAT(file::GetContents(baz_path, file::Defaults()),
              IsOkAndHolds("baz content"));

  EXPECT_TRUE(IsUntampered(blaze_util::Path(foo_path)));
  EXPECT_TRUE(IsUntampered(blaze_util::Path(bar_path)));
  EXPECT_TRUE(IsUntampered(blaze_util::Path(baz_path)));

  const auto far_future = absl::Now() + absl::Hours(24 * 365 * 9);
  EXPECT_THAT(get_mtime(foo_path), IsOkAndHolds(Gt(far_future)));
  EXPECT_THAT(get_mtime(bar_path), IsOkAndHolds(Gt(far_future)));
  EXPECT_THAT(get_mtime(baz_path), IsOkAndHolds(Gt(far_future)));
}

TEST_F(BlazeArchiveTest, TestNoDataExtractionIfInstallBaseExists) {
  std::unique_ptr<blaze::WorkspaceLayout> workspace_layout(
      new blaze::WorkspaceLayout());
  BazelStartupOptions startup_options(workspace_layout.get());
  set_startup_options(startup_options, blaze_path, output_dir);
  LoggingInfo logging_info(blaze_path, blaze::GetMillisecondsMonotonic());

  ExtractionDurationMillis extraction_time_one =
      ExtractData(blaze_path, archive_contents, expected_install_md5,
                  startup_options, &logging_info);
  ASSERT_TRUE(extraction_time_one.archive_extracted);

  ExtractionDurationMillis extraction_time_two =
      ExtractData(blaze_path, archive_contents, expected_install_md5,
                  startup_options, &logging_info);

  ASSERT_FALSE(extraction_time_two.archive_extracted);
}
}  // namespace blaze
