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

#include <algorithm>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/nullability.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "bindings/input_hasher.h"
#include "riegeli/bytes/reader.h"

namespace credentio {
absl_nullable std::unique_ptr<BindingHasher> BindingHasher::Create(
    absl::string_view alg, std::vector<Chunk> chunks,
    BindingHasherTracker& tracker) {
  auto hasher = InputHasher::Create(alg);
  if (!hasher.ok()) {
    tracker.RecordAlgorithmUnsupported();
    return nullptr;
  }
  return std::make_unique<BindingHasher>(*std::move(hasher), std::move(chunks));
}

std::optional<std::string> BindingHasher::Digest(riegeli::Reader& input,
                                                 BindingHasherTracker& tracker,
                                                 uint64_t start_offset,
                                                 int64_t end_offset) {
  if (!input.SupportsSize() || !input.Size().has_value()) {
    tracker.RecordMalformed();
    return std::nullopt;
  }
  const uint64_t file_size = *input.Size();

  if (end_offset < 0) {
    end_offset = file_size;
  }
  if (end_offset > file_size) {
    tracker.RecordMalformed();
    return std::nullopt;
  }

  auto update_input = [&](uint64_t offset, int64_t size) -> bool {
    if (size <= 0) {
      return true;
    }
    const absl::Status status = hasher_->Update(input, offset, size);
    if (!status.ok()) {
      tracker.RecordGeneralError(status);
      return false;
    }
    return true;
  };

  uint64_t pos = start_offset;
  std::optional<Chunk::Op> last_op = std::nullopt;
  for (const auto& chunk : chunks_) {
    // Check Op compatibility.
    if (last_op.has_value() && (chunk.op == Chunk::Op::kInclusion) !=
                                   (*last_op == Chunk::Op::kInclusion)) {
      tracker.RecordMalformed();
      return std::nullopt;
    }
    last_op = chunk.op;

    // Check out of file or negative length chunk.
    if (pos >= end_offset || chunk.length < 0 || chunk.offset > end_offset ||
        chunk.offset < pos) {
      tracker.RecordMalformed();
      return std::nullopt;
    }

    // Advance to the chunk offset.
    const uint64_t next_pos = std::min<uint64_t>(chunk.offset, end_offset);
    if (chunk.op != Chunk::Op::kInclusion) {
      if (!update_input(pos, next_pos - pos)) {
        return std::nullopt;
      }
    }
    pos = next_pos;
    if (pos >= end_offset && chunk.op != Chunk::Op::kExclusion) {
      // Appending to the end of file is not allowed.
      tracker.RecordMalformed();
      return std::nullopt;
    }

    // Advance through the chunk.
    int64_t chunk_size = chunk.length;
    const int64_t file_left_size = end_offset - pos;
    switch (chunk.op) {
      case Chunk::Op::kExclusion:
      case Chunk::Op::kInclusion:
        if (chunk_size > file_left_size) {
          tracker.RecordMismatch();
          return std::nullopt;
        }
        if (chunk_size == 0) {
          chunk_size = file_left_size;
        }
        if (chunk.op == Chunk::Op::kInclusion) {
          if (!update_input(pos, chunk_size)) {
            return std::nullopt;
          }
        }
        break;
      case Chunk::Op::kInsertion:
        // Ignore the chunk size.
        chunk_size = 0;
        hasher_->Update(chunk.additional_data);
        break;
    }
    pos += chunk_size;
  }

  if (!last_op.has_value() || *last_op != Chunk::Op::kInclusion) {
    // Advance the rest of file.
    if (!update_input(pos, end_offset - pos)) {
      return std::nullopt;
    }
  }
  return hasher_->Digest();
}
}  // namespace credentio
