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

#include <cstddef>
#include <memory>
#include <optional>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/nullability.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/check.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "assertion/hashed_uri_validator.h"
#include "constants/ingredient_relationships.h"
#include "constants/labels.h"
#include "constants/status_codes.h"
#include "jumbf/box.h"
#include "proto/assertion.pb.h"
#include "proto/bmff_based_hash_assertion.pb.h"
#include "proto/boxes_hash_assertion.pb.h"
#include "proto/collection_data_hash_assertion.pb.h"
#include "proto/data_hash_assertion.pb.h"
#include "proto/generator_info.pb.h"
#include "proto/hashed_uri.pb.h"
#include "proto/ingredient_assertion.pb.h"
#include "proto/manifest.pb.h"
#include "proto/validation_result.pb.h"
#include "proto/validation_status.pb.h"
#include "uuid/uuid.h"
#include "validator/graph_internals.h"
#include "validator/tracker.h"

namespace credentio {
namespace {

template <typename T>
const Manifest* GetManifest(const T* result, absl::string_view label) {
  if (result->active_manifest().label() == label) {
    return &result->active_manifest();
  }
  for (const auto& ingredient_manifest : result->ingredient_manifests()) {
    if (ingredient_manifest.label() == label) {
      return &ingredient_manifest;
    }
  }
  return nullptr;
}

bool IsIngredientAssertion(const Assertion& assertion) {
  return assertion.has_ingredient_v3();
}

// Returns true if the given label is a hard binding assertion label.
// Does not match multi-asset hash assertions or the "part hash" assertions they
// reference.

// Returns true if the given label is for a hard binding assertion, a
// multi-asset hash assertion, or a "part hash" assertion.

std::optional<HashedUri> GetIngredientManifestHashedUri(
    const Assertion& assertion) {
  if (assertion.ingredient_v3().has_active_manifest()) {
    return assertion.ingredient_v3().active_manifest();
  }
  return std::nullopt;
}

absl::string_view GetIngredientRelationship(const Assertion& assertion) {
  return assertion.ingredient_v3().relationship();
}

std::string GetAssertionUri(absl::string_view manifest_label,
                            const Assertion& assertion) {
  return absl::StrJoin({absl::StrCat(kManifestStoreUrlPrefix, manifest_label),
                        kAssertionStoreLabel, assertion.label()},
                       kManifestLabelDelimiter);
}

// No failures are recorded in the tracker for this method as these failures
// are recorded during the ValidateNode call.
std::optional<std::string> GetHardBindingUri(
    const PartialValidationResultProto& result,
    absl::string_view manifest_label, ValidationTracker& tracker) {
  if (manifest_label.empty()) {
    return std::nullopt;
  }
  auto* manifest_with_content_bindings = GetManifest(&result, manifest_label);
  if (manifest_with_content_bindings == nullptr) {
    return std::nullopt;
  }

  std::optional<std::string> uri;
  for (const auto& assertion : manifest_with_content_bindings->assertions()) {
    if ((assertion.has_bmff_based_hash() || assertion.has_boxes_hash() ||
         assertion.has_data_hash() || assertion.has_collection_data_hash()) &&
        !absl::StrContains(assertion.label(), ".part")) {
      uri = GetAssertionUri(manifest_label, assertion);
      break;
    }
  }
  return uri;
}

// No failures are recorded in the tracker for this method as these failures
// are recorded during the ValidateNode call.
std::optional<std::string> GetMultiAssetHashUri(
    const PartialValidationResultProto& result,
    absl::string_view manifest_label, ValidationTracker& tracker) {
  if (manifest_label.empty()) {
    return std::nullopt;
  }
  auto* manifest_with_content_bindings = GetManifest(&result, manifest_label);
  if (manifest_with_content_bindings == nullptr) {
    return std::nullopt;
  }

  std::optional<std::string> uri;
  for (const auto& assertion : manifest_with_content_bindings->assertions()) {
    if (assertion.has_multi_asset_hash()) {
      uri = GetAssertionUri(manifest_label, assertion);
      break;
    }
  }
  return uri;
}

void SetHardBindingUri(absl::string_view manifest_with_content_bindings_label,
                       PartialValidationResultProto& result) {
  ValidationTracker tracker(result.mutable_active_manifest());

  if (result.active_manifest().label().empty()) {
    return;
  }
  if (auto hard_binding_uri = GetHardBindingUri(
          result, manifest_with_content_bindings_label, tracker);
      hard_binding_uri.has_value()) {
    result.set_hard_binding_uri(*hard_binding_uri);
  }
  if (auto multi_asset_hash_uri = GetMultiAssetHashUri(
          result, manifest_with_content_bindings_label, tracker);
      multi_asset_hash_uri.has_value()) {
    result.set_multi_asset_hash_uri(*multi_asset_hash_uri);
  }
}

// Returns the containing manifest path from the given assertion path, or
// nullopt if the assertion path is invalid.
std::optional<absl::string_view> ManifestPathFromAssertionPath(
    absl::string_view path) {
  // Absolute assertion path should look like `/c2pa/<manifest
  // label>/c2pa.assertions/...`. Find the position of the third slash to
  // extract the manifest path.
  if (path.empty() || path[0] != '/') {
    return std::nullopt;
  }
  size_t second_slash = path.find('/', 1);
  if (second_slash == std::string::npos) {
    return std::nullopt;
  }
  size_t third_slash = path.find('/', second_slash + 1);
  if (third_slash == std::string::npos) {
    return std::nullopt;
  }
  return path.substr(0, third_slash);
}

absl::string_view ManifestLabel(const jumbf::SuperBox& node) {
  return node.description.label.value_or("");
}

std::string ManifestPath(const jumbf::SuperBox& node) {
  return absl::StrCat("/c2pa/", ManifestLabel(node));
}

// Applies checks based on the manifest type, returning true if processing
// should continue.
bool CheckManifestType(Manifest& manifest, credentio::Uuid type_uuid,
                       std::string* manifest_with_content_bindings_label,
                       ValidationTracker& tracker) {
  if (type_uuid == kStandardManifestUuid) {
    if (manifest_with_content_bindings_label->empty()) {
      // This is either the active manifest or the first standard manifest
      // found by following the chain of parent ingredients from the active
      // manifest.
      *manifest_with_content_bindings_label = manifest.label();
    }
    return true;
  }
  if (type_uuid == kUpdateManifestUuid) {
    // Update manifest checks are performed in the assertion validator.
    manifest.set_is_update_manifest(true);
    return true;
  }
  if (type_uuid == kCompressedManifestUuid) {
    tracker.RecordFailure(
        FailureStatusCode::kGoogleUnsupportedManifestType,
        {.explanation = "Compressed manifests not supported"});
    return false;
  }
  if (type_uuid == kTimestampManifestUuid) {
    // No need to support time-stamp manifests (deprecated in C2PA 2.2).
    tracker.RecordFailure(FailureStatusCode::kGoogleUnsupportedManifestType,
                          {.explanation = "Timestamp manifests not supported"});
    return false;
  }
  tracker.RecordFailure(
      FailureStatusCode::kGoogleUnsupportedManifestType,
      {.explanation =
           absl::StrCat("Unrecognized manifest type: ", type_uuid.ToString())});
  return false;
}

// Returns true if the manifest label uses a legacy (pre-C2PA-2.1) format.
bool IsLegacyManifestLabel(absl::string_view manifest_label) {
  return !absl::StartsWith(manifest_label, "urn:c2pa");
}

}  // namespace

absl::StatusOr<std::unique_ptr<PartialValidationResultProto>>
ManifestGraph::Validate() {
  ABSL_RETURN_IF_ERROR(ValidateGraph());
  ABSL_ASSIGN_OR_RETURN(auto result, ValidatePostProcess());
  // At this point, the set of redacted assertions and the set of ingredient
  // manifests should be fully populated. We can perform the second pass of the
  // ingredient validation algorithm in
  // https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_performing_explicit_validation.
  return ValidateWithRedactions(std::move(result));
}

absl::StatusOr<std::unique_ptr<PartialValidationResultProto>>
ManifestGraph::ValidatePostProcess() {
  auto result = std::make_unique<PartialValidationResultProto>();
  for (const auto& ingredient_manifest_path : ingredient_manifest_paths_) {
    ABSL_ASSIGN_OR_RETURN(auto manifest_state,
                          GetValidatedManifestState(ingredient_manifest_path));
    absl::flat_hash_set<std::pair<absl::string_view, absl::string_view>>
        existing_failures;
    existing_failures.reserve(
        manifest_state->manifest.validation().failures_size());
    for (const auto& failure :
         manifest_state->manifest.validation().failures()) {
      existing_failures.insert(std::make_pair(failure.code(), failure.url()));
    }
    for (const IngredientAssertion& assertion :
         manifest_state->referencing_ingredient_assertions) {
      PropagateFailuresFromIngredientAssertion(
          assertion.assertion->ingredient_v3(),
          *manifest_state->manifest.mutable_validation(), existing_failures);
    }
    *result->add_ingredient_manifests() = std::move(manifest_state->manifest);
  }
  ABSL_ASSIGN_OR_RETURN(
      auto active_manifest_state,
      GetValidatedManifestState(ManifestPath(active_manifest_)));
  *result->mutable_active_manifest() =
      std::move(active_manifest_state->manifest);
  SetHardBindingUri(manifest_with_content_bindings_label_, *result);
  return result;
}

std::optional<std::string> ManifestGraph::ProcessIngredientAssertion(
    const Assertion& assertion, absl::string_view manifest_path,
    absl::string_view default_algorithm, ValidationTracker& tracker) {
  const std::string assertion_url = absl::StrCat(
      kAssertionStoreLabel, kManifestLabelDelimiter, assertion.label());
  std::optional<HashedUri> manifest_hashed_uri =
      GetIngredientManifestHashedUri(assertion);
  if (!manifest_hashed_uri.has_value()) {
    // Record informational code if the ingredient assertion does not have
    // an `active_manifest` field, unless relationship is `inputTo` (Step
    // 7-a-iii in the algorithm).
    if (GetIngredientRelationship(assertion) !=
        kIngredientRelationshipInputTo) {
      tracker.RecordInformational(
          InformationalStatusCode::kIngredientUnknownProvenance,
          {.url = assertion_url});
    }
    return std::nullopt;
  }
  auto absolute_path = uri_resolver_.GetAbsolutePathFromUri(
      manifest_hashed_uri->url(), manifest_path);
  if (!absolute_path.ok()) {
    tracker.RecordFailure(FailureStatusCode::kIngredientManifestMissing,
                          {.url = assertion_url});
    return std::nullopt;
  }
  if (assertion.ingredient_v3().has_claim_signature()) {
    // Validate the claim signature hash.
    const auto& claim_signature = assertion.ingredient_v3().claim_signature();
    HashedUriValidator claim_signature_hash_validator(
        std::string(manifest_path), uri_resolver_, &hash_checker_factory_);
    claim_signature_hash_validator.SetErrorCodes(HashedUriValidator::Codes{
        .missing = FailureStatusCode::kIngredientClaimSignatureMissing,
        .mismatch = FailureStatusCode::kIngredientClaimSignatureMismatch});
    claim_signature_hash_validator.SetDefaultAlgorithm(
        std::string(default_algorithm));
    auto path = claim_signature_hash_validator.Validate(claim_signature,
                                                        assertion_url, tracker);
    if (!path.has_value()) {
      return std::nullopt;  // Validation failure status has been recorded.
    }
    tracker.RecordSuccess(SuccessStatusCode::kIngredientClaimSignatureValidated,
                          {.url = assertion_url});
  } else {
    // Validate the manifest hash.
    HashedUriValidator manifest_hash_validator(
        std::string(manifest_path), uri_resolver_, &hash_checker_factory_);
    manifest_hash_validator.SetErrorCodes(HashedUriValidator::Codes{
        .missing = FailureStatusCode::kIngredientManifestMissing,
        .mismatch = FailureStatusCode::kIngredientManifestMismatch});
    manifest_hash_validator.SetDefaultAlgorithm(std::string(default_algorithm));
    auto path = manifest_hash_validator.Validate(*manifest_hashed_uri,
                                                 assertion_url, tracker);
    if (!path.has_value()) {
      return std::nullopt;  // Validation failure status has been recorded.
    }
    tracker.RecordSuccess(SuccessStatusCode::kIngredientManifestValidated,
                          {.url = assertion_url});
  }
  return *absolute_path;
}

ManifestGraph::ManifestState& ManifestGraph::GetOrCreateManifestState(
    absl::string_view path) {
  auto [it, inserted] = manifests_.insert({std::string(path), nullptr});
  if (inserted) {
    it->second = std::make_unique<ManifestState>();
  }
  return *it->second;
}

absl::StatusOr<ManifestGraph::ManifestState* absl_nonnull>
ManifestGraph::GetValidatedManifestState(absl::string_view path) {
  auto it = manifests_.find(path);
  if (it == manifests_.end()) {
    return absl::InternalError(
        absl::StrCat("manifest state not found: ", path));
  }
  if (it->second->validation_state != InternalValidationState::kValidated) {
    return absl::InternalError(
        absl::StrCat("manifest is not yet validated: ", path));
  }
  return it->second.get();
}

absl::Status ManifestGraph::ValidateGraph() {
  std::stack<const jumbf::SuperBox*> to_visit;
  to_visit.push(&active_manifest_);
  bool is_active_manifest = true;
  while (!to_visit.empty()) {
    const jumbf::SuperBox* node = to_visit.top();
    to_visit.pop();
    ABSL_RETURN_IF_ERROR(ValidateNode(*node,
                                      /*is_active_manifest=*/is_active_manifest,
                                      to_visit));
    is_active_manifest = false;
  }
  return absl::OkStatus();
}

// Validates the claim and assertions for the given "node" that represents a
// manifest in the manifest graph. Calling this function for a node is similar
// to jumping to Step 3 in the ingredient validation algorithm in
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_performing_explicit_validation
// for a target manifest represented by this node in the manifest graph.
//
// The method:
// * Locates and validates the claim (Step 4 in the algorithm).
// * Updates the set of redacted assertions (Step 5 in the algorithm).
// * Validates all assertions in the claim (Step 6 in the algorithm).
// * Finally, the method pushes all eligible ingredient manifests onto the
//   `to_visit` stack (Step 7 in the algorithm).
absl::Status ManifestGraph::ValidateNode(
    const jumbf::SuperBox& node, bool is_active_manifest,
    std::stack<const jumbf::SuperBox*>& to_visit) {
  absl::string_view manifest_label = ManifestLabel(node);
  std::string manifest_path = ManifestPath(node);
  ManifestState& manifest_state = GetOrCreateManifestState(manifest_path);
  if (manifest_state.validation_state == InternalValidationState::kValidated) {
    return absl::OkStatus();
  }
  if (!is_active_manifest) ingredient_manifest_paths_.push_back(manifest_path);
  InternalValidationStateLock validation_state_lock(&manifest_state);

  Manifest& manifest = manifest_state.manifest;
  manifest.set_label(manifest_label);
  ValidationTracker tracker(&manifest);
  {
    if (IsLegacyManifestLabel(manifest_label)) {
      tracker.RecordFailure(
          FailureStatusCode::kGoogleUnsupportedSpecVersion,
          {.explanation = "deprecated manifest label format"});
      return absl::OkStatus();
    }
    if (!CheckManifestType(manifest, node.description.type_uuid,
                           &manifest_with_content_bindings_label_, tracker)) {
      return absl::OkStatus();
    }

    auto validated_claim = claim_validator_.Validate(node, tracker);
    if (!validated_claim.has_value()) {
      return absl::OkStatus();
    }
    *manifest.mutable_claim() = *std::move(validated_claim);
    // Update the set of redacted assertions.
    for (const auto& assertion : manifest.claim().redacted_assertions()) {
      ProcessRedaction(assertion, manifest_path, tracker);
    }
    //
    // Validate assertions and populate `manifest.assertions`.
    assertion_validator_.ValidateClaimAssertions(
        uri_resolver_, manifest_state.redacted_assertions, manifest, tracker);
    // Find ingredient manifests from the validated ingredient assertions and
    // add them to the `ingredients` field of the result.
    std::vector<std::string> ingredients;
    for (const auto& assertion : manifest.assertions()) {
      if (IsIngredientAssertion(assertion)) {
        auto ingredient_manifest_path = ProcessIngredientAssertion(
            assertion, manifest_path,
            /*default_algorithm=*/
            manifest.claim().default_algorithm(), tracker);
        if (ingredient_manifest_path.has_value()) {
          auto ingredient_manifest_box =
              uri_resolver_.ResolvePath(*ingredient_manifest_path);
          if (!ingredient_manifest_box.ok() ||
              *ingredient_manifest_box == nullptr) {
            tracker.RecordFailure(
                FailureStatusCode::kIngredientManifestMissing,
                {.url =
                     absl::StrCat(kAssertionStoreLabel, kManifestLabelDelimiter,
                                  assertion.label()),
                 .explanation = absl::StrCat(
                     "Failed to resolve the ingredient manifest URI: ",
                     *ingredient_manifest_path)});
          } else {
            ManifestState& ingredient_manifest_state =
                GetOrCreateManifestState(*ingredient_manifest_path);
            ingredient_manifest_state.referencing_ingredient_assertions
                .push_back(IngredientAssertion{.assertion = &assertion,
                                               .assertion_uri = GetAssertionUri(
                                                   manifest_label, assertion)});
            // Update the set of ingredients that will be recursed into.
            if (ingredient_manifest_state.validation_state !=
                InternalValidationState::kValidated) {
              ingredients.push_back(*ingredient_manifest_path);
            }
          }
        }
      }
    }
    // Push ingredient manifests onto the stack for depth-first traversal.
    for (; !ingredients.empty(); ingredients.pop_back()) {
      const std::string& ingredient_manifest = ingredients.back();
      auto ingredient_manifest_box =
          uri_resolver_.ResolvePath(ingredient_manifest);
      if (!ingredient_manifest_box.ok() ||
          *ingredient_manifest_box == nullptr) {
        // This should never happen because we have already validated the
        // ingredient manifest URI.
        continue;
      }
      to_visit.push(*ingredient_manifest_box);
    }
  }
  if (manifest.validation().failures_size() == 0 &&
      manifest.validation().successes_size() == 0) {
    tracker.RecordFailure(FailureStatusCode::kGoogleInternalError,
                          {.explanation = "No failure or success "
                                          "status codes were recorded."});
  }
  return absl::OkStatus();
}

absl::StatusOr<std::unique_ptr<PartialValidationResultProto>>
ManifestGraph::ValidateWithRedactions(
    std::unique_ptr<PartialValidationResultProto> result) {
  return result;
}

void ManifestGraph::ProcessRedaction(absl::string_view redacted_assertion_uri,
                                     absl::string_view manifest_path,
                                     ValidationTracker& tracker) {
  // Resolve the redacted assertion URI to an absolute path before adding it
  // to the set.
  absl::StatusOr<std::string> absolute_path =
      uri_resolver_.GetAbsolutePathFromUri(redacted_assertion_uri,
                                           manifest_path);
  if (!absolute_path.ok()) {
    // Malformed URI.
    tracker.RecordFailure(FailureStatusCode::kAssertionMissing, {});
    return;
  }
  // Check if the redacted assertion URI points into the manifest whose claim
  // redacted it.
  if (absl::StartsWith(*absolute_path, manifest_path)) {
    tracker.RecordFailure(FailureStatusCode::kAssertionSelfRedacted, {});
    return;
  }
  std::optional<absl::string_view> redacted_assertion_manifest_path =
      ManifestPathFromAssertionPath(*absolute_path);
  if (!redacted_assertion_manifest_path.has_value()) {
    // Malformed path.
    tracker.RecordFailure(FailureStatusCode::kAssertionMissing, {});
    return;
  }
  GetOrCreateManifestState(*redacted_assertion_manifest_path)
      .redacted_assertions.insert(*absolute_path);
}

ManifestGraph::InternalValidationStateLock::InternalValidationStateLock(
    ManifestState* absl_nonnull manifest_state)
    : manifest_state_(*manifest_state) {
  DCHECK(manifest_state_.validation_state ==
         InternalValidationState::kUnvalidated);
  manifest_state_.validation_state = InternalValidationState::kBeingValidated;
}

ManifestGraph::InternalValidationStateLock::~InternalValidationStateLock() {
  manifest_state_.validation_state = InternalValidationState::kValidated;
}
}  // namespace credentio
