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

#include <utility>

#include "absl/container/flat_hash_set.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "proto/ingredient_assertion.pb.h"
#include "proto/validation_status.pb.h"
#include "testing/proto_test_utils.h"

namespace credentio {
namespace {

using ::credentio_testing::EqualsProto;
using ::credentio_testing::ParseTextProtoOrDie;

TEST(PropagateFailuresFromIngredientAssertionTest, V3IngredientWithFailures) {
  auto assertion = ParseTextProtoOrDie<IngredientAssertionV3>(R"pb(
    validation_results {
      active_manifest {
        failures {
          code: "assertion.dataHash.mismatch"
          url: "self#jumbf=/c2pa/urn:c2pa:b5689eb7-36d2-5fc5-2ce8-495a0aebfa1c/c2pa.assertions/c2pa.hash.data"
        }
        failures {
          code: "assertion.missing"
          url: "self#jumbf=/c2pa/urn:c2pa:b5689eb7-36d2-5fc5-2ce8-495a0aebfa1c/c2pa.assertions/c2pa.actions"
          explanation: "can't find assertion"
        }
        successes {
          code: "timeStamp.validated"
          url: "self#jumbf=/c2pa/urn:c2pa:b5689eb7-36d2-5fc5-2ce8-495a0aebfa1c/c2pa.signature"
        }
      }
    }
  )pb");
  ValidationStatusSet validation;
  absl::flat_hash_set<std::pair<absl::string_view, absl::string_view>>
      existing_failures;
  PropagateFailuresFromIngredientAssertion(assertion, validation,
                                           existing_failures);
  EXPECT_THAT(
      validation, EqualsProto(ParseTextProtoOrDie<ValidationStatusSet>(R"pb(
        failures {
          code: "assertion.dataHash.mismatch"
          url: "self#jumbf=/c2pa/urn:c2pa:b5689eb7-36d2-5fc5-2ce8-495a0aebfa1c/c2pa.assertions/c2pa.hash.data"
          explanation: "from original validator"
        }
        failures {
          code: "assertion.missing"
          url: "self#jumbf=/c2pa/urn:c2pa:b5689eb7-36d2-5fc5-2ce8-495a0aebfa1c/c2pa.assertions/c2pa.actions"
          explanation: "from original validator: can't find assertion"
        }
      )pb")));
}

TEST(PropagateFailuresFromIngredientAssertionTest, DedupFailures) {
  auto assertion = ParseTextProtoOrDie<IngredientAssertionV3>(R"pb(
    validation_results {
      active_manifest {
        failures {
          code: "assertion.dataHash.mismatch"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.hash.data"
          explanation: "explanation 1"
        }
        # duplicated in ValidationStatusSet below, will be dropped
        failures {
          code: "assertion.missing"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.actions.v2"
          explanation: "explanation 2"
        }
        failures {
          code: "assertion.missing"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.metadata"
          explanation: "explanation 3"
        }
        successes {
          code: "timeStamp.validated"
          url: "self#jumbf=/c2pa/urn:c2pa:b5689eb7-36d2-5fc5-2ce8-495a0aebfa1c/c2pa.signature"
        }
      }
    }
  )pb");
  auto validation = ParseTextProtoOrDie<ValidationStatusSet>(R"pb(
    failures {
      code: "assertion.dataHash.malformed"
      url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.hash.data"
      explanation: "explanation 4"
    }
    failures {
      code: "assertion.missing"
      url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.actions.v2"
      explanation: "explanation 5"
    }
    failures {
      code: "assertion.missing"
      url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.metadata__1"
      explanation: "explanation 6"
    }
  )pb");
  absl::flat_hash_set<std::pair<absl::string_view, absl::string_view>>
      existing_failures;
  for (const auto& failure : validation.failures()) {
    existing_failures.insert(std::make_pair(failure.code(), failure.url()));
  }
  PropagateFailuresFromIngredientAssertion(assertion, validation,
                                           existing_failures);
  EXPECT_THAT(
      validation, EqualsProto(ParseTextProtoOrDie<ValidationStatusSet>(R"pb(
        failures {
          code: "assertion.dataHash.malformed"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.hash.data"
          explanation: "explanation 4"
        }
        failures {
          code: "assertion.missing"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.actions.v2"
          explanation: "explanation 5"
        }
        failures {
          code: "assertion.missing"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.metadata__1"
          explanation: "explanation 6"
        }
        failures {
          code: "assertion.dataHash.mismatch"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.hash.data"
          explanation: "from original validator: explanation 1"
        }
        failures {
          code: "assertion.missing"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.metadata"
          explanation: "from original validator: explanation 3"
        }
      )pb")));
}

TEST(PropagateFailuresFromIngredientAssertionTest, RepeatedCallsDedup) {
  auto assertion1 = ParseTextProtoOrDie<IngredientAssertionV3>(R"pb(
    validation_results {
      active_manifest {
        failures {
          code: "assertion.dataHash.mismatch"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.hash.data"
          explanation: "explanation 1"
        }
      }
    }
  )pb");
  auto assertion2 = ParseTextProtoOrDie<IngredientAssertionV3>(R"pb(
    validation_results {
      active_manifest {
        failures {
          code: "assertion.dataHash.mismatch"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.hash.data"
          explanation: "explanation 2"
        }
      }
    }
  )pb");
  ValidationStatusSet validation;
  absl::flat_hash_set<std::pair<absl::string_view, absl::string_view>>
      existing_failures;
  PropagateFailuresFromIngredientAssertion(assertion1, validation,
                                           existing_failures);
  PropagateFailuresFromIngredientAssertion(assertion2, validation,
                                           existing_failures);
  EXPECT_EQ(validation.failures_size(), 1);
  EXPECT_EQ(validation.failures(0).explanation(),
            "from original validator: explanation 1");
}

TEST(PropagateFailuresFromIngredientAssertionTest, MaxFailuresLimit) {
  ValidationStatusSet validation;
  absl::flat_hash_set<std::pair<absl::string_view, absl::string_view>>
      existing_failures;
  for (int i = 0; i < 10000; ++i) {
    auto* failure = validation.add_failures();
    failure->set_code(absl::StrCat("code_", i));
    failure->set_url(absl::StrCat("url_", i));
    existing_failures.insert(std::make_pair(failure->code(), failure->url()));
  }
  auto assertion = ParseTextProtoOrDie<IngredientAssertionV3>(R"pb(
    validation_results {
      active_manifest {
        failures {
          code: "new.failure"
          url: "self#jumbf=/c2pa/manifest1/c2pa.assertions/c2pa.hash.data"
        }
      }
    }
  )pb");
  PropagateFailuresFromIngredientAssertion(assertion, validation,
                                           existing_failures);
  EXPECT_EQ(validation.failures_size(), 10000);
}

}  // namespace
}  // namespace credentio
