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

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

#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/status/statusor.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "crypto/algorithms.h"
#include "crypto/default/hasher.h"
#include "crypto/hash.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "riegeli/bytes/string_reader.h"

namespace credentio {
namespace {

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

std::string Sha256Digest(absl::string_view data) {
  absl::StatusOr<std::unique_ptr<Hasher>> hasher = CreateHasher("sha256");
  if (!hasher.ok()) return "";
  (*hasher)->Update(data);
  return (*hasher)->Digest();
}

TEST(InputHasherTest, CreateWithValidAlgString) {
  EXPECT_THAT(InputHasher::Create("sha256"), IsOk());
  EXPECT_THAT(InputHasher::Create("sha384"), IsOk());
  EXPECT_THAT(InputHasher::Create("sha512"), IsOk());
}

TEST(InputHasherTest, CreateWithInvalidAlgString) {
  EXPECT_THAT(InputHasher::Create("invalid"),
              StatusIs(absl::StatusCode::kInvalidArgument));
}

TEST(InputHasherTest, CreateWithValidAlgEnum) {
  EXPECT_THAT(InputHasher::Create(HashAlgorithm::kSha256), IsOk());
  EXPECT_THAT(InputHasher::Create(HashAlgorithm::kSha384), IsOk());
  EXPECT_THAT(InputHasher::Create(HashAlgorithm::kSha512), IsOk());
}

class MockHasher : public Hasher {
 public:
  MOCK_METHOD(void, Update, (absl::string_view data), (override));
  MOCK_METHOD(std::string, Digest, (), (override));
};

TEST(InputHasherTest, CreateWithCustomHasher) {
  auto mock_hasher = std::make_unique<MockHasher>();
  EXPECT_CALL(*mock_hasher, Update("test"));
  EXPECT_CALL(*mock_hasher, Digest()).WillOnce(Return("mock_digest"));

  auto input_hasher = InputHasher::Create(std::move(mock_hasher));
  ABSL_ASSERT_OK(input_hasher);
  (*input_hasher)->Update("test");
  EXPECT_THAT((*input_hasher)->Digest(), Eq("mock_digest"));
}

TEST(InputHasherTest, UpdateStringView) {
  auto hasher = InputHasher::Create("sha256");
  ABSL_ASSERT_OK(hasher);
  (*hasher)->Update("hello");
  (*hasher)->Update(" ");
  (*hasher)->Update("world");

  EXPECT_THAT(absl::BytesToHexString((*hasher)->Digest()),
              Eq(absl::BytesToHexString(Sha256Digest("hello world"))));
}

TEST(InputHasherTest, UpdateRiegeliEmpty) {
  auto hasher = InputHasher::Create("sha256");
  ABSL_ASSERT_OK(hasher);
  std::string data = "";
  riegeli::StringReader reader(data);
  EXPECT_THAT((*hasher)->Update(reader, 0, 0), IsOk());

  EXPECT_THAT(absl::BytesToHexString((*hasher)->Digest()),
              Eq(absl::BytesToHexString(Sha256Digest(data))));
}

TEST(InputHasherTest, UpdateRiegeliSmall) {
  auto hasher = InputHasher::Create("sha256");
  ABSL_ASSERT_OK(hasher);
  std::string data = "small data";
  riegeli::StringReader reader(data);
  EXPECT_THAT((*hasher)->Update(reader, 0, data.length()), IsOk());

  EXPECT_THAT(absl::BytesToHexString((*hasher)->Digest()),
              Eq(absl::BytesToHexString(Sha256Digest(data))));
}

TEST(InputHasherTest, UpdateRiegeliLarge) {
  auto hasher = InputHasher::Create("sha256");
  ABSL_ASSERT_OK(hasher);
  std::string data(20000, 'a');  // Larger than default chunk size
  riegeli::StringReader reader(data);
  EXPECT_THAT((*hasher)->Update(reader, 0, data.length()), IsOk());

  EXPECT_THAT(absl::BytesToHexString((*hasher)->Digest()),
              Eq(absl::BytesToHexString(Sha256Digest(data))));
}

TEST(InputHasherTest, UpdateRiegeliWithOffset) {
  auto hasher = InputHasher::Create("sha256");
  ABSL_ASSERT_OK(hasher);
  std::string data = "prefix_and_data";
  riegeli::StringReader reader(data);
  EXPECT_THAT((*hasher)->Update(reader, 7, 3), IsOk());  // "and"

  EXPECT_THAT(absl::BytesToHexString((*hasher)->Digest()),
              Eq(absl::BytesToHexString(Sha256Digest("and"))));
}

TEST(InputHasherTest, UpdateRiegeliMultiple) {
  auto hasher = InputHasher::Create("sha256");
  ABSL_ASSERT_OK(hasher);
  std::string data1 = "first part";
  std::string data2 = " second part";

  riegeli::StringReader reader1(data1);
  riegeli::StringReader reader2(data2);

  EXPECT_THAT((*hasher)->Update(reader1, 0, data1.length()), IsOk());
  (*hasher)->Update(" middle ");
  EXPECT_THAT((*hasher)->Update(reader2, 0, data2.length()), IsOk());

  EXPECT_THAT(absl::BytesToHexString((*hasher)->Digest()),
              Eq(absl::BytesToHexString(
                  Sha256Digest("first part middle  second part"))));
}

TEST(InputHasherTest, UpdateRiegeliClosedReaderFails) {
  auto hasher = InputHasher::Create("sha256");
  ABSL_ASSERT_OK(hasher);
  riegeli::StringReader reader("test");
  reader.Close();

  EXPECT_THAT((*hasher)->Update(reader, 0, 4),
              StatusIs(absl::StatusCode::kFailedPrecondition,
                       HasSubstr("Object closed")));
}

TEST(InputHasherTest, UpdateRiegeliOffsetOutOfRange) {
  auto hasher = InputHasher::Create("sha256");
  ABSL_ASSERT_OK(hasher);
  riegeli::StringReader reader("test");

  EXPECT_THAT(
      (*hasher)->Update(reader, 10, 4),
      StatusIs(absl::StatusCode::kInternal, HasSubstr("Failed to seek to 10")));
}

TEST(InputHasherTest, UpdateRiegeliLengthExceedsSourceFails) {
  auto hasher = InputHasher::Create("sha256");
  ABSL_ASSERT_OK(hasher);
  riegeli::StringReader reader("test");

  EXPECT_THAT((*hasher)->Update(reader, 0, 100),
              StatusIs(absl::StatusCode::kDataLoss,
                       HasSubstr("Failed to read from source")));
}

}  // namespace
}  // namespace credentio
