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

#include <string>

#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/strings/escaping.h"
#include "bindings/input_hasher.h"
#include "crypto/algorithms.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "riegeli/bytes/string_reader.h"
#include "riegeli/bytes/string_writer.h"

namespace credentio {
namespace {

using ::absl_testing::IsOk;
using ::absl_testing::StatusIs;
using ::testing::HasSubstr;

TEST(WriteTest, LittleEndianWrite) {
  std::string output;
  riegeli::StringWriter writer(&output);

  EXPECT_THAT(Write32(1, /*is_big_endian=*/false, writer), IsOk());

  writer.Close();

  EXPECT_EQ(output, std::string("\x01\0\0\0", 4));
}

TEST(WriteTest, BigEndianWrite) {
  std::string output;
  riegeli::StringWriter writer(&output);

  EXPECT_THAT(Write32(1, /*is_big_endian=*/true, writer), IsOk());

  writer.Close();

  EXPECT_EQ(output, std::string("\0\0\0\x01", 4));
}

TEST(WriteTest, Fails) {
  std::string output;
  riegeli::StringWriter writer(&output);
  writer.Close();

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  EXPECT_THAT(
      Write32(1, /*is_big_endian=*/true, writer),
      StatusIs(absl::StatusCode::kDataLoss, HasSubstr("failed to write")));
}

TEST(HashWriteTest, LittleEndianWrite16) {
  std::string output;
  riegeli::StringWriter writer(&output);

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  EXPECT_THAT(HashWrite16(1, /*is_big_endian=*/false, **hasher, writer),
              IsOk());

  writer.Close();

  EXPECT_EQ(output, std::string("\x01\0", 2));
  EXPECT_EQ(absl::Base64Escape((*hasher)->Digest()),
            "R9xUDJTOtwSiOHXBEnPha7C4qHrthN6RHyEzVoEV8lQ=");
}

TEST(HashWriteTest, BigEndianWrite16) {
  std::string output;
  riegeli::StringWriter writer(&output);

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  EXPECT_THAT(HashWrite16(1, /*is_big_endian=*/true, **hasher, writer), IsOk());

  writer.Close();

  EXPECT_EQ(output, std::string("\0\x01", 2));
  EXPECT_EQ(absl::Base64Escape((*hasher)->Digest()),
            "tBP0fRPuL+bIRbLuFBr4HehY307FSaWLeXC7lmRbyNI=");
}

TEST(HashWriteTest, LittleEndianWrite32) {
  std::string output;
  riegeli::StringWriter writer(&output);

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  EXPECT_THAT(HashWrite32(1, /*is_big_endian=*/false, **hasher, writer),
              IsOk());

  writer.Close();

  EXPECT_EQ(output, std::string("\x01\0\0\0", 4));
  EXPECT_EQ(absl::Base64Escape((*hasher)->Digest()),
            "Z6vdchAk8P9OCz9ML8E7xbrULQt4UdRW2I0gPRWqpFA=");
}

TEST(HashWriteTest, BigEndianWrite32) {
  std::string output;
  riegeli::StringWriter writer(&output);

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  EXPECT_THAT(HashWrite32(1, /*is_big_endian=*/true, **hasher, writer), IsOk());

  writer.Close();

  EXPECT_EQ(output, std::string("\0\0\0\x01", 4));
  EXPECT_EQ(absl::Base64Escape((*hasher)->Digest()),
            "tAcRqIxwOXVvuKc4J+q+LA/loDRsp+ChBK3A/HZPUo0=");
}

TEST(HashWriteTest, Fails) {
  std::string output;
  riegeli::StringWriter writer(&output);
  writer.Close();

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  EXPECT_THAT(
      HashWrite32(1, /*is_big_endian=*/true, **hasher, writer),
      StatusIs(absl::StatusCode::kDataLoss, HasSubstr("failed to write")));
}

TEST(ReadHashWriteTest, Success) {
  std::string input = "test_string";
  riegeli::StringReader reader(input);
  std::string output;
  riegeli::StringWriter writer(&output);

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  EXPECT_THAT(ReadHashWrite(reader, 4, **hasher, writer), IsOk());

  writer.Close();

  EXPECT_EQ(output, "test");
  EXPECT_EQ(absl::Base64Escape((*hasher)->Digest()),
            "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=");
}

TEST(ReadHashTest, Success) {
  std::string input = "test_string";
  riegeli::StringReader reader(input);

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  EXPECT_THAT(ReadHash(reader, 4, **hasher), IsOk());

  EXPECT_EQ(absl::Base64Escape((*hasher)->Digest()),
            "n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=");
}

TEST(ReadHashTest, FailsWithClosedReader) {
  std::string input = "test_string";
  riegeli::StringReader reader(input);

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  reader.Close();
  EXPECT_THAT(
      ReadHash(reader, 4, **hasher),
      StatusIs(absl::StatusCode::kDataLoss, HasSubstr("Failed to read")));
}

TEST(ReadHashWriteTest, FailsWithClosedReader) {
  std::string input = "test_string";
  riegeli::StringReader reader(input);
  std::string output;
  riegeli::StringWriter writer(&output);

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  reader.Close();
  EXPECT_THAT(
      ReadHashWrite(reader, 4, **hasher, writer),
      StatusIs(absl::StatusCode::kDataLoss, HasSubstr("Failed to read")));
}

TEST(ReadHashWriteTest, FailsWithClosedWriter) {
  std::string input = "test_string";
  riegeli::StringReader reader(input);
  std::string output;
  riegeli::StringWriter writer(&output);

  auto hasher = InputHasher::Create(HashAlgorithm::kSha256);
  ABSL_ASSERT_OK(hasher);

  writer.Close();
  EXPECT_THAT(
      ReadHashWrite(reader, 4, **hasher, writer),
      StatusIs(absl::StatusCode::kDataLoss, HasSubstr("Failed to write")));
}

}  // namespace
}  // namespace credentio
