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

#include <string>
#include <vector>

#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "assertion/assertion_parser.h"
#include "assertion/hashed_uri_validator.h"
#include "constants/labels.h"
#include "constants/status_codes.h"
#include "proto/actions_assertion.pb.h"
#include "proto/assertion.pb.h"
#include "proto/hashed_uri.pb.h"
#include "proto/ingredient_assertion.pb.h"
#include "validator/tracker.h"

namespace credentio {
namespace {

bool ValidateHashedUri(const HashedUri& hashed_uri,
                       const HashedUriValidator& hashed_uri_validator,
                       absl::string_view assertion_url,
                       ValidationTracker& validation_tracker) {
  return hashed_uri_validator
      .Validate(hashed_uri, assertion_url, validation_tracker)
      .has_value();
}

bool IsUnsupportedRelatedAssertionLabel(absl::string_view label) {
  return label == kIngredientAssertionV1Label ||
         label == kIngredientAssertionV2Label ||
         label == kIngredientAssertionV3Label ||
         label == kActionsAssertionV1Label || label == kActionsAssertionV2Label;
}

bool ValidateTypeForRelatedAssertion(absl::string_view related_path,
                                     absl::string_view manifest_label,
                                     absl::string_view assertion_url,
                                     ValidationTracker& validation_tracker) {
  const std::vector<absl::string_view> related_tokens =
      absl::StrSplit(related_path, '/');
  if (related_tokens.size() <= 3) {
    return false;
  }

  if (related_tokens[2] != manifest_label) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kAssertionActionMalformed,
        {.url = assertion_url,
         .explanation = "Related Assertion is not in the same manifest as the "
                        "action assertion."});
    return false;
  }

  const absl::string_view label =
      StripMultipleInstanceSuffix(related_tokens.back());
  if (IsUnsupportedRelatedAssertionLabel(label)) {
    validation_tracker.RecordFailure(
        FailureStatusCode::kAssertionActionMalformed,
        {.url = assertion_url,
         .explanation =
             absl::StrCat("unsupported related assertion type: ", label)});
    return false;
  }
  return true;
}

bool ValidateRelatedAssertions(const ActionParameters& parameters,
                               const HashedUriValidator& hashed_uri_validator,
                               absl::string_view manifest_label,
                               absl::string_view assertion_url,
                               ValidationTracker& validation_tracker) {
  for (const auto& related_uri : parameters.related_assertions()) {
    auto path = hashed_uri_validator.Validate(related_uri, assertion_url,
                                              validation_tracker);
    if (!path.has_value()) {
      // Note: C2PA 2.4 Validation
      // (https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_c2pa_actions_validation)
      // states that the HashedUri should be validated (which could add failure
      // codes), and then states to additionally add the failure code
      // assertion.action.malformed if the referenced assertion can not be
      // resolved (i.e. is missing or hash mismatch) this results in two
      // failures for the same issue.
      validation_tracker.RecordFailure(
          FailureStatusCode::kAssertionActionMalformed,
          {.url = assertion_url,
           .explanation = absl::StrCat("could not resolve related assertion: ",
                                       related_uri.url())});
      return false;
    }
    if (!ValidateTypeForRelatedAssertion(*path, manifest_label, assertion_url,
                                         validation_tracker)) {
      return false;
    }
  }
  return true;
}

template <typename ActionsT>
bool ValidateActions(const ActionsT& actions,
                     const HashedUriValidator& hashed_uri_validator,
                     absl::string_view manifest_label,
                     absl::string_view assertion_url,
                     ValidationTracker& validation_tracker) {
  for (const auto& action : actions.actions()) {
    if (!action.has_parameters()) {
      continue;
    }
    for (const auto& ingredient : action.parameters().ingredients()) {
      if (!ValidateHashedUri(ingredient, hashed_uri_validator, assertion_url,
                             validation_tracker)) {
        return false;
      }
    }
    if (!ValidateRelatedAssertions(action.parameters(), hashed_uri_validator,
                                   manifest_label, assertion_url,
                                   validation_tracker)) {
      return false;
    }
  }
  return true;
}

bool ValidateIngredientV3(const IngredientAssertionV3& ingredient,
                          const HashedUriValidator& hashed_uri_validator,
                          absl::string_view assertion_url,
                          ValidationTracker& validation_tracker) {
  // `active_manifest` and `claim_signature` are validated in `ManifestGraph`
  // when appropriate -- the `active_manifest` hash won't validate when the
  // ingredient has redactions.
  return !ingredient.has_thumbnail() ||
         ValidateHashedUri(ingredient.thumbnail(), hashed_uri_validator,
                           assertion_url, validation_tracker);
}
}  // namespace

bool ReferencesValidator::Validate(const Assertion& assertion) const {
  const std::string assertion_url = absl::StrCat(
      kAssertionStoreLabel, kManifestLabelDelimiter, assertion.label());
  switch (assertion.assertion_case()) {
    case Assertion::kActionsV1:
      return ValidateActions(assertion.actions_v1(), hashed_uri_validator_,
                             manifest_label_, assertion_url, tracker_);
    case Assertion::kActions:
      return ValidateActions(assertion.actions(), hashed_uri_validator_,
                             manifest_label_, assertion_url, tracker_);
    case Assertion::kIngredientV3:
      return ValidateIngredientV3(assertion.ingredient_v3(),
                                  hashed_uri_validator_, assertion_url,
                                  tracker_);
    default:
      return true;
  }
}
}  // namespace credentio
