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

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

#include "absl/log/absl_check.h"
#include "absl/log/check.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/status_matchers.h"  // IWYU pragma: keep
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "assertion/assertion_encoder.h"
#include "constants/labels.h"
#include "crypto/default/hasher.h"
#include "crypto/hash.h"
#include "jumbf/box.h"
#include "jumbf/constants.h"
#include "jumbf/parse.h"
#include "jumbf/test_utils.h"
#include "proto/assertion.pb.h"
#include "utils/byte_readers.h"
#include "utils/byte_writers.h"
#include "uuid/uuid.h"

namespace credentio {
namespace {

absl::StatusOr<absl::string_view> TrimJumbfHeader(absl::string_view raw_bytes) {
  ABSL_ASSIGN_OR_RETURN(auto lbox, ConsumeUint<uint32_t>(&raw_bytes));
  ABSL_RETURN_IF_ERROR(SkipBytes<uint32_t>(&raw_bytes));
  if (lbox == 1) {
    auto xlbox_status = SkipBytes<uint64_t>(&raw_bytes);
    ABSL_RETURN_IF_ERROR(xlbox_status);
  }
  return raw_bytes;
}

std::string ComputeHashOrDie(absl::string_view algorithm,
                             absl::string_view contents) {
  auto hasher = CreateHasher(algorithm);
  ABSL_CHECK_OK(hasher) << "Unsupported algorithm: " << algorithm;
  (*hasher)->Update(contents);
  return (*hasher)->Digest();
}

}  // namespace

jumbf::SuperBox ParseSuperBoxOrDie(const std::string* bytes) {
  absl::string_view bytes_view = *bytes;
  auto box = jumbf::ConsumeSuperBox(&bytes_view, /*recursion_limit=*/-1);
  ABSL_CHECK_OK(box);
  ABSL_CHECK_EQ(bytes_view, "");
  return *box;
}

jumbf::SuperBox CreateManifestStore(
    absl::Span<const jumbf::SuperBox> manifests) {
  jumbf::SuperBox box = {
      .description =
          {
              .type_uuid = kManifestStoreUuid,
              .label = kManifestStoreLabel,
          },
      .raw_bytes = "b64'testing'",
  };
  for (const auto& m : manifests) {
    box.contents.push_back({.payload = m});
  }
  return box;
}

jumbf::SuperBox CreateStandardManifest(
    absl::string_view label, absl::Span<const jumbf::SuperBox> boxes) {
  jumbf::SuperBox box = {
      .description =
          {
              .type_uuid = kStandardManifestUuid,
              .label = label,
          },
      .raw_bytes = "b64'testing'",
  };
  for (const auto& b : boxes) {
    box.contents.push_back({.payload = b});
  }
  return box;
}

jumbf::SuperBox CreateUpdateManifest(absl::string_view label,
                                     absl::Span<const jumbf::SuperBox> boxes) {
  jumbf::SuperBox box = {
      .description =
          {
              .type_uuid = kUpdateManifestUuid,
              .label = label,
          },
      .raw_bytes = "b64'testing'",
  };
  for (const auto& b : boxes) {
    box.contents.push_back({.payload = b});
  }
  return box;
}

std::string EncodeClaimSignatureBox(absl::string_view cbor) {
  return jumbf::EncodeSuperBox(kClaimSignatureUuid, kClaimSignatureLabel,
                               {jumbf::EncodeCborBox(cbor)});
}

std::string EncodeAssertionBoxOrDie(const Assertion& assertion,
                                    const AssertionEncoder& encoder) {
  auto assertion_cbor = encoder.ToCbor(assertion);
  ABSL_CHECK_OK(assertion_cbor);
  std::string assertion_cbor_box =
      jumbf::EncodeCborBox(std::string(*assertion_cbor));
  return jumbf::EncodeSuperBox(jumbf::kCborBoxTypeUuid, assertion.label(),
                               {assertion_cbor_box}, /*requestable=*/true);
}

jumbf::SuperBox CreateAssertionStoreBox() {
  return {
      .description =
          {
              .type_uuid = kAssertionStoreUuid,
              .label = kAssertionStoreLabel,
          },
      .raw_bytes = "b64'testing'",
  };
}

jumbf::SuperBox CreateAssertionStoreBox(
    absl::Span<const jumbf::SuperBox> assertions) {
  auto assertion_store_box = CreateAssertionStoreBox();
  for (const auto& assertion : assertions) {
    assertion_store_box.contents.push_back({.payload = assertion});
  }
  return assertion_store_box;
}

jumbf::SuperBox CreateAssertionBoxFromCbor(absl::string_view label,
                                           absl::string_view cbor) {
  return {
      .description = {.label = label},
      .contents = {jumbf::ContentBox{.payload =
                                         jumbf::CborBox{.payload = cbor}}},
      .raw_bytes = "b64'testing'",
  };
}

jumbf::SuperBox CreateAssertionBoxFromJson(absl::string_view label,
                                           absl::string_view json) {
  return {
      .description = {.label = label},
      .contents = {jumbf::ContentBox{.payload =
                                         jumbf::JsonBox{.payload = json}}},
      .raw_bytes = "b64'testing'",
  };
}

jumbf::SuperBox CreateAssertionBoxFromEmbeddedFile(
    absl::string_view label, absl::string_view media_type,
    absl::string_view file_contents,
    std::optional<absl::string_view> file_name) {
  return {
      .description = {.label = label},
      .contents = {jumbf::ContentBox{.payload =
                                         jumbf::EmbeddedFileDescriptionBox{
                                             .media_type = media_type,
                                             .file_name = file_name}},
                   jumbf::ContentBox{
                       .payload =
                           jumbf::BinaryDataBox{.payload = file_contents}}},
      .raw_bytes = "b64'testing'",
  };
}

jumbf::SuperBox CreateActionsAssertionBoxFromCbor(absl::string_view cbor) {
  return CreateAssertionBoxFromCbor(kActionsAssertionV2Label, cbor);
}

jumbf::SuperBox CreateBmffBasedHashAssertionBoxFromCbor(
    absl::string_view cbor) {
  return CreateAssertionBoxFromCbor(kBmffBasedHashAssertionV3Label, cbor);
}

jumbf::SuperBox CreateDataHashAssertionBoxFromCbor(absl::string_view cbor) {
  return CreateAssertionBoxFromCbor(kDataHashAssertionLabel, cbor);
}

std::string GetHash(absl::string_view algorithm, const jumbf::SuperBox& box) {
  auto raw_bytes = TrimJumbfHeader(box.raw_bytes);
  ABSL_CHECK_OK(raw_bytes);
  return ComputeHashOrDie(algorithm, *raw_bytes);
}

std::string CreateStartOfManifestStorePayload(
    absl::Span<const uint8_t> prefix) {
  std::vector<uint8_t> bytes;
  bytes.reserve(prefix.size() + 40);
  for (const auto& byte : prefix) {
    bytes.push_back(byte);
  }
  WriteUint32NetworkOrder(10, &bytes);
  WriteUint32NetworkOrder(jumbf::kSuperBoxType, &bytes);
  WriteUint32NetworkOrder(10, &bytes);
  WriteUint32NetworkOrder(jumbf::kDescriptionBoxType, &bytes);
  WriteUint64NetworkOrder(0x6332'7061'0011'0010, &bytes);
  WriteUint64NetworkOrder(0x8000'00AA'0038'9B71, &bytes);
  bytes.push_back(0b0000'0011);
  WriteUint32NetworkOrder('c2pa', &bytes);
  bytes.push_back(0x00);
  return std::string(reinterpret_cast<const char*>(bytes.data()), bytes.size());
}

}  // namespace credentio
