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

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

#include "absl/base/nullability.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "crypto/algorithms.h"
#include "formats/zip/embedder.h"
#include "formats/zip/hasher_data.h"
#include "formats/zip/reader.h"
#include "proto/generator.pb.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/bytes/writer.h"

namespace credentio {

absl::Status ZipWriter::Write(GenerateManifestStoreRequest& request,
                              riegeli::Reader* absl_nonnull source,
                              riegeli::Writer* absl_nonnull destination) {
  if (request.has_hard_binding()) {
    return absl::InvalidArgumentError(
        "request must not include `hard_binding` (binding is computed by "
        "ZipWriter)");
  }
  // Phase 2 below reads back and patches `destination`. Check this before
  // writing anything, so that an unsuitable `destination` is left untouched.
  if (!destination->SupportsReadMode()) {
    return absl::InvalidArgumentError(
        "ZipWriter::Write requires a riegeli::Writer that supports read mode.");
  }
  if (!destination->SupportsRandomAccess()) {
    return absl::InvalidArgumentError(
        "ZipWriter::Write requires a riegeli::Writer that supports random "
        "access.");
  }

  ABSL_ASSIGN_OR_RETURN(auto reader, ZipReader::Create(source));

  std::vector<ZipReader::FileEntry> file_entries;
  while (reader->HasNext()) {
    ABSL_ASSIGN_OR_RETURN(auto entry, reader->Next());
    file_entries.push_back(entry);
  }

  // The two-phase approach is required for ZIP-based assets: The sections to be
  // hashed can't be finalized until the manifest store size is known and
  // content types stream is updated.

  // Phase 1: Copy the asset to the destination, update the content types
  // stream, compute preliminary hard binding, produce a manifest store
  // template, and embed a zero-filled placeholder in the asset.
  HashAlgorithm alg = HashAlgorithm::kSha256;
  ABSL_ASSIGN_OR_RETURN(
      *request.mutable_hard_binding()->mutable_collection_data_hash(),
      CollectionDataHashTemplate(file_entries, alg));
  ABSL_ASSIGN_OR_RETURN(ManifestStoreTemplate manifest_store_template,
                        generator_.GenerateManifestStoreTemplate(request));
  constexpr int64_t kMaxManifestStoreSizeBytes = 100 * 1024 * 1024;  // 100 MiB
  if (manifest_store_template.manifest_store_size() <= 0 ||
      manifest_store_template.manifest_store_size() >
          kMaxManifestStoreSizeBytes) {
    return absl::InvalidArgumentError(
        absl::StrCat("invalid manifest store template size: ",
                     manifest_store_template.manifest_store_size()));
  }

  ZipEmbedder embedder;
  ABSL_ASSIGN_OR_RETURN(
      auto copy_and_allocate_result,
      embedder.CopyAndAllocate(source, file_entries,
                               manifest_store_template.manifest_store_size(),
                               destination));

  // Phase 2: Compute final hard binding based on the updated content, finalize
  // the manifest store, and embed the final manifest store in the asset.
  riegeli::Reader* phase2_reader = destination->ReadMode(0);
  if (phase2_reader == nullptr) {
    return absl::InternalError("failed to switch to read mode");
  }

  ABSL_ASSIGN_OR_RETURN(auto phase2_zip_reader,
                        ZipReader::Create(phase2_reader));
  std::vector<ZipReader::FileEntry> phase2_file_entries;
  while (phase2_zip_reader->HasNext()) {
    ABSL_ASSIGN_OR_RETURN(auto entry, phase2_zip_reader->Next());
    phase2_file_entries.push_back(entry);
  }
  FinalizeManifestStoreRequest finalize_request;
  *finalize_request.mutable_manifest_store_template() =
      std::move(manifest_store_template);
  ABSL_ASSIGN_OR_RETURN(
      *finalize_request.mutable_hard_binding()->mutable_collection_data_hash(),
      DigestCollectionDataHash(
          phase2_reader, alg, phase2_file_entries,
          copy_and_allocate_result.central_directory_offset));
  ABSL_ASSIGN_OR_RETURN(auto response,
                        generator_.FinalizeManifestStore(finalize_request));
  if (response.manifest_store().size() !=
      finalize_request.manifest_store_template().manifest_store_size()) {
    return absl::InternalError("manifest store size does not match template");
  }
  ABSL_RETURN_IF_ERROR(embedder.Embed(response.manifest_store(),
                                      copy_and_allocate_result, destination));
  return absl::OkStatus();
}

}  // namespace credentio
