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

#include <optional>

#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "assertion/parse_assertion.h"
#include "constants/labels.h"
#include "constants/status_codes.h"
#include "google/protobuf/struct.pb.h"
#include "proto/assertion.pb.h"
#include "validator/tracker.h"

namespace credentio {

namespace {
void RecordAssertionParsingFailure(absl::string_view label, absl::Status error,
                                   ValidationTracker& validation_tracker) {
  validation_tracker.RecordFailure(
      FailureStatusCode::kAssertionCborInvalid,
      {.url =
           absl::StrCat(kAssertionStoreLabel, kManifestLabelDelimiter, label),
       .explanation = absl::StrCat("Failed to parse the assertion with label: ",
                                   label, " and error: ", error.message())});
}

bool IsBmffBasedHashLabel(absl::string_view label) {
  return label == kBmffBasedHashAssertionV2Label ||
         label == kBmffBasedHashAssertionV3Label ||
         label == kBmffBasedHashAssertionV2PartLabel ||
         label == kBmffBasedHashAssertionV3PartLabel;
}

bool IsDataHashLabel(absl::string_view label) {
  return label == kDataHashAssertionLabel ||
         label == kDataHashAssertionPartLabel;
}

bool IsUnsupportedIngredientLabel(absl::string_view label) {
  return label == kIngredientAssertionV1Label ||
         label == kIngredientAssertionV2Label;
}

bool IsBoxesHashLabel(absl::string_view label) {
  return label == kBoxesHashAssertionLabel ||
         label == kBoxesHashAssertionPartLabel;
}

bool IsCollectionDataHashLabel(absl::string_view label) {
  return label == kCollectionDataHashAssertionLabel ||
         label == kCollectionDataHashAssertionPartLabel;
}

}  // namespace

absl::string_view StripMultipleInstanceSuffix(absl::string_view label) {
  return label.substr(0, label.find("__"));
}

bool AssertionTypeMatcher::Matches(absl::string_view label) const {
  return StripMultipleInstanceSuffix(label) == label_;
}

std::optional<Assertion> AssertionParser::ParseCbor(
    absl::string_view label, absl::string_view content,
    ValidationTracker& validation_tracker) const {
  absl::string_view stripped_label = StripMultipleInstanceSuffix(label);
  if (IsUnsupportedIngredientLabel(stripped_label)) {
    // Unlike other assertion types, it's not safe to ignore an unsupported
    // ingredient assertion.
    validation_tracker.RecordFailure(
        FailureStatusCode::kGoogleUnsupportedSpecVersion,
        {.url =
             absl::StrCat(kAssertionStoreLabel, kManifestLabelDelimiter, label),
         .explanation = "c2pa.ingredient (v1) and c2pa.ingredient.v2 "
                        "assertions are not supported"});
    return std::nullopt;
  }

  Assertion assertion;
  assertion.set_label(label);
  absl::Status status;

  if (stripped_label == kActionsAssertionV2Label) {
    status = ParseAssertion(content, assertion.mutable_actions());
  } else if (stripped_label == kActionsAssertionV1Label) {
    status = ParseAssertion(content, assertion.mutable_actions_v1());
  } else if (IsBmffBasedHashLabel(stripped_label)) {
    status = ParseAssertion(content, assertion.mutable_bmff_based_hash());
  } else if (IsDataHashLabel(stripped_label)) {
    status = ParseAssertion(content, assertion.mutable_data_hash());
  } else if (stripped_label == kIngredientAssertionV3Label) {
    status = ParseAssertion(content, assertion.mutable_ingredient_v3());
  } else if (IsBoxesHashLabel(stripped_label)) {
    status = ParseAssertion(content, assertion.mutable_boxes_hash());
  } else if (stripped_label == kMultiAssetHashAssertionLabel) {
    status = ParseAssertion(content, assertion.mutable_multi_asset_hash());
  } else if (IsCollectionDataHashLabel(stripped_label)) {
    status = ParseAssertion(content, assertion.mutable_collection_data_hash());
  } else if (stripped_label == kAiDisclosureAssertionLabel) {
    status = ParseAssertion(content, assertion.mutable_ai_disclosure());
  } else if (stripped_label == kEnvironmentalSustainabilityAssertionLabel) {
    status = ParseAssertion(content,
                            assertion.mutable_environmental_sustainability());
  } else if (stripped_label == kSoftBindingAssertionLabel) {
    status = ParseAssertion(content, assertion.mutable_soft_binding());
  } else {
    return std::nullopt;
  }

  if (!status.ok()) {
    RecordAssertionParsingFailure(label, status, validation_tracker);
    return std::nullopt;
  }
  return assertion;
}

std::optional<Assertion> AssertionParser::ParseThumbnail(
    absl::string_view label, absl::string_view media_type,
    absl::string_view data, std::optional<absl::string_view> file_name,
    ValidationTracker& validation_tracker) const {
  Assertion assertion;
  assertion.set_label(label);
  if (absl::StartsWith(label, kThumbnailClaimAssertionLabelPrefix)) {
    *assertion.mutable_claim_thumbnail() =
        ParseThumbnailAssertion(media_type, data, file_name);
    return assertion;
  }
  if (absl::StartsWith(label, kThumbnailIngredientAssertionLabelPrefix)) {
    *assertion.mutable_ingredient_thumbnail() =
        ParseThumbnailAssertion(media_type, data, file_name);
    return assertion;
  }
  return std::nullopt;
}

std::optional<Assertion> AssertionParser::ParseMetadata(
    absl::string_view label, absl::string_view content,
    ValidationTracker& validation_tracker) const {
  Assertion assertion;
  assertion.set_label(label);
  absl::string_view stripped_label = StripMultipleInstanceSuffix(label);

  if (stripped_label == kRepositoryReceiptAssertionLabel) {
    if (auto status =
            ParseAssertion(content, assertion.mutable_repository_receipt());
        !status.ok()) {
      validation_tracker.RecordFailure(
          FailureStatusCode::kAssertionJsonInvalid,
          {.url = absl::StrCat(kAssertionStoreLabel, kManifestLabelDelimiter,
                               label),
           .explanation =
               absl::StrCat("Failed to parse the assertion with label: ", label,
                            " and error: ", status.message())});
      return std::nullopt;
    }
    return assertion;
  }

  if (!absl::EndsWith(stripped_label, kMetadataAssertionLabelSuffix)) {
    return std::nullopt;
  }
  if (auto status =
          ParseStruct(content, assertion.mutable_metadata()->mutable_value());
      !status.ok()) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kAssertionJsonInvalid,
        {.url =
             absl::StrCat(kAssertionStoreLabel, kManifestLabelDelimiter, label),
         .explanation =
             absl::StrCat("Failed to parse the assertion with label: ", label,
                          " and error: ", status.message())});
    return std::nullopt;
  }
  if (!assertion.metadata().value().fields().contains("@context")) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kGeneralError,
        {.url =
             absl::StrCat(kAssertionStoreLabel, kManifestLabelDelimiter, label),
         .explanation = "Metadata doesn't have @context"});
    return std::nullopt;
  }
  return assertion;
}

}  // namespace credentio
