// 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 <algorithm>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>

#include "absl/base/nullability.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "crypto/algorithms.h"
#include "crypto/default/hasher.h"
#include "crypto/hash.h"
#include "riegeli/bytes/reader.h"

namespace credentio {
namespace {

constexpr uint64_t kMaxChunkBytes = 1024 * 1024;  // 1 MiB

absl::Status AddToHash(Hasher& hasher, riegeli::Reader& asset,
                       uint64_t read_start, uint64_t read_length) {
  if (!asset.Seek(read_start) || asset.pos() != read_start) {
    return absl::InternalError(absl::Substitute(
        "Failed to seek to $0 in the file. Current position is "
        "$1.",
        read_start, asset.pos()));
  }

  for (uint64_t i = 0; i < read_length; i += kMaxChunkBytes) {
    uint64_t length = std::min(read_length - i, kMaxChunkBytes);

    std::string contents;
    if (!asset.Read(length, contents)) {
      return asset.StatusOrAnnotate(
          absl::DataLossError("Failed to read from source"));
    }
    hasher.Update(contents);
  }
  return absl::OkStatus();
}

class SimpleInputHasher : public InputHasher {
 public:
  explicit SimpleInputHasher(std::unique_ptr<Hasher> absl_nonnull hasher)
      : hasher_(std::move(hasher)) {}

  absl::Status Update(riegeli::Reader& input, uint64_t offset,
                      uint64_t length) override {
    return AddToHash(*hasher_, input, offset, length);
  }

  void Update(absl::string_view data) override { hasher_->Update(data); }

  std::string Digest() override { return hasher_->Digest(); }

 private:
  std::unique_ptr<Hasher> hasher_;
};

}  // namespace

absl::StatusOr<std::unique_ptr<InputHasher> absl_nonnull> InputHasher::Create(
    absl::string_view alg) {
  ABSL_ASSIGN_OR_RETURN(auto hasher, CreateHasher(alg));
  return std::make_unique<SimpleInputHasher>(std::move(hasher));
}

absl::StatusOr<std::unique_ptr<InputHasher> absl_nonnull> InputHasher::Create(
    HashAlgorithm alg) {
  ABSL_ASSIGN_OR_RETURN(auto hasher, CreateHasher(alg));
  return std::make_unique<SimpleInputHasher>(std::move(hasher));
}

absl::StatusOr<std::unique_ptr<InputHasher>> InputHasher::Create(
    std::unique_ptr<Hasher> absl_nonnull hasher) {
  return std::make_unique<SimpleInputHasher>(std::move(hasher));
}

}  // namespace credentio
