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

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

#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "bindings/input_hasher.h"
#include "bindings/merkle.h"
#include "cbor/cbor.h"
#include "cbor/parse.h"
#include "constants/labels.h"
#include "constants/status_codes.h"
#include "crypto/hash.h"
#include "formats/bmff/box_header.h"
#include "proto/bmff_based_hash_assertion.cbor.h"
#include "proto/bmff_based_hash_assertion.pb.h"
#include "riegeli/bytes/reader.h"
#include "utils/riegeli.h"
#include "utils/status_tracker.h"

namespace credentio {

namespace {

std::string GetMerkleKey(int64_t unique_id, int64_t local_id) {
  return absl::StrFormat("%d-%d", unique_id, local_id);
}

absl::StatusOr<std::string> ReadPurpose(riegeli::Reader& contents) {
  std::string purpose;
  if (!ReadNullTerminatedString(contents, 20, purpose)) {
    return contents.StatusOrAnnotate(absl::DataLossError("kUnexpectedEof"));
  }
  return purpose;
}

absl::StatusOr<BmffMerkleMap> ReadBmffMerkleMap(riegeli::Reader& contents,
                                                int64_t length) {
  constexpr int64_t kMaxMerkleMapSize = 10 * 1024 * 1024;  // 10 MiB
  if (length < 0 || length > kMaxMerkleMapSize) {
    return absl::InvalidArgumentError(
        absl::StrFormat("invalid length for merkle map: %d", length));
  }
  std::string aux_box_raw;
  if (!contents.Read(length, aux_box_raw)) {
    return absl::InternalError("failed to read auxiliary merkle map");
  }

  BmffMerkleMap aux_box;
  ABSL_ASSIGN_OR_RETURN(auto aux_box_cbor, cbor::Parse(aux_box_raw));
  ABSL_ASSIGN_OR_RETURN(auto aux_box_cbor_map, aux_box_cbor->AsMap());
  ABSL_RETURN_IF_ERROR(cbor::ToProto(aux_box_cbor_map, &aux_box));
  return aux_box;
}

absl::StatusOr<std::string> ComputeLeafHash(const HasherFactory& factory,
                                            riegeli::Reader& contents,
                                            int64_t offset, int64_t length) {
  ABSL_ASSIGN_OR_RETURN(auto hasher, factory.Create());
  ABSL_ASSIGN_OR_RETURN(auto input_hasher,
                        InputHasher::Create(std::move(hasher)));
  ABSL_RETURN_IF_ERROR(input_hasher->Update(contents, offset, length));
  return input_hasher->Digest();
}

absl::StatusOr<std::string> JoinHashes(const HasherFactory& factory,
                                       absl::string_view hash1,
                                       absl::string_view hash2) {
  ABSL_ASSIGN_OR_RETURN(auto hasher, factory.Create());
  hasher->Update(hash1);
  hasher->Update(hash2);
  return hasher->Digest();
}

struct LeafData {
  std::vector<BmffBoxHeader> mdat_atoms;
  absl::flat_hash_map<std::string, std::vector<BmffMerkleMap>> auxiliary_data;
};

absl::StatusOr<LeafData> ExtractLeafData(riegeli::Reader& contents) {
  LeafData result;

  if (!contents.Seek(0) || contents.pos() != 0) {
    return absl::InternalError("failed to seek to start of file");
  }
  auto status = IterateOverBmffBoxes(
      contents,
      [&result,
       &contents](const BmffBoxHeader& header) -> absl::StatusOr<bool> {
        // Non-fragmented assets have 1 merkle tree per `mdat`
        // Fragmented assets could have merkle tree per track
        // https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_general_20
        if (header.type == "mdat") {
          // Non-fragmented assets require auxiliary data after the last mdat.
          // https://spec.c2pa.org/specifications/specifications/2.2/specs/C2PA_Specification.html#_non_fragmented_asset_that_can_be_validated_piecewise
          if (!result.auxiliary_data.empty()) {
            return absl::InvalidArgumentError(
                "encountered auxiliary atom before the first mdat atom");
          }
          result.mdat_atoms.push_back(header);
        }
        if (header.type == "uuid" &&
            header.user_type == credentio::kC2paBmffBoxUuid) {
          // Read next string to determine the purpose of the uuid atom.
          ABSL_ASSIGN_OR_RETURN(auto purpose, ReadPurpose(contents));

          if (purpose == "merkle") {
            uint64_t end_of_box = header.start + header.box_size;
            if (contents.pos() >= end_of_box) {
              return absl::InvalidArgumentError(
                  "box size too small for metadata headers");
            }
            uint64_t remaining_data = end_of_box - contents.pos();
            ABSL_ASSIGN_OR_RETURN(auto aux_box,
                                  ReadBmffMerkleMap(contents, remaining_data));

            result
                .auxiliary_data[GetMerkleKey(aux_box.unique_id(),
                                             aux_box.local_id())]
                .push_back(aux_box);
          }
        }
        return true;
      });
  ABSL_RETURN_IF_ERROR(status);
  return result;
}

}  // namespace

absl::Status MerkleValidator::ValidateMerkleMap(
    const BmffMerkle& merkle, const BmffBoxHeader& mdat_atom,
    std::vector<BmffMerkleMap> auxiliary_merkle_maps,
    absl::string_view fallback_algo, StatusTracker& tracker) const {
  if (merkle.has_init_hash()) {
    tracker.RecordFailure(
        FailureStatusCode::kGoogleInternalError,
        {.url = assertion_uri_,
         .explanation = "fragmented merkle validations are not supported yet"});
    return absl::UnimplementedError(
        "fragmented merkle validations are not supported yet");
  }

  // Derive the full row sizes and number of rows away and validates the counts.
  absl::StatusOr<DerivedTreeData> derived_data = DeriveMerkleTreeData(
      merkle.count(), merkle.hashes_size(), auxiliary_merkle_maps.size());
  if (!derived_data.ok()) {
    tracker.RecordFailure(FailureStatusCode::kAssertionBmffHashMalformed,
                          {.url = assertion_uri_,
                           .explanation = derived_data.status().message()});
    return derived_data.status();
  }

  uint64_t mdat_offset_adjustment = 0;
  for (const auto& exclusion : assertion_.exclusions()) {
    if (exclusion.xpath() == "/mdat" && !exclusion.subsets().empty()) {
      mdat_offset_adjustment = exclusion.subsets(0).offset();
      break;
    }
  }

  uint64_t header_or_adjustment_size =
      std::max<uint64_t>(mdat_atom.header_size, mdat_offset_adjustment);

  if (mdat_atom.box_size < header_or_adjustment_size) {
    tracker.RecordFailure(
        FailureStatusCode::kAssertionBmffHashMalformed,
        {.url = assertion_uri_,
         .explanation = "mdat atom box_size is smaller than header_size or "
                        "exclusion adjustment"});
    return absl::InvalidArgumentError(
        "mdat atom box_size is smaller than header_size or exclusion "
        "adjustment");
  }

  // Calculate and validate the lengths of each leaf using net payload size.
  uint64_t net_mdat_payload_size =
      mdat_atom.box_size - header_or_adjustment_size;
  absl::StatusOr<std::vector<int64_t>> leaf_sizes =
      DeriveMerkleBlockSizes(merkle, net_mdat_payload_size);
  if (!leaf_sizes.ok()) {
    tracker.RecordFailure(
        FailureStatusCode::kAssertionBmffHashMalformed,
        {.url = assertion_uri_, .explanation = leaf_sizes.status().message()});
    return leaf_sizes.status();
  }

  // Based on the above calculations, we ensure the assertion is not malformed,
  // now compute and compare the leaf hashes.
  uint64_t offset = mdat_atom.start + header_or_adjustment_size;
  for (int64_t i = 0; i < merkle.count(); ++i) {
    absl::string_view algo = merkle.has_alg() ? merkle.alg() : fallback_algo;
    absl::StatusOr<std::unique_ptr<HasherFactory>> factory =
        factory_provider_->Create(algo);
    if (!factory.ok()) {
      tracker.RecordFailure(FailureStatusCode::kAssertionBmffHashMalformed,
                            {.url = assertion_uri_,
                             .explanation = absl::StrFormat(
                                 "unsupported hash algorithm: %s", algo)});
      return absl::InvalidArgumentError(
          absl::StrFormat("unsupported hash algorithm: %s", algo));
    }

    absl::StatusOr<std::string> leaf_hash =
        ComputeLeafHash(**factory, contents_, offset, leaf_sizes.value()[i]);
    offset += leaf_sizes.value()[i];
    if (!leaf_hash.ok()) {
      tracker.RecordFailure(
          FailureStatusCode::kAssertionBmffHashMalformed,
          {.url = assertion_uri_, .explanation = leaf_hash.status().message()});
      return leaf_hash.status();
    }

    std::string computed_hash = std::move(leaf_hash.value());

    if (!auxiliary_merkle_maps.empty()) {
      const BmffMerkleMap& auxiliary = auxiliary_merkle_maps[i];
      int64_t current_index = auxiliary.location();
      int64_t current_count = merkle.count();
      int proof_index = 0;

      for (int64_t r = 0; r < derived_data->delta_rows; ++r) {
        bool has_sibling = false;
        bool sibling_on_left = false;

        if (current_index % 2 == 1) {
          has_sibling = true;
          sibling_on_left = true;
        } else if (current_index + 1 < current_count) {
          has_sibling = true;
          sibling_on_left = false;
        }

        if (has_sibling) {
          if (proof_index >= auxiliary.hashes_size()) {
            tracker.RecordFailure(
                FailureStatusCode::kAssertionBmffHashMalformed,
                {.url = assertion_uri_,
                 .explanation = "missing auxiliary proof hash"});
            return absl::InvalidArgumentError("missing auxiliary proof hash");
          }
          absl::string_view hash = auxiliary.hashes(proof_index++);
          if (sibling_on_left) {
            ABSL_ASSIGN_OR_RETURN(computed_hash,
                                  JoinHashes(**factory, hash, computed_hash));
          } else {
            ABSL_ASSIGN_OR_RETURN(computed_hash,
                                  JoinHashes(**factory, computed_hash, hash));
          }
        }

        current_index >>= 1;
        current_count = (current_count + 1) >> 1;
      }

      if (proof_index != auxiliary.hashes_size()) {
        tracker.RecordFailure(
            FailureStatusCode::kAssertionBmffHashMalformed,
            {.url = assertion_uri_,
             .explanation = "surplus auxiliary proof hashes"});
        return absl::InvalidArgumentError("surplus auxiliary proof hashes");
      }
    }

    uint64_t hashes_index = i >> derived_data->delta_rows;
    if (merkle.hashes(hashes_index) != computed_hash) {
      tracker.RecordFailure(FailureStatusCode::kAssertionBmffHashMismatch,
                            {.url = assertion_uri_,
                             .explanation = absl::StrFormat(
                                 "merkle map hash mismatch on leaf: %d", i)});
      return absl::InternalError("merkle map hash mismatch");
    }
  }
  return absl::OkStatus();
}

absl::Status MerkleValidator::Validate(StatusTracker& tracker) const {
  absl::StatusOr<LeafData> atoms = ExtractLeafData(contents_);
  if (!atoms.ok()) {
    tracker.RecordFailure(
        FailureStatusCode::kGoogleInternalError,
        {.url = assertion_uri_, .explanation = atoms.status().message()});
    return absl::InternalError("failed to extract leaf data");
  }
  if (atoms->mdat_atoms.size() != assertion_.merkles_size()) {
    // This should only apply to non-fragmented assets.
    tracker.RecordFailure(
        FailureStatusCode::kAssertionBmffHashMalformed,
        {.url = assertion_uri_,
         .explanation =
             "number of mdat atoms does not match the number of merkle maps"});
    return absl::InternalError(
        "number of mdat atoms does not match the number of merkle maps");
  }

  for (int64_t i = 0; i < atoms->mdat_atoms.size(); ++i) {
    BmffMerkle merkle = assertion_.merkles(i);
    const auto& aux_maps = atoms->auxiliary_data[GetMerkleKey(
        merkle.unique_id(), merkle.local_id())];
    ABSL_RETURN_IF_ERROR(ValidateMerkleMap(
        merkle, atoms->mdat_atoms[i], aux_maps, assertion_.alg(), tracker));
  }
  return absl::OkStatus();
}

}  // namespace credentio
