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

#include <optional>
#include <utility>

#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "constants/labels.h"
#include "cose/sig_structure.h"
#include "jumbf/box.h"
#include "jumbf/parse.h"

namespace credentio {
namespace {
bool IsManifestStore(const jumbf::SuperBox& superbox) {
  return superbox.description.type_uuid == kManifestStoreUuid &&
         superbox.description.label == kManifestStoreLabel;
}

bool IsManifest(const jumbf::SuperBox& superbox) {
  return superbox.description.type_uuid == kStandardManifestUuid ||
         superbox.description.type_uuid == kUpdateManifestUuid ||
         superbox.description.type_uuid == kTimestampManifestUuid ||
         superbox.description.type_uuid == kCompressedManifestUuid;
}

bool IsClaimSignature(const jumbf::SuperBox& superbox) {
  return superbox.description.type_uuid == kClaimSignatureUuid &&
         superbox.description.label == kClaimSignatureLabel;
}
}  // namespace

absl::StatusOr<ManifestStoreView> ManifestStoreView::Create(
    absl::string_view manifest_store) {
  ABSL_ASSIGN_OR_RETURN(
      auto super_box_res,
      jumbf::ConsumeSuperBox(&manifest_store, /*recursion_limit=*/4));
  jumbf::SuperBox super_box = std::move(super_box_res);
  if (!IsManifestStore(super_box)) {
    return absl::InvalidArgumentError("No C2PA manifest store");
  }
  return ManifestStoreView(std::move(super_box));
}

absl::StatusOr<ManifestView> ManifestStoreView::GetActiveManifest() const {
  const jumbf::SuperBox* active_manifest = nullptr;
  for (const auto& box : superbox_.contents) {
    if (box.Holds<jumbf::SuperBox>()) {
      const auto& superbox = box.Get<jumbf::SuperBox>();
      if (IsManifest(superbox)) {
        active_manifest = &superbox;
      }
    }
  }
  if (active_manifest == nullptr) {
    return absl::InvalidArgumentError("No active manifest found");
  }
  return ManifestView::Create(*active_manifest);
}

absl::StatusOr<ManifestView> ManifestView::Create(jumbf::SuperBox superbox) {
  if (!IsManifest(superbox)) {
    return absl::InvalidArgumentError("Not a manifest box");
  }
  if (superbox.description.type_uuid == kCompressedManifestUuid) {
    return absl::InvalidArgumentError("Compressed manifests are not supported");
  }
  return ManifestView(std::move(superbox));
}

absl::StatusOr<ClaimSignatureView> ManifestView::GetClaimSignature() const {
  std::optional<jumbf::SuperBox> claim_signature_superbox = std::nullopt;
  for (const auto& content : superbox_.contents) {
    if (content.Holds<jumbf::SuperBox>() &&
        IsClaimSignature(content.Get<jumbf::SuperBox>())) {
      claim_signature_superbox = content.Get<jumbf::SuperBox>();
      break;
    }
  }
  if (!claim_signature_superbox.has_value()) {
    return absl::InvalidArgumentError(
        "No claim signature found in the manifest");
  }
  return ClaimSignatureView::Create(claim_signature_superbox.value());
}

absl::string_view ManifestView::label() const {
  return superbox_.description.label.value_or("");
}

absl::StatusOr<ClaimSignatureView> ClaimSignatureView::Create(
    jumbf::SuperBox superbox) {
  if (!IsClaimSignature(superbox)) {
    return absl::InvalidArgumentError("Not a claim signature box");
  }
  return ClaimSignatureView(std::move(superbox));
}

absl::StatusOr<absl::string_view> ClaimSignatureView::GetPayload() const {
  if (superbox_.contents.size() != 1 ||
      !superbox_.contents[0].Holds<jumbf::CborBox>()) {
    return absl::InvalidArgumentError("Invalid claim signature box");
  }
  return superbox_.contents[0].Get<jumbf::CborBox>().payload;
}

absl::StatusOr<CoseSign1TaggedStructure> ClaimSignatureView::GetStruct() const {
  ABSL_ASSIGN_OR_RETURN(auto payload_res, GetPayload());
  return DecodeCoseSign1TaggedStructure(payload_res);
}

}  // namespace credentio
