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

#include <memory>
#include <optional>
#include <utility>
#include <vector>

#include "absl/base/nullability.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "assertion/validator.h"
#include "claim/validator.h"
#include "constants/labels.h"
#include "constants/status_codes.h"
#include "cose/verifier.h"
#include "crypto/default/hasher.h"
#include "crypto/hash.h"
#include "jumbf/box.h"
#include "jumbf/parse.h"
#include "jumbf/uri.h"
#include "proto/assertion.pb.h"
#include "proto/ingredient_assertion.pb.h"
#include "proto/validation_result.pb.h"
#include "utils/dual_status_tracker.h"
#include "uuid/uuid.h"
#include "validator/graph.h"
#include "validator/result.h"
#include "validator/validator_metrics.h"
#include "validator/validator_options.h"

namespace credentio {

namespace {

using ::jumbf::SuperBox;

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

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

absl::StatusOr<std::unique_ptr<PartialValidationResultProto>>
ValidateManifestStore(absl::string_view manifest_store,
                      const ValidatorOptions& options,
                      const AssertionValidator& assertion_validator,
                      const ClaimValidator& claim_validator,
                      const HashCheckerFactory& hash_checker_factory,
                      ValidatorMetrics* absl_nullable metrics) {
  // Obtain the superbox proto from the serialized manifest.
  // Any error from parsing the JUMBF boxes is considered "No Manifest Found"
  // A recursion limit of 3 should suffice, but we'll allow for a bit more in
  // case of future changes.
  absl::StatusOr<SuperBox> ms_superbox_or =
      jumbf::ConsumeSuperBox(&manifest_store, /*recursion_limit=*/9);
  if (!ms_superbox_or.ok()) {
    return absl::NotFoundError(ms_superbox_or.status().message());
  }
  SuperBox ms_superbox = *std::move(ms_superbox_or);

  auto uri_resolver = jumbf::UriResolver::WithSingleRootChild(&ms_superbox);
  if (!IsManifestStore(ms_superbox)) {
    return absl::NotFoundError(
        "JUMBF SuperBox does not contain a manifest store");
  }

  // Fetch the active manifest from the manifest store.
  // The last C2PA Manifest superbox in the C2PA Manifest Store superbox shall
  // be considered the active manifest.
  std::optional<SuperBox> active_manifest;
  for (auto it = ms_superbox.contents.rbegin();
       it != ms_superbox.contents.rend(); ++it) {
    if (it->Holds<SuperBox>() && IsManifest(it->Get<SuperBox>())) {
      active_manifest = it->Get<SuperBox>();
      break;
    }
  }
  if (!active_manifest.has_value()) {
    return absl::NotFoundError("No active manifest found in manifest store");
  }

  ManifestGraph graph(&*active_manifest, &uri_resolver, &assertion_validator,
                      &claim_validator, &hash_checker_factory, &options);
  absl::StatusOr<std::unique_ptr<PartialValidationResultProto>> result =
      graph.Validate();

  if (!result.ok()) {
    // Don't suppress the internal error.
    if (result.status().code() == absl::StatusCode::kInternal) {
      return result;
    }
    return absl::NotFoundError(result.status().message());
  }

  return result;
}

}  // namespace

ManifestStoreValidatorImpl::ManifestStoreValidatorImpl(ValidatorOptions options)
    : cose_verifier_(CreateCoseVerifier({
          .crypto_read_handler = std::move(options.crypto_read_handler),
          .clock = options.clock,
      })),
      options_(std::move(options)),
      claim_validator_(cose_verifier_.get()),
      assertion_validator_({.skip_actions_assertion_validation_for_test =
                                options_.accept_legacy_manifest_for_test}),
      hash_checker_factory_(DefaultHashCheckerFactory()) {}

absl::StatusOr<std::unique_ptr<PartialValidationResultProto>>
ManifestStoreValidatorImpl::Validate(absl::string_view manifest_store) const {
  ABSL_ASSIGN_OR_RETURN(
      auto partial_validation_result,
      ValidateManifestStore(manifest_store, options_, assertion_validator_,
                            claim_validator_, hash_checker_factory_,
                            options_.metrics));

  if (options_.spec_version >= SpecVersion::kC2pa_2_4) {
    partial_validation_result->set_spec_version(
        SpecVersionToString(options_.spec_version));
    if (!options_.trust_list_uri.empty()) {
      partial_validation_result->set_trust_list_uri(options_.trust_list_uri);
    }
  }

  if (options_.metrics != nullptr) {
    options_.metrics->RecordPartialValidationResult(*partial_validation_result);
  }

  if (partial_validation_result->has_hard_binding_uri()) {
    // The manifest store indicates that a hard binding assertion is present.
    const Assertion* absl_nullable assertion =
        GetAssertion(partial_validation_result.get(),
                     partial_validation_result->hard_binding_uri());
    if (assertion == nullptr) {
      // The assertion cannot be found, this means it was redacted for being a
      // deprecated assertion.
      ABSL_ASSIGN_OR_RETURN(auto tracker,
                            DualStatusTracker::FromPartialValidationResult(
                                partial_validation_result.get()));
      tracker->RecordFailure(
          FailureStatusCode::kClaimHardBindingsMissing,
          {.explanation = "The active hard binding assertion was deprecated."});
      partial_validation_result->clear_hard_binding_uri();
    }
  }

  return partial_validation_result;
}

}  // namespace credentio
