// Copyright 2026 Google LLC
//
// 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 "formats/zip/writer.h"

#include <memory>
#include <optional>
#include <string>
#include <utility>

#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "formats/byte_range.h"
#include "formats/zip/extractor.h"
#include "generator/generator.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "proto/generator.pb.h"
#include "proto/manifest.pb.h"
#include "proto/validation_status.pb.h"
#include "riegeli/bytes/cfile_reader.h"
#include "riegeli/bytes/cfile_writer.h"
#include "riegeli/bytes/string_reader.h"
#include "riegeli/bytes/string_writer.h"
#include "testing/nonprod_generator.h"
#include "testing/nonprod_validator.h"
#include "testing/test_file_utils.h"
#include "validator/asset_validator.h"
#include "validator/result.h"

namespace credentio {
namespace {

using ::absl_testing::IsOkAndHolds;
using ::absl_testing::StatusIs;
using ::testing::AllOf;
using ::testing::Field;
using ::testing::Gt;
using ::testing::HasSubstr;
using ::testing::IsEmpty;
using ::testing::Optional;

class ZipWriterTest : public testing::Test {
 protected:
  void SetUp() override {
    auto generator = CreateNonProdManifestStoreGenerator({});
    ABSL_ASSERT_OK(generator);
    generator_ = *std::move(generator);
    writer_ = std::make_unique<ZipWriter>(generator_.get());
    auto validator = CreateNonProdValidator({});
    ABSL_ASSERT_OK(validator);
    validator_ = *std::move(validator);
  }
  std::unique_ptr<ManifestStoreGenerator> generator_;
  std::unique_ptr<ZipWriter> writer_;
  std::unique_ptr<AssetValidator> validator_;
};

TEST_F(ZipWriterTest, Write) {
  GenerateManifestStoreRequest request;
  request.mutable_actions()
      ->mutable_created()
      ->mutable_action_metadata()
      ->set_description("test only");

  auto source = credentio_testing::GetFileReader(
      "credentio/formats/zip/testing/"
      "no_c2pa_032_asset.pptx");
  ABSL_ASSERT_OK(source);

  std::string result;
  riegeli::StringWriter destination(&result);
  ABSL_ASSERT_OK(destination.status());

  ABSL_ASSERT_OK(writer_->Write(request, source->get(), &destination));
  ASSERT_TRUE(destination.Close());

  riegeli::StringReader result_reader(result);
  ABSL_ASSERT_OK(result_reader.status());

  EXPECT_THAT(ZipExtractor().ExtractManifestStoreLocation(result_reader, {}),
              IsOkAndHolds(Optional(AllOf(Field(&ByteRange::offset, Gt(0)),
                                          Field(&ByteRange::length, Gt(0))))));

  ASSERT_TRUE(result_reader.Seek(0));
  auto validation_result = validator_->Validate(
      result_reader,
      "application/"
      "vnd.openxmlformats-officedocument.presentationml.presentation");
  ABSL_ASSERT_OK(validation_result);
  EXPECT_THAT(
      (*validation_result)->proto().active_manifest().validation().failures(),
      IsEmpty());
}

TEST_F(ZipWriterTest, WriteWithHardBindingFails) {
  GenerateManifestStoreRequest request;
  request.mutable_actions()
      ->mutable_created()
      ->mutable_action_metadata()
      ->set_description("test only");
  request.mutable_hard_binding();

  absl::StatusOr<std::string> pptx_file_contents =
      credentio_testing::GetContents(
          "credentio/formats/zip/testing/"
          "no_c2pa_032_asset.pptx");
  ABSL_ASSERT_OK(pptx_file_contents);
  riegeli::StringReader source(*pptx_file_contents);
  ABSL_ASSERT_OK(source.status());
  std::string result;
  riegeli::StringWriter destination(&result);
  ABSL_ASSERT_OK(destination.status());
  EXPECT_THAT(writer_->Write(request, &source, &destination),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("must not include `hard_binding`")));
}

TEST_F(ZipWriterTest, WriteToDestinationWithoutReadModeFails) {
  GenerateManifestStoreRequest request;
  request.mutable_actions()
      ->mutable_created()
      ->mutable_action_metadata()
      ->set_description("test only");

  auto source = credentio_testing::GetFileReader(
      "credentio/formats/zip/testing/"
      "no_c2pa_032_asset.pptx");
  ABSL_ASSERT_OK(source);

  // By default, `riegeli::CFileWriter` opens the file write-only.
  const std::string output_path =
      absl::StrCat(testing::TempDir(), "/write_only_output.pptx");
  riegeli::CFileWriter destination(output_path);
  ABSL_ASSERT_OK(destination.status());
  ASSERT_FALSE(destination.SupportsReadMode());

  EXPECT_THAT(writer_->Write(request, source->get(), &destination),
              StatusIs(absl::StatusCode::kInvalidArgument,
                       HasSubstr("supports read mode")));
  ASSERT_TRUE(destination.Close());

  // Nothing is written to the rejected destination.
  riegeli::CFileReader output(output_path);
  ABSL_ASSERT_OK(output.status());
  EXPECT_THAT(output.Size(), Optional(0));
}

}  // namespace
}  // namespace credentio
