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

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

#include "absl/base/nullability.h"
#include "absl/log/die_if_null.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "bindings/binding_hasher.h"
#include "bindings/input_hasher.h"
#include "constants/status_codes.h"
#include "crypto/algorithms.h"
#include "formats/asset_byte_info.h"
#include "formats/zip/constants.h"
#include "formats/zip/reader.h"
#include "proto/assertion.pb.h"
#include "proto/collection_data_hash_assertion.pb.h"
#include "proto/validation_result.pb.h"
#include "riegeli/bytes/reader.h"
#include "utils/dual_status_tracker.h"
#include "utils/status_tracker.h"
#include "validator/result.h"
#include "validator/validation_result_internal.h"

namespace credentio {

namespace {

class CollectionDataHashBindingHasherTracker : public BindingHasherTracker {
 public:
  explicit CollectionDataHashBindingHasherTracker(
      StatusTracker* tracker, absl::string_view hard_binding_uri)
      : tracker_(*ABSL_DIE_IF_NULL(tracker)),
        hard_binding_uri_(hard_binding_uri) {}

  void RecordMismatch() override {
    tracker_.RecordFailure(FailureStatusCode::kAssertionCollectionHashMismatch,
                           {.url = hard_binding_uri_});
  }
  void RecordMalformed() override {
    tracker_.RecordFailure(FailureStatusCode::kAssertionCollectionHashMalformed,
                           {.url = hard_binding_uri_});
  }
  void RecordAlgorithmUnsupported() override {
    tracker_.RecordFailure(FailureStatusCode::kAlgorithmUnsupported,
                           {.url = hard_binding_uri_});
  }
  void RecordGeneralError(absl::Status error) override {
    tracker_.RecordFailure(
        FailureStatusCode::kGeneralError,
        {.url = hard_binding_uri_, .explanation = error.message()});
  }
  void RecordInvalidUri() {
    tracker_.RecordFailure(
        FailureStatusCode::kAssertionCollectionHashInvalidUri,
        {.url = hard_binding_uri_});
  }
  void RecordIncorrectFileCount() {
    tracker_.RecordFailure(
        FailureStatusCode::kAssertionCollectionHashIncorrectFileCount,
        {.url = hard_binding_uri_});
  }

 private:
  StatusTracker& tracker_;
  absl::string_view hard_binding_uri_;
};

bool HasRelativePathComponents(absl::string_view uri_str) {
  return uri_str == "." || uri_str == ".." || absl::StartsWith(uri_str, "./") ||
         absl::StartsWith(uri_str, "../") ||
         absl::StrContains(uri_str, "/./") ||
         absl::StrContains(uri_str, "/../") || absl::EndsWith(uri_str, "/.") ||
         absl::EndsWith(uri_str, "/..");
}
}  // namespace

absl::StatusOr<std::unique_ptr<ValidationResultProto>>
CollectionDataHashHardBindingValidator::Validate(
    riegeli::Reader& contents, const AssetByteInfo& asset_byte_info,
    std::unique_ptr<PartialValidationResultProto> partial_validation_result)
    const {
  const Assertion* absl_nullable assertion =
      GetAssertion(partial_validation_result.get(),
                   partial_validation_result->hard_binding_uri());
  if (assertion == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "missing assertion: ", partial_validation_result->hard_binding_uri()));
  }
  if (!assertion->has_collection_data_hash()) {
    return absl::InvalidArgumentError(
        absl::StrCat("assertion is not a collection data hash assertion: ",
                     partial_validation_result->hard_binding_uri()));
  }

  ABSL_ASSIGN_OR_RETURN(auto tracker,
                        DualStatusTracker::FromPartialValidationResult(
                            partial_validation_result.get()));

  Validate(contents, assertion->collection_data_hash(),
           partial_validation_result->hard_binding_uri(), *tracker);

  return MakeFullValidationResult(std::move(partial_validation_result));
}

void CollectionDataHashHardBindingValidator::Validate(
    riegeli::Reader& contents, const CollectionDataHashAssertion& assertion,
    absl::string_view hard_binding_uri, StatusTracker& tracker) const {
  if (!contents.SupportsSize() || !contents.Size().has_value()) {
    tracker.RecordFailure(
        FailureStatusCode::kGeneralError,
        {.url = hard_binding_uri,
         .explanation = "Failed to get the size of the file"});
    return;
  }
  uint64_t file_size = *contents.Size();

  CollectionDataHashBindingHasherTracker hasher_tracker(&tracker,
                                                        hard_binding_uri);
  if (assertion.uris().empty()) {
    hasher_tracker.RecordMalformed();
    return;
  }

  auto alg = ParseHashAlgorithm(assertion.alg());
  if (!alg.ok()) {
    hasher_tracker.RecordAlgorithmUnsupported();
    return;
  }

  auto zip_reader = ZipReader::Create(&contents);
  if (!zip_reader.ok()) {
    LOG(ERROR) << "Failed to open the file: " << zip_reader.status();
    hasher_tracker.RecordGeneralError(
        absl::InternalError("Failed to open the file"));
    return;
  }

  std::vector<ZipReader::FileEntry> file_entries;
  while ((*zip_reader)->HasNext()) {
    auto entry = (*zip_reader)->Next();
    if (!entry.ok()) {
      hasher_tracker.RecordGeneralError(
          absl::InternalError("Failed to read ZIP entry"));
      return;
    }
    file_entries.push_back(*entry);
  }

  std::map<std::string, const UriHashedData*> expected_uris;
  for (const auto& uri_data : assertion.uris()) {
    if (uri_data.uri().empty() || uri_data.hash().empty()) {
      hasher_tracker.RecordMalformed();
      return;
    }
    // Validate that the URI has no relative path components (i.e. no "." or
    // "..")
    if (HasRelativePathComponents(uri_data.uri())) {
      hasher_tracker.RecordInvalidUri();
      return;
    }
    expected_uris[std::string(uri_data.uri())] = &uri_data;
  }

  // Validate URI hashes
  const ZipReader::FileEntry* manifest_file_entry = nullptr;
  for (const auto& entry : file_entries) {
    if (entry.file_name == kZipManifestFileName) {
      manifest_file_entry = &entry;
      continue;
    }
    auto it = expected_uris.find(entry.file_name);
    if (it == expected_uris.end()) {
      hasher_tracker.RecordIncorrectFileCount();
      return;
    }
    const auto& expected = *it->second;

    auto file_hasher = InputHasher::Create(*alg);
    if (!file_hasher.ok()) {
      hasher_tracker.RecordGeneralError(file_hasher.status());
      return;
    }

    uint32_t entry_start = entry.local_file_header_offset;
    uint32_t entry_end = entry.file_range.offset + entry.file_range.length;
    if (entry.has_data_descriptor) {
      if (!contents.Seek(entry_end)) {
        hasher_tracker.RecordGeneralError(
            absl::InternalError("Failed to seek to data descriptor"));
        return;
      }
      std::string sig;
      if (!contents.Read(4, sig)) {
        hasher_tracker.RecordGeneralError(
            absl::InternalError("Failed to read data descriptor signature"));
        return;
      }
      if (sig == kZipDataDescriptorSignature) {
        entry_end += kDataDescriptorWithSignatureSize;
      } else {
        entry_end += kDataDescriptorSize;
      }
    }

    auto update_status =
        (*file_hasher)->Update(contents, entry_start, entry_end - entry_start);
    if (!update_status.ok()) {
      hasher_tracker.RecordGeneralError(update_status);
      return;
    }
    std::string file_hash = (*file_hasher)->Digest();
    if (expected.hash() != file_hash) {
      hasher_tracker.RecordMismatch();
      return;
    }

    expected_uris.erase(it);
  }

  if (!expected_uris.empty()) {
    hasher_tracker.RecordIncorrectFileCount();
    return;
  }

  // Validate ZIP central directory hash
  if (manifest_file_entry == nullptr) {
    hasher_tracker.RecordGeneralError(
        absl::InternalError("Manifest file entry not found"));
    return;
  }
  auto cd_hasher = InputHasher::Create(*alg);
  if (!cd_hasher.ok()) {
    hasher_tracker.RecordGeneralError(cd_hasher.status());
    return;
  }
  uint32_t cd_offset = (*zip_reader)->central_directory_offset();
  uint32_t manifest_crc32_offset =
      manifest_file_entry->central_directory_header_offset + 16;

  auto update_status =
      (*cd_hasher)
          ->Update(contents, cd_offset, manifest_crc32_offset - cd_offset);
  if (!update_status.ok()) {
    hasher_tracker.RecordGeneralError(update_status);
    return;
  }
  update_status = (*cd_hasher)
                      ->Update(contents, manifest_crc32_offset + 4,
                               file_size - (manifest_crc32_offset + 4));
  if (!update_status.ok()) {
    hasher_tracker.RecordGeneralError(update_status);
    return;
  }

  std::string cd_hash = (*cd_hasher)->Digest();
  if (assertion.zip_central_directory_hash() != cd_hash) {
    hasher_tracker.RecordMismatch();
    return;
  }

  tracker.RecordSuccess(SuccessStatusCode::kAssertionCollectionHashMatch,
                        {.url = hard_binding_uri});
}

}  // namespace credentio
