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

#include <cstdint>
#include <limits>
#include <memory>
#include <optional>

#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/substitute.h"
#include "bindings/input_hasher.h"
#include "crypto/algorithms.h"
#include "proto/data_hash_assertion.pb.h"
#include "riegeli/bytes/reader.h"

namespace credentio {

namespace {

absl::StatusOr<uint64_t> GetSize(riegeli::Reader& input) {
  if (!input.SupportsSize()) {
    return absl::InvalidArgumentError("input does not support size");
  }
  std::optional<uint64_t> input_size = input.Size();
  if (!input_size.has_value()) {
    return absl::InvalidArgumentError("input does not have a size");
  }
  return *input_size;
}

absl::StatusOr<DataHashAssertion> DigestDataHashInternal(
    riegeli::Reader& input, HashAlgorithm alg, uint64_t manifest_store_offset,
    uint64_t manifest_store_length) {
  ABSL_ASSIGN_OR_RETURN(uint64_t input_size, GetSize(input));

  if (manifest_store_offset >
          static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) ||
      manifest_store_length >
          static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
    return absl::InvalidArgumentError(absl::Substitute(
        "Manifest store offset ($0) or length ($1) exceeds int64 max",
        manifest_store_offset, manifest_store_length));
  }

  uint64_t manifest_store_end;
  if (__builtin_add_overflow(manifest_store_offset, manifest_store_length,
                             &manifest_store_end)) {
    return absl::InvalidArgumentError(absl::Substitute(
        "Manifest store end calculation overflowed: offset $0, length $1",
        manifest_store_offset, manifest_store_length));
  }

  if (manifest_store_end > input_size) {
    return absl::InvalidArgumentError(absl::Substitute(
        "Manifest store range [$0, $1) exceeds input size $2",
        manifest_store_offset, manifest_store_end, input_size));
  }

  ABSL_ASSIGN_OR_RETURN(std::unique_ptr<InputHasher> hasher,
                        InputHasher::Create(alg));
  ABSL_RETURN_IF_ERROR(hasher->Update(input, 0, manifest_store_offset));
  ABSL_RETURN_IF_ERROR(hasher->Update(input, manifest_store_end,
                                      input_size - manifest_store_end));
  DataHashAssertion assertion;
  assertion.set_alg(absl::StrCat(alg));
  assertion.set_hash(hasher->Digest());
  DataRange* exclusion = assertion.add_exclusions();
  exclusion->set_start(static_cast<int64_t>(manifest_store_offset));
  exclusion->set_length(static_cast<int64_t>(manifest_store_length));
  return assertion;
}

}  // namespace

absl::StatusOr<DataHashAssertion> DataHashTemplate(HashAlgorithm alg) {
  DataHashAssertion assertion;
  assertion.set_alg(absl::StrCat(alg));
  ABSL_ASSIGN_OR_RETURN(std::unique_ptr<InputHasher> hasher,
                        InputHasher::Create(alg));
  assertion.set_hash(hasher->Digest());
  DataRange* exclusion = assertion.add_exclusions();
  exclusion->set_start(0);
  exclusion->set_length(0);
  return assertion;
}

absl::StatusOr<DataHashAssertion> DigestDataHash(
    riegeli::Reader& input, HashAlgorithm alg, uint64_t manifest_store_offset,
    uint64_t manifest_store_length) {
  return DigestDataHashInternal(input, alg, manifest_store_offset,
                                manifest_store_length);
}

}  // namespace credentio
