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

#include <cstddef>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#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 "formats/asset_box.h"
#include "formats/riff/extractor.h"
#include "proto/boxes_hash_assertion.pb.h"
#include "riegeli/bytes/reader.h"

namespace credentio {
namespace {

// Creator of a single BoxHash entry for a set of boxes.
// This isn't RIFF-specific; could move to a common location.
class BoxHasher {
 public:
  static absl::StatusOr<BoxHasher> Create(HashAlgorithm alg,
                                          BoxesHashAssertion* assertion) {
    ABSL_ASSIGN_OR_RETURN(std::unique_ptr<InputHasher> hasher,
                          InputHasher::Create(alg));
    return BoxHasher(std::move(hasher), assertion->add_boxes());
  }

  absl::Status HashBox(riegeli::Reader& input, const AssetBox& box) {
    entry_->add_names(box.identifier);
    ABSL_RETURN_IF_ERROR(
        hasher_->Update(input, box.byte_range.offset, box.byte_range.length));
    return absl::OkStatus();
  }

  void Finish() { entry_->set_hash(hasher_->Digest()); }

 private:
  BoxHasher(std::unique_ptr<InputHasher> hasher, BoxHash* entry)
      : hasher_(std::move(hasher)), entry_(entry) {}
  std::unique_ptr<InputHasher> hasher_;
  BoxHash* entry_;
};

void AddC2paEntry(BoxesHashAssertion& assertion) {
  BoxHash* entry = assertion.add_boxes();
  entry->add_names("C2PA");
  entry->set_hash(std::string(1, '\0'));
}

}  // namespace

absl::StatusOr<BoxesHashAssertion> DigestRiffBoxHash(riegeli::Reader& input,
                                                     HashAlgorithm alg) {
  BoxesHashAssertion assertion;
  assertion.set_alg(absl::StrCat(alg));
  ABSL_ASSIGN_OR_RETURN(
      std::vector<AssetBox> boxes,
      RiffExtractor().ExtractBoxes(input, {.requires_c2pa = false}));
  // Produce hashes for the boxes prior to the (existing or expected) C2PA box.
  std::optional<BoxHasher> hasher;
  size_t b = 0;
  for (; b < boxes.size(); ++b) {
    const auto& box = boxes[b];
    if (b == 0) {
      if (box.identifier != "RIFF") {
        return absl::InvalidArgumentError(absl::Substitute(
            "First box has ID '$0', expected 'RIFF'", box.identifier));
      }
    } else {
      if (box.identifier == "RIFF") {
        // Second RIFF box -- insert placeholder C2PA box first.
        break;
      }
    }
    if (box.identifier == "C2PA") {
      ++b;
      break;
    }
    if (!hasher) {
      ABSL_ASSIGN_OR_RETURN(hasher, BoxHasher::Create(alg, &assertion));
    }
    ABSL_RETURN_IF_ERROR(hasher->HashBox(input, box));
  }
  if (hasher) {
    hasher->Finish();
    hasher = std::nullopt;
  }
  if (b == 0) {
    return absl::InvalidArgumentError("RIFF chunk not found");
  }

  AddC2paEntry(assertion);

  // C2PA chunk should be the last box in the first RIFF chunk, so the next
  // chunk, if any, should be another top-level RIFF chunk.
  if (b < boxes.size() && boxes[b].identifier != "RIFF") {
    return absl::InvalidArgumentError(absl::Substitute(
        "Expected RIFF chunk, found '$0'", boxes[b].identifier));
  }

  // Produce hashes for any remaining boxes (after the C2PA chunk).
  for (; b < boxes.size(); ++b) {
    const auto& box = boxes[b];
    if (box.identifier == "C2PA") {
      return absl::InvalidArgumentError("Unexpected C2PA chunk found");
    }
    if (!hasher) {
      ABSL_ASSIGN_OR_RETURN(hasher, BoxHasher::Create(alg, &assertion));
    }
    ABSL_RETURN_IF_ERROR(hasher->HashBox(input, box));
  }
  if (hasher) {
    hasher->Finish();
    hasher = std::nullopt;
  }
  return assertion;
}

}  // namespace credentio
