// 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 <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") {
            // Leverage the offset found within the manifest to find first aux
            // 4 bytes are the version and flag data
            // 1 byte is the null terminator of the purpose string
            const uint64_t metadata_header_size = purpose.size() + 4 + 1;
            if (header.box_size < header.header_size ||
                header.box_size - header.header_size < metadata_header_size) {
              return absl::InvalidArgumentError(
                  "box size too small for metadata headers");
            }
            int64_t remaining_data =
                header.box_size - header.header_size - metadata_header_size;
            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();
  }

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

  // Calculate and validate the lengths of each leaf.
  absl::StatusOr<std::vector<int64_t>> leaf_sizes = DeriveMerkleBlockSizes(
      merkle, mdat_atom.box_size - mdat_atom.header_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.
  int64_t offset = mdat_atom.start + mdat_atom.header_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()) {
      int64_t running_row_index = i;
      BmffMerkleMap auxiliary = auxiliary_merkle_maps[i];
      for (const auto& hash : auxiliary.hashes()) {
        if (running_row_index % 2 == 1) {
          ABSL_ASSIGN_OR_RETURN(computed_hash,
                                JoinHashes(**factory, hash, computed_hash));
        } else {
          ABSL_ASSIGN_OR_RETURN(computed_hash,
                                JoinHashes(**factory, computed_hash, hash));
        }
        running_row_index >>= 1;
      }
    }

    int64_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 at index %d: Expected: %s, Actual: %s",
               hashes_index, merkle.hashes(hashes_index), computed_hash)});
      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
