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

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

#include "absl/base/nullability.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/types/span.h"
#include "bindings/input_hasher.h"
#include "crypto/algorithms.h"
#include "formats/zip/constants.h"
#include "formats/zip/reader.h"
#include "proto/collection_data_hash_assertion.pb.h"
#include "riegeli/bytes/reader.h"

namespace credentio {

absl::StatusOr<CollectionDataHashAssertion> CollectionDataHashTemplate(
    absl::Span<const ZipReader::FileEntry> file_entries, HashAlgorithm alg) {
  CollectionDataHashAssertion assertion;
  assertion.set_alg(absl::StrCat(alg));
  for (const ZipReader::FileEntry& file_entry : file_entries) {
    if (file_entry.file_name == kZipManifestFileName) {
      continue;
    }
    UriHashedData* uri_hashed_data = assertion.add_uris();
    uri_hashed_data->set_uri(file_entry.file_name);
    uri_hashed_data->set_hash(std::string(HashSizeBytes(alg), 0));
  }
  assertion.set_zip_central_directory_hash(std::string(HashSizeBytes(alg), 0));

  return assertion;
}

absl::StatusOr<CollectionDataHashAssertion> DigestCollectionDataHash(
    riegeli::Reader* absl_nonnull source, HashAlgorithm alg,
    absl::Span<const ZipReader::FileEntry> file_entries,
    uint64_t central_directory_offset) {
  ABSL_ASSIGN_OR_RETURN(std::vector<ZipReader::FileEntry> sorted_entries,
                        ZipReader::SortFileEntries(file_entries));
  if (!source->Size().has_value()) {
    return absl::InternalError("source->Size() returned no value");
  }
  CollectionDataHashAssertion assertion;
  assertion.set_alg(absl::StrCat(alg));
  const ZipReader::FileEntry* manifest_file_entry = nullptr;
  for (const ZipReader::FileEntry& file_entry : sorted_entries) {
    if (file_entry.file_name == kZipManifestFileName) {
      manifest_file_entry = &file_entry;
      continue;
    }
    UriHashedData* uri_hashed_data = assertion.add_uris();
    uri_hashed_data->set_uri(file_entry.file_name);

    int64_t entry_end =
        file_entry.file_range.offset + file_entry.file_range.length;
    if (file_entry.has_data_descriptor) {
      if (!source->Seek(entry_end) || source->pos() != entry_end) {
        return absl::InternalError("Failed to seek to entry end.");
      }
      std::string buffer;
      if (!source->Read(kZipDataDescriptorSignature.size(), buffer)) {
        return absl::InternalError("Failed to read data descriptor signature.");
      }
      if (buffer == kZipDataDescriptorSignature) {
        entry_end += kDataDescriptorWithSignatureSize;
      } else {
        entry_end += kDataDescriptorSize;
      }
    }
    ABSL_ASSIGN_OR_RETURN(std::unique_ptr<InputHasher> hasher,
                          InputHasher::Create(alg));
    ABSL_RETURN_IF_ERROR(
        hasher->Update(*source, file_entry.local_file_header_offset,
                       entry_end - file_entry.local_file_header_offset));
    uri_hashed_data->set_hash(hasher->Digest());
  }

  ABSL_ASSIGN_OR_RETURN(std::unique_ptr<InputHasher> hasher,
                        InputHasher::Create(alg));
  if (!source->Seek(central_directory_offset) ||
      source->pos() != central_directory_offset) {
    return absl::InternalError("Failed to seek to central directory offset.");
  }

  if (manifest_file_entry == nullptr) {
    return absl::InternalError("No manifest file entry found.");
  }
  uint64_t crc32_offset =
      manifest_file_entry->central_directory_header_offset + 16;
  ABSL_RETURN_IF_ERROR(hasher->Update(*source, central_directory_offset,
                                      crc32_offset - central_directory_offset));
  uint64_t after_crc32_offset = crc32_offset + 4;
  ABSL_RETURN_IF_ERROR(
      hasher->Update(*source, after_crc32_offset,
                     source->Size().value() - after_crc32_offset));
  assertion.set_zip_central_directory_hash(hasher->Digest());

  return assertion;
}
}  // namespace credentio
