// 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_cbor_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 AssertionCborEncoder& 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
