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

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

#include "absl/base/nullability.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/cord.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "crypto/algorithms.h"
#include "formats/hasher_data.h"
#include "formats/id3/embedder.h"
#include "proto/generator.pb.h"
#include "riegeli/bytes/cord_reader.h"
#include "riegeli/bytes/cord_writer.h"
#include "riegeli/bytes/writer.h"

namespace credentio {
namespace {

// Copies the input to the output cord, with the given manifest store embedded,
// and returns the offset of the manifest store in the result.
absl::StatusOr<int64_t> CopyAndEmbedCord(riegeli::Reader& input,
                                         absl::string_view manifest_store,
                                         riegeli::Writer& output) {
  if (!input.Seek(0)) {
    return absl::InternalError("failed to seek to start of input");
  }
  Id3Embedder embedder;
  ABSL_ASSIGN_OR_RETURN(int64_t manifest_store_offset,
                        embedder.CopyAndEmbed(input, manifest_store, output));
  return manifest_store_offset;
}
}  // namespace

absl::Status Id3Writer::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 "
        "Id3Writer)");
  }

  // The two-phase approach is required for ID3-compatible audio: The hash can't
  // be computed correctly until the manifest store size is known, because the
  // manifest size affects the top-level ID3 tag size.

  // Phase 1: 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_data_hash(),
                        DataHashTemplate(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()));
  }
  absl::Cord phase1_result;
  riegeli::CordWriter phase1_writer(&phase1_result);
  ABSL_ASSIGN_OR_RETURN(
      int64_t manifest_store_offset,
      CopyAndEmbedCord(
          *source,
          std::string(manifest_store_template.manifest_store_size(), '\0'),
          phase1_writer));
  if (!phase1_writer.Close()) {
    return absl::InternalError("failed to close phase 1 writer");
  }

  // 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::CordReader phase2_reader(&phase1_result);
  FinalizeManifestStoreRequest finalize_request;
  *finalize_request.mutable_manifest_store_template() =
      std::move(manifest_store_template);
  ABSL_ASSIGN_OR_RETURN(
      *finalize_request.mutable_hard_binding()->mutable_data_hash(),
      DigestDataHash(
          phase2_reader, HashAlgorithm::kSha256,
          /*manifest_store_offset=*/manifest_store_offset,
          /*manifest_store_length=*/
          finalize_request.manifest_store_template().manifest_store_size()));
  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");
  }
  destination->Write(phase1_result.Subcord(0, manifest_store_offset));
  destination->Write(response.manifest_store());
  destination->Write(phase1_result.Subcord(
      manifest_store_offset + response.manifest_store().size(),
      phase1_result.size()));
  return absl::OkStatus();
}
}  // namespace credentio
