// 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/hasher_data.h"

#include <cstdint>
#include <memory>
#include <string>
#include <vector>

#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "bindings/collection_data_hash_hard_binding_validator.h"
#include "constants/status_codes.h"
#include "crypto/algorithms.h"
#include "formats/zip/reader.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "proto/collection_data_hash_assertion.pb.h"
#include "riegeli/bytes/reader.h"
#include "testing/proto_test_utils.h"
#include "testing/test_file_utils.h"
#include "testing/test_validation_tracker.h"
#include "utils/status_tracker.h"
#include "validator/tracker.h"

namespace credentio {
namespace {

using ::absl_testing::StatusIs;
using ::credentio_testing::EqualsProto;
using ::testing::HasSubstr;
using ::testing::IsEmpty;
using ::testing::SizeIs;

// A StatusTracker that records to a ValidationTracker.
class RecordingStatusTracker : public StatusTracker {
 public:
  explicit RecordingStatusTracker(ValidationTracker& tracker)
      : tracker_(tracker) {}

  void RecordSuccess(SuccessStatusCode code,
                     ValidationTracker::RecordOptions options) override {
    tracker_.RecordSuccess(code, options);
  }
  void RecordFailure(FailureStatusCode code,
                     ValidationTracker::RecordOptions options) override {
    tracker_.RecordFailure(code, options);
  }
  void RecordInformational(InformationalStatusCode code,
                           ValidationTracker::RecordOptions options) override {
    tracker_.RecordInformational(code, options);
  }

  ValidationTracker& tracker_;
};

class DigestCollectionDataHashTest : public testing::Test {
 protected:
  static void SetUpTestSuite() {
    // This ZIP archive contains three files: "file_1.txt", "file_2.txt" and a
    // fake manifest.
    auto file_reader = credentio_testing::GetFileReader(
        "credentio/formats/zip/testing/"
        "asset_fake_c2pa.zip");
    ABSL_ASSERT_OK(file_reader);
    source_ = file_reader->release();
    auto reader = ZipReader::Create(source_);
    ABSL_ASSERT_OK(reader);
    central_directory_offset_ = (*reader)->central_directory_offset();
    file_entries_ = new std::vector<ZipReader::FileEntry>();
    while ((*reader)->HasNext()) {
      absl::StatusOr<ZipReader::FileEntry> entry = (*reader)->Next();
      ABSL_ASSERT_OK(entry);
      file_entries_->push_back(*entry);
    }
  }

  static void TearDownTestSuite() {
    delete file_entries_;
    file_entries_ = nullptr;
    delete source_;
    source_ = nullptr;
  }

  inline static riegeli::Reader* source_ = nullptr;
  inline static std::vector<ZipReader::FileEntry>* file_entries_ = nullptr;
  inline static uint64_t central_directory_offset_ = 0;
};

TEST_F(DigestCollectionDataHashTest, TemplateMatchesFinal) {
  absl::StatusOr<CollectionDataHashAssertion> template_assertion =
      CollectionDataHashTemplate(*file_entries_, HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(template_assertion);

  absl::StatusOr<CollectionDataHashAssertion> final_assertion =
      DigestCollectionDataHash(source_, HashAlgorithm::kSha256, *file_entries_,
                               central_directory_offset_);
  ABSL_ASSERT_OK(final_assertion);
  EXPECT_THAT(final_assertion->zip_central_directory_hash(),
              SizeIs(template_assertion->zip_central_directory_hash().size()));
  EXPECT_THAT(final_assertion->uris(), SizeIs(template_assertion->uris_size()));

  // Copy values from final assertion to template assertion and compare.
  for (int i = 0; i < final_assertion->uris_size(); ++i) {
    template_assertion->mutable_uris(i)->set_hash(
        final_assertion->uris(i).hash());
  }
  template_assertion->set_zip_central_directory_hash(
      final_assertion->zip_central_directory_hash());

  EXPECT_THAT(*final_assertion, EqualsProto(*template_assertion));
}

TEST_F(DigestCollectionDataHashTest, BindingValidates) {
  absl::StatusOr<CollectionDataHashAssertion> final_assertion =
      DigestCollectionDataHash(source_, HashAlgorithm::kSha256, *file_entries_,
                               central_directory_offset_);
  ABSL_ASSERT_OK(final_assertion);

  ASSERT_TRUE(source_->Seek(0));

  CollectionDataHashHardBindingValidator validator;
  TestValidationTracker t;
  RecordingStatusTracker tracker(t.tracker());
  validator.Validate(*source_, *final_assertion, "test_uri", tracker);

  EXPECT_THAT(
      t.GetSuccesses(),
      ContainsSuccess(SuccessStatusCode::kAssertionCollectionHashMatch));
  EXPECT_THAT(t.GetFailures(), IsEmpty());
  EXPECT_THAT(t.GetInformationals(), IsEmpty());
}

TEST_F(DigestCollectionDataHashTest,
       DigestCollectionDataHashFailsWithDuplicateEntries) {
  ASSERT_GE(file_entries_->size(), 1);
  std::vector<ZipReader::FileEntry> duplicate_entries = *file_entries_;
  duplicate_entries.push_back((*file_entries_)[0]);

  EXPECT_THAT(
      DigestCollectionDataHash(source_, HashAlgorithm::kSha256,
                               duplicate_entries, central_directory_offset_),
      StatusIs(absl::StatusCode::kInvalidArgument,
               HasSubstr("Overlapping or duplicate ZIP entries detected")));
}

}  // namespace
}  // namespace credentio
