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

#include <string>

#include "absl/container/flat_hash_set.h"
#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/strings/str_cat.h"
#include "constants/status_codes.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "proto/assertion.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 "testing/proto_test_utils.h"

namespace credentio {
namespace {

using ::absl_testing::StatusIs;
using ::credentio_testing::EqualsProto;
using ::credentio_testing::ParseTextProtoOrDie;
using ::testing::ElementsAre;
using ::testing::IsEmpty;
using ::testing::TestParamInfo;
using ::testing::TestWithParam;

struct TrackerTestCase {
  std::string test_name;
  credentio::SuccessStatusCode success_code;
  credentio::FailureStatusCode failure_code;
  std::string expected_success_codes;
  std::string expected_failure_codes;
};
using TrackerTest = TestWithParam<TrackerTestCase>;

absl::flat_hash_set<std::string> GetFailures(ValidationStatusSet validation) {
  absl::flat_hash_set<std::string> failures;
  for (const auto& failure : validation.failures()) {
    failures.insert(std::string(failure.code()));
  }
  return failures;
}

absl::flat_hash_set<std::string> GetSuccesses(ValidationStatusSet validation) {
  absl::flat_hash_set<std::string> successes;
  for (const auto& success : validation.successes()) {
    successes.insert(std::string(success.code()));
  }
  return successes;
}

TEST(DualStatusTrackerTest, ManifestNotFound) {
  auto result = ParseTextProtoOrDie<PartialValidationResultProto>(R"pb(
    active_manifest { label: "a" }
    hard_binding_uri: "self#jumbf=/c2pa/1234/c2pa.assertions/c2pa.hash.boxes"
  )pb");
  EXPECT_THAT(DualStatusTracker::FromPartialValidationResult(&result),
              StatusIs(absl::StatusCode::kInvalidArgument));
}

TEST(DualStatusTrackerTest, NoHardBindingUri) {
  auto result = ParseTextProtoOrDie<PartialValidationResultProto>(R"pb(
    active_manifest { label: "a" }
  )pb");
  EXPECT_THAT(DualStatusTracker::FromPartialValidationResult(&result),
              StatusIs(absl::StatusCode::kInvalidArgument));
}

TEST(DualStatusTrackerTest, WritesStatusCodesToSingleTracker) {
  auto result = ParseTextProtoOrDie<PartialValidationResultProto>(R"pb(
    active_manifest { label: "a" }
    hard_binding_uri: "self#jumbf=/c2pa/a/c2pa.assertions/c2pa.hash.boxes"
  )pb");

  auto tracker = DualStatusTracker::FromPartialValidationResult(&result);
  ASSERT_TRUE(tracker.ok());
  const auto& active = result.active_manifest();

  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());

  (*tracker)->RecordSuccess(SuccessStatusCode::kAssertionBmffHashMatch, {});
  EXPECT_THAT(GetSuccesses(active.validation()),
              ElementsAre("assertion.bmffHash.match"));
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());

  (*tracker)->RecordFailure(FailureStatusCode::kAssertionBmffHashMismatch, {});
  EXPECT_THAT(GetSuccesses(active.validation()),
              ElementsAre("assertion.bmffHash.match"));
  EXPECT_THAT(GetFailures(active.validation()),
              ElementsAre("assertion.bmffHash.mismatch"));
}

TEST(DualStatusTrackerTest, WritesDifferentSuccessCode) {
  auto result = ParseTextProtoOrDie<PartialValidationResultProto>(R"pb(
    active_manifest { label: "a" }
    ingredient_manifests { label: "i" }
    hard_binding_uri: "self#jumbf=/c2pa/i/c2pa.assertions/c2pa.hash.boxes"
  )pb");

  auto tracker = DualStatusTracker::FromPartialValidationResult(&result);
  ASSERT_TRUE(tracker.ok());

  const auto& active = result.active_manifest();
  const auto& ingredient = result.ingredient_manifests(0);

  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());
  EXPECT_THAT(GetSuccesses(ingredient.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(ingredient.validation()), IsEmpty());

  (*tracker)->RecordSuccess(SuccessStatusCode::kAssertionBmffHashMatch, {});
  EXPECT_THAT(GetSuccesses(active.validation()),
              ElementsAre("com.google.assertion.bmffHash.match"));
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());
  EXPECT_THAT(GetSuccesses(ingredient.validation()),
              ElementsAre("assertion.bmffHash.match"));
  EXPECT_THAT(GetFailures(ingredient.validation()), IsEmpty());
}

TEST(DualStatusTrackerTest, WritesSameFailureCode) {
  auto result = ParseTextProtoOrDie<PartialValidationResultProto>(R"pb(
    active_manifest { label: "a" }
    ingredient_manifests { label: "i" }
    hard_binding_uri: "self#jumbf=/c2pa/i/c2pa.assertions/c2pa.hash.boxes"
  )pb");

  auto tracker = DualStatusTracker::FromPartialValidationResult(&result);
  ASSERT_TRUE(tracker.ok());

  const auto& active = result.active_manifest();
  const auto& ingredient = result.ingredient_manifests(0);

  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());
  EXPECT_THAT(GetSuccesses(ingredient.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(ingredient.validation()), IsEmpty());

  (*tracker)->RecordFailure(FailureStatusCode::kClaimCborInvalid, {});
  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()),
              ElementsAre("claim.cbor.invalid"));
  EXPECT_THAT(GetSuccesses(ingredient.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(ingredient.validation()),
              ElementsAre("claim.cbor.invalid"));
}

TEST(DualStatusTrackerTest, WritesDifferentFailureCode) {
  auto result = ParseTextProtoOrDie<PartialValidationResultProto>(R"pb(
    active_manifest { label: "a" }
    ingredient_manifests { label: "i" }
    hard_binding_uri: "self#jumbf=/c2pa/i/c2pa.assertions/c2pa.hash.boxes"
  )pb");

  auto tracker = DualStatusTracker::FromPartialValidationResult(&result);
  ASSERT_TRUE(tracker.ok());

  const auto& active = result.active_manifest();
  const auto& ingredient = result.ingredient_manifests(0);

  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());
  EXPECT_THAT(GetSuccesses(ingredient.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(ingredient.validation()), IsEmpty());

  (*tracker)->RecordFailure(FailureStatusCode::kAssertionBmffHashMismatch, {});
  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()),
              ElementsAre("com.google.assertion.bmffHash.mismatch"));
  EXPECT_THAT(GetSuccesses(ingredient.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(ingredient.validation()),
              ElementsAre("assertion.bmffHash.mismatch"));
}

TEST(DualStatusTrackerTest, StatusUrls) {
  auto result = ParseTextProtoOrDie<PartialValidationResultProto>(R"pb(
    active_manifest { label: "a" }
    ingredient_manifests { label: "i" }
    hard_binding_uri: "self#jumbf=/c2pa/i/c2pa.assertions/c2pa.hash.boxes"
  )pb");

  auto tracker = DualStatusTracker::FromPartialValidationResult(&result);
  ASSERT_TRUE(tracker.ok());

  const auto& active = result.active_manifest();
  const auto& ingredient = result.ingredient_manifests(0);

  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());
  EXPECT_THAT(GetSuccesses(ingredient.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(ingredient.validation()), IsEmpty());

  (*tracker)->RecordFailure(FailureStatusCode::kAssertionBmffHashMismatch, {});
  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()),
              ElementsAre("com.google.assertion.bmffHash.mismatch"));
  EXPECT_THAT(GetSuccesses(ingredient.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(ingredient.validation()),
              ElementsAre("assertion.bmffHash.mismatch"));

  EXPECT_THAT(active.validation(),
              EqualsProto(ParseTextProtoOrDie<ValidationStatusSet>(
                  R"pb(
                    failures {
                      code: "com.google.assertion.bmffHash.mismatch"
                      url: "self#jumbf=/c2pa/a"
                    }
                  )pb")));
  EXPECT_THAT(ingredient.validation(),
              EqualsProto(ParseTextProtoOrDie<ValidationStatusSet>(
                  R"pb(
                    failures {
                      code: "assertion.bmffHash.mismatch"
                      url: "self#jumbf=/c2pa/i"
                    }
                  )pb")));
}

TEST(DualStatusTrackerTest, WritesUnexpectedSuccessCode) {
  auto result = ParseTextProtoOrDie<PartialValidationResultProto>(R"pb(
    active_manifest { label: "a" }
    hard_binding_uri: "self#jumbf=/c2pa/a/c2pa.assertions/c2pa.hash.boxes"
  )pb");

  auto tracker = DualStatusTracker::FromPartialValidationResult(&result);
  ASSERT_TRUE(tracker.ok());
  const auto& active = result.active_manifest();

  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());

  (*tracker)->RecordSuccess(SuccessStatusCode::kClaimSignatureValidated, {});
  EXPECT_THAT(GetSuccesses(active.validation()),
              ElementsAre("claimSignature.validated"));
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());
}

// Parametrized tests for success and failure codes.
TEST_P(TrackerTest, WritesStatusCodesToSingleTrackerAssertionsInActive) {
  const TrackerTestCase& test_case = GetParam();

  PartialValidationResultProto result;
  result.mutable_active_manifest()->set_label("active_manifest");
  result.mutable_active_manifest()->add_assertions()->set_label("assertion1");
  result.set_hard_binding_uri(
      "self#jumbf=/c2pa/active_manifest/c2pa.assertions/assertion1");

  auto tracker = DualStatusTracker::FromPartialValidationResult(&result);
  ASSERT_TRUE(tracker.ok());
  const auto& active = result.active_manifest();

  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());

  (*tracker)->RecordSuccess(test_case.success_code, {});
  EXPECT_THAT(GetSuccesses(active.validation()),
              ElementsAre(test_case.expected_success_codes));
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());

  (*tracker)->RecordFailure(test_case.failure_code, {});
  EXPECT_THAT(GetSuccesses(active.validation()),
              ElementsAre(test_case.expected_success_codes));
  EXPECT_THAT(GetFailures(active.validation()),
              ElementsAre(test_case.expected_failure_codes));
}

TEST_P(TrackerTest, WritesStatusCodesToSingleTrackerAssertionsInIngredient) {
  const TrackerTestCase& test_case = GetParam();

  PartialValidationResultProto result;
  result.mutable_active_manifest()->set_label("active_manifest");
  result.add_ingredient_manifests()->set_label("ingredient_manifest");
  result.mutable_ingredient_manifests(0)->add_assertions()->set_label(
      "assertion1");
  result.set_hard_binding_uri(
      "self#jumbf=/c2pa/ingredient_manifest/c2pa.assertions/assertion1");

  auto tracker = DualStatusTracker::FromPartialValidationResult(&result);
  ASSERT_TRUE(tracker.ok());
  const auto& active = result.active_manifest();

  // It is expected to have "com.google." prefixes here.
  std::string expected_success_codes =
      absl::StrCat("com.google.", test_case.expected_success_codes);
  std::string expected_failure_codes =
      absl::StrCat("com.google.", test_case.expected_failure_codes);
  EXPECT_THAT(GetSuccesses(active.validation()), IsEmpty());
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());

  (*tracker)->RecordSuccess(test_case.success_code, {});
  EXPECT_THAT(GetSuccesses(active.validation()),
              ElementsAre(expected_success_codes));
  EXPECT_THAT(GetFailures(active.validation()), IsEmpty());

  (*tracker)->RecordFailure(test_case.failure_code, {});
  EXPECT_THAT(GetSuccesses(active.validation()),
              ElementsAre(expected_success_codes));
  EXPECT_THAT(GetFailures(active.validation()),
              ElementsAre(expected_failure_codes));
}

INSTANTIATE_TEST_SUITE_P(
    TrackerTest, TrackerTest,
    testing::ValuesIn<TrackerTestCase>({
        {"BmffWithMismatch", SuccessStatusCode::kAssertionBmffHashMatch,
         FailureStatusCode::kAssertionBmffHashMismatch,
         "assertion.bmffHash.match", "assertion.bmffHash.mismatch"},
        {"BmffWithMalformed", SuccessStatusCode::kAssertionBmffHashMatch,
         FailureStatusCode::kAssertionBmffHashMalformed,
         "assertion.bmffHash.match", "assertion.bmffHash.malformed"},
        {"BoxesWithMismatch", SuccessStatusCode::kAssertionBoxesHashMatch,
         FailureStatusCode::kAssertionBoxesHashMismatch,
         "assertion.boxesHash.match", "assertion.boxesHash.mismatch"},
        {"BoxesWithUnknown", SuccessStatusCode::kAssertionBoxesHashMatch,
         FailureStatusCode::kAssertionBoxesHashUnknownBox,
         "assertion.boxesHash.match", "assertion.boxesHash.unknownBox"},
        {"BoxesWithMalformed", SuccessStatusCode::kAssertionBoxesHashMatch,
         FailureStatusCode::kAssertionBoxesHashMalformed,
         "assertion.boxesHash.match", "assertion.boxesHash.malformed"},
        {"DataWithMismatch", SuccessStatusCode::kAssertionDataHashMatch,
         FailureStatusCode::kAssertionDataHashMismatch,
         "assertion.dataHash.match", "assertion.dataHash.mismatch"},
        {"DataWithMalformed", SuccessStatusCode::kAssertionDataHashMatch,
         FailureStatusCode::kAssertionDataHashMalformed,
         "assertion.dataHash.match", "assertion.dataHash.malformed"},
        {"MultiAssetWithMalformed",
         SuccessStatusCode::kAssertionMultiAssetHashMatch,
         FailureStatusCode::kAssertionMultiAssetHashMalformed,
         "assertion.multiAssetHash.match",
         "assertion.multiAssetHash.malformed"},
        {"MultiAssetWithMismatch",
         SuccessStatusCode::kAssertionMultiAssetHashMatch,
         FailureStatusCode::kAssertionMultiAssetHashMismatch,
         "assertion.multiAssetHash.match", "assertion.multiAssetHash.mismatch"},
        {"MultiAssetWithMissingPart",
         SuccessStatusCode::kAssertionMultiAssetHashMatch,
         FailureStatusCode::kAssertionMultiAssetHashMissingPart,
         "assertion.multiAssetHash.match",
         "assertion.multiAssetHash.missingPart"},
    }),
    [](const TestParamInfo<TrackerTest::ParamType>& info) {
      return info.param.test_name;
    });

}  // namespace
}  // namespace credentio
