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

#include <cstdint>
#include <optional>
#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/string_view.h"
#include "absl/types/span.h"
#include "formats/zip/constants.h"
#include "formats/zip/content_type_stream_util.h"
#include "formats/zip/crc.h"
#include "formats/zip/reader.h"
#include "riegeli/base/byte_fill.h"
#include "riegeli/base/types.h"
#include "riegeli/bytes/reader.h"
#include "riegeli/bytes/writer.h"
#include "riegeli/endian/endian_writing.h"

namespace credentio {
namespace {

// A file entry that has been copied from the source to the destination.
struct FileCopied {
  ZipReader::FileEntry entry;
  riegeli::Position offset_in_destination;
};

// Copies a file entry from the source to the destination.
absl::Status CopyFileEntry(riegeli::Reader* absl_nonnull source,
                           const ZipReader::FileEntry& entry,
                           riegeli::Writer* absl_nonnull destination) {
  int64_t file_end = entry.file_range.offset + entry.file_range.length;
  int64_t data_descriptor_length = 0;
  if (entry.has_data_descriptor) {
    source->Seek(file_end);
    ABSL_RETURN_IF_ERROR(source->status());
    std::string buffer;
    source->Read(kZipDataDescriptorSignature.size(), buffer);
    ABSL_RETURN_IF_ERROR(source->status());
    if (buffer == kZipDataDescriptorSignature) {
      data_descriptor_length = kDataDescriptorWithSignatureSize;
    } else {
      data_descriptor_length = kDataDescriptorSize;
    }
  }
  int64_t length =
      file_end + data_descriptor_length - entry.local_file_header_offset;
  source->Seek(entry.local_file_header_offset);
  ABSL_RETURN_IF_ERROR(source->status());
  source->Copy(length, *destination);
  ABSL_RETURN_IF_ERROR(source->status());
  ABSL_RETURN_IF_ERROR(destination->status());

  return absl::OkStatus();
}

// Reads the content types stream from the source, writes the updated stream to
// the destination, including the local file header and the data descriptor (if
// used). Returns a `ContentTypesStreamMetadata` containing the updated metadata
// of the content types stream.
absl::StatusOr<ContentTypesStreamMetadata> WriteUpdatedContentTypesStream(
    riegeli::Reader* absl_nonnull source,
    const ZipReader::FileEntry& content_types_file_entry,
    riegeli::Writer* absl_nonnull destination) {
  if (content_types_file_entry.has_data_descriptor) {
    // Copy the original local file header since they don't need to be updated.
    source->Seek(content_types_file_entry.local_file_header_offset);
    ABSL_RETURN_IF_ERROR(source->status());
    source->Copy(kLocalFileHeaderFixedSize + kOoxmlContentTypesFileName.size() +
                     content_types_file_entry.extra_field_length,
                 *destination);
    ABSL_RETURN_IF_ERROR(source->status());
    ABSL_RETURN_IF_ERROR(destination->status());

    // Read and update the original content types stream from the source.
    ABSL_ASSIGN_OR_RETURN(
        ContentTypesStream content_types_stream,
        ReadContentTypesStream(source, content_types_file_entry));
    ABSL_RETURN_IF_ERROR(UpdateContentTypesStream(
        content_types_stream, kZipC2paManifestMimeType, kZipManifestFileName));
    return WriteContentTypesStream(content_types_stream,
                                   content_types_file_entry.has_data_descriptor,
                                   destination);
  } else {
    return absl::UnimplementedError(
        "Content types stream without a data descriptor is not supported.");
  }
}

// Writes the central directory header for the updated content types stream to
// the destination.
absl::Status WriteUpdatedContentTypesStreamCentralDirectoryHeader(
    riegeli::Reader* absl_nonnull source,
    const ZipReader::FileEntry& original_file_entry,
    const ContentTypesStreamMetadata& content_types_stream_metadata,
    int64_t updated_local_file_header_offset,
    riegeli::Writer* absl_nonnull destination) {
  // Copy the following fields from the original central directory header:
  //   - Central directory file header signature (4 bytes)
  //   - Version made by (2 bytes)
  //   - Version needed to extract (2 bytes)
  //   - General purpose bit flag (2 bytes)
  //   - Compression method (2 bytes)
  //   - File modification time (2 bytes)
  //   - File modification date (2 bytes)
  source->Seek(original_file_entry.central_directory_header_offset);
  ABSL_RETURN_IF_ERROR(source->status());
  source->Copy(16, *destination);
  ABSL_RETURN_IF_ERROR(source->status());
  ABSL_RETURN_IF_ERROR(destination->status());

  // CRC-32 (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(content_types_stream_metadata.crc32,
                                       *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Compressed size (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(
      content_types_stream_metadata.compressed_size, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Uncompressed size (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(
      content_types_stream_metadata.uncompressed_size, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Copy the remaining fields from the original central directory header:
  //   - File name length (2 bytes)
  //   - Extra field length (2 bytes)
  //   - File comment length (2 bytes)
  //   - Disk number start (2 bytes)
  //   - Internal file attributes (2 bytes)
  //   - External file attributes (4 bytes)
  source->Seek(original_file_entry.central_directory_header_offset + 28);
  ABSL_RETURN_IF_ERROR(source->status());
  source->Copy(14, *destination);
  ABSL_RETURN_IF_ERROR(source->status());
  ABSL_RETURN_IF_ERROR(destination->status());

  // Local file header offset (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(updated_local_file_header_offset,
                                       *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // File name
  destination->Write(kOoxmlContentTypesFileName);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Extra field and File comment data
  int64_t extra_and_comment_length = original_file_entry.extra_field_length +
                                     original_file_entry.file_comment_length;
  if (extra_and_comment_length > 0) {
    source->Seek(original_file_entry.central_directory_header_offset +
                 kCentralDirectoryHeaderFixedSize +
                 original_file_entry.file_name.size());
    ABSL_RETURN_IF_ERROR(source->status());
    source->Copy(extra_and_comment_length, *destination);
    ABSL_RETURN_IF_ERROR(source->status());
    ABSL_RETURN_IF_ERROR(destination->status());
  }

  return absl::OkStatus();
}

// Writes the local file header for the manifest store to the destination.
absl::Status WriteManifestLocalFileHeader(
    int64_t manifest_store_size, riegeli::Writer* absl_nonnull destination) {
  // Local file header signature (4 bytes)
  destination->Write(kZipLocalFileHeaderSignature);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Version needed to extract (2 bytes)
  riegeli::WriteLittleEndian<uint16_t>(10, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Zero-filled fields:
  //   - General purpose bit flag (2 bytes)
  //   - Compression method (2 bytes, 0 means no compression)
  //   - File modification time (2 bytes)
  //   - File modification date (2 bytes)
  //   - CRC-32 (4 bytes, placeholder)
  destination->Write(riegeli::ByteFill(12));
  ABSL_RETURN_IF_ERROR(destination->status());

  // Compressed size (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(manifest_store_size, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Uncompressed size (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(manifest_store_size, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // File name length (2 bytes, little-endian)
  riegeli::WriteLittleEndian<uint16_t>(kZipManifestFileName.size(),
                                       *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Zero-filled extra field length (2 bytes)
  destination->Write(riegeli::ByteFill(2));
  ABSL_RETURN_IF_ERROR(destination->status());

  // File name
  destination->Write(kZipManifestFileName);
  ABSL_RETURN_IF_ERROR(destination->status());

  return absl::OkStatus();
}

// Writes the central directory header for the manifest store to the
// destination.
absl::Status WriteManifestCentralDirectoryHeader(
    uint32_t manifest_store_size,
    uint32_t manifest_store_local_file_header_offset,
    riegeli::Writer* absl_nonnull destination) {
  // Central directory file header signature (4 bytes)
  destination->Write(kZipCentralDirectorySignature);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Version made by (2 bytes)
  riegeli::WriteLittleEndian<uint16_t>(20, *destination);  // Version 2.0
  ABSL_RETURN_IF_ERROR(destination->status());

  // Version needed to extract (2 bytes)
  riegeli::WriteLittleEndian<uint16_t>(10, *destination);  // Version 1.0
  ABSL_RETURN_IF_ERROR(destination->status());

  // Zero-filled fields:
  //   - General purpose bit flag (2 bytes)
  //   - Compression method (2 bytes, 0 means no compression)
  //   - File modification time (2 bytes)
  //   - File modification date (2 bytes)
  //   - CRC-32 (4 bytes, placeholder)
  destination->Write(riegeli::ByteFill(12));
  ABSL_RETURN_IF_ERROR(destination->status());

  // Compressed size (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(manifest_store_size, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Uncompressed size (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(manifest_store_size, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // File name length (2 bytes, little-endian)
  riegeli::WriteLittleEndian<uint16_t>(kZipManifestFileName.size(),
                                       *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Zero-filled fields:
  //   - Extra field length (2 bytes)
  //   - File comment length (2 bytes)
  //   - Disk number start (2 bytes)
  //   - Internal file attributes (2 bytes)
  //   - External file attributes (4 bytes)
  destination->Write(riegeli::ByteFill(12));
  ABSL_RETURN_IF_ERROR(destination->status());

  // Local file header offset (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(manifest_store_local_file_header_offset,
                                       *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // File name
  destination->Write(kZipManifestFileName);
  ABSL_RETURN_IF_ERROR(destination->status());

  return absl::OkStatus();
}

// Writes the central directory header for a copied file entry to the
// destination.
absl::Status WriteCentralDirectoryHeader(
    riegeli::Reader* absl_nonnull source, const FileCopied& file_copied,
    riegeli::Writer* absl_nonnull destination) {
  source->Seek(file_copied.entry.central_directory_header_offset);
  ABSL_RETURN_IF_ERROR(source->status());

  int64_t total_cd_length = kCentralDirectoryHeaderFixedSize +
                            file_copied.entry.file_name.size() +
                            file_copied.entry.extra_field_length +
                            file_copied.entry.file_comment_length;

  if (file_copied.offset_in_destination ==
      file_copied.entry.local_file_header_offset) {
    source->Copy(total_cd_length, *destination);
    ABSL_RETURN_IF_ERROR(source->status());
    ABSL_RETURN_IF_ERROR(destination->status());
  } else {
    source->Copy(kCentralDirectoryHeaderFixedSize - 4, *destination);
    ABSL_RETURN_IF_ERROR(source->status());
    ABSL_RETURN_IF_ERROR(destination->status());

    riegeli::WriteLittleEndian<uint32_t>(file_copied.offset_in_destination,
                                         *destination);
    ABSL_RETURN_IF_ERROR(destination->status());

    source->Skip(4);
    ABSL_RETURN_IF_ERROR(source->status());

    int64_t remaining_length = file_copied.entry.file_name.size() +
                               file_copied.entry.extra_field_length +
                               file_copied.entry.file_comment_length;
    source->Copy(remaining_length, *destination);
    ABSL_RETURN_IF_ERROR(source->status());
    ABSL_RETURN_IF_ERROR(destination->status());
  }
  return absl::OkStatus();
}

// Updates the End of Central Directory (EOCD) record with the new central
// directory offset, length and entry count.
absl::Status UpdateEndOfCentralDirectory(
    riegeli::Reader* absl_nonnull source, uint32_t central_directory_offset,
    uint32_t central_directory_length, uint16_t entry_count,
    riegeli::Writer* absl_nonnull destination) {
  // The first 8 bytes of the EOCD don't need to be updated.
  auto source_size = source->Size();
  if (!source_size.has_value()) return source->status();
  source->Seek(*source_size - kEocdRecordSize);
  ABSL_RETURN_IF_ERROR(source->status());
  source->Copy(8, *destination);
  ABSL_RETURN_IF_ERROR(source->status());
  ABSL_RETURN_IF_ERROR(destination->status());

  // Total number of entries in the central directory on this disk (2 bytes,
  // little-endian)
  riegeli::WriteLittleEndian<uint16_t>(entry_count, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Total number of entries in the central directory (2 bytes, little-endian)
  riegeli::WriteLittleEndian<uint16_t>(entry_count, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Size of the central directory (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(central_directory_length, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Offset of the start of the central directory (4 bytes, little-endian)
  riegeli::WriteLittleEndian<uint32_t>(central_directory_offset, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  // Zero-filled comment length (2 bytes)
  destination->Write(riegeli::ByteFill(2));
  ABSL_RETURN_IF_ERROR(destination->status());

  return absl::OkStatus();
}

}  // namespace

absl::StatusOr<ZipEmbedder::CopyAndAllocateResult> ZipEmbedder::CopyAndAllocate(
    riegeli::Reader* absl_nonnull source,
    absl::Span<const ZipReader::FileEntry> file_entries,
    int64_t manifest_store_size,
    riegeli::Writer* absl_nonnull destination) const {
  ABSL_ASSIGN_OR_RETURN(std::vector<ZipReader::FileEntry> sorted_entries,
                        ZipReader::SortFileEntries(file_entries));

  // Step 1: Copy all the files in the ZIP archive from the source to the
  // destination, except the content types stream.
  std::vector<FileCopied> files_copied;
  std::optional<ZipReader::FileEntry> content_types_file_entry;
  for (const auto& entry : sorted_entries) {
    if (entry.file_name == kOoxmlContentTypesFileName) {
      content_types_file_entry = entry;
      continue;
    }
    if (entry.file_name == kZipManifestFileName) {
      return absl::AlreadyExistsError("Manifest store already exists.");
    }
    files_copied.push_back(
        {.entry = entry, .offset_in_destination = destination->pos()});
    ABSL_RETURN_IF_ERROR(CopyFileEntry(source, entry, destination));
  }

  // Step 2: Write the updated content types stream to the destination.
  if (!content_types_file_entry.has_value()) {
    return absl::NotFoundError("Content types stream not found.");
  }
  auto content_types_stream_output_offset = destination->pos();
  ABSL_ASSIGN_OR_RETURN(ContentTypesStreamMetadata content_types_metadata,
                        WriteUpdatedContentTypesStream(
                            source, *content_types_file_entry, destination));

  // Step 3: Write the zero-filled manifest store to the destination.
  auto manifest_store_local_file_header_offset = destination->pos();
  ABSL_RETURN_IF_ERROR(
      WriteManifestLocalFileHeader(manifest_store_size, destination));
  auto manifest_store_offset = destination->pos();
  destination->Write(riegeli::ByteFill(manifest_store_size));
  ABSL_RETURN_IF_ERROR(destination->status());

  // Step 4: Write the central directory headers.
  auto central_directory_offset = destination->pos();
  for (const auto& file : files_copied) {
    ABSL_RETURN_IF_ERROR(
        WriteCentralDirectoryHeader(source, file, destination));
  }
  ABSL_RETURN_IF_ERROR(WriteUpdatedContentTypesStreamCentralDirectoryHeader(
      source, *content_types_file_entry, content_types_metadata,
      content_types_stream_output_offset, destination));
  auto manifest_store_central_directory_header_offset = destination->pos();
  ABSL_RETURN_IF_ERROR(WriteManifestCentralDirectoryHeader(
      manifest_store_size, manifest_store_local_file_header_offset,
      destination));

  // Step 5: Update the End of Central Directory (EOCD).
  ABSL_RETURN_IF_ERROR(UpdateEndOfCentralDirectory(
      source, central_directory_offset,
      /*central_directory_length=*/destination->pos() -
          central_directory_offset,
      files_copied.size() + 2, destination));

  destination->Flush();
  ABSL_RETURN_IF_ERROR(destination->status());

  return CopyAndAllocateResult{
      .manifest_store_offset = manifest_store_offset,
      .manifest_store_central_directory_header_offset =
          manifest_store_central_directory_header_offset,
      .central_directory_offset = central_directory_offset,
  };
}

absl::Status ZipEmbedder::Embed(
    absl::string_view manifest_store,
    const CopyAndAllocateResult& copy_and_allocate_result,
    riegeli::Writer* absl_nonnull destination) const {
  if (!destination->SupportsRandomAccess()) {
    return absl::InvalidArgumentError(
        "ZipEmbedder::Embed requires a riegeli::Writer that supports random "
        "access.");
  }
  uint32_t crc32 = ZipFileCrc(manifest_store);

  int64_t local_file_header_crc_offset =
      copy_and_allocate_result.manifest_store_offset -
      kZipManifestFileName.size() - 16;
  int64_t central_directory_header_crc_offset =
      copy_and_allocate_result.manifest_store_central_directory_header_offset +
      16;

  // Replace the zero-filled manifest store placeholder with the actual manifest
  // store. Also update the CRC-32 fields in both the local file header and the
  // central directory header with the actual CRC-32 of the manifest store.
  destination->Seek(local_file_header_crc_offset);
  ABSL_RETURN_IF_ERROR(destination->status());
  riegeli::WriteLittleEndian<uint32_t>(crc32, *destination);
  ABSL_RETURN_IF_ERROR(destination->status());

  destination->Seek(copy_and_allocate_result.manifest_store_offset);
  ABSL_RETURN_IF_ERROR(destination->status());
  destination->Write(manifest_store);
  ABSL_RETURN_IF_ERROR(destination->status());

  destination->Seek(central_directory_header_crc_offset);
  ABSL_RETURN_IF_ERROR(destination->status());
  riegeli::WriteLittleEndian<uint32_t>(crc32, *destination);
  return destination->status();
}

}  // namespace credentio
