// 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.
//

#ifndef THIRD_PARTY_CREDENTIO_TESTING_TEST_VALIDATION_TRACKER_H_
#define THIRD_PARTY_CREDENTIO_TESTING_TEST_VALIDATION_TRACKER_H_

#include <string>

#include "absl/container/flat_hash_set.h"
#include "absl/strings/str_cat.h"
#include "constants/status_codes.h"
#include "gmock/gmock.h"
#include "google/protobuf/repeated_ptr_field.h"
#include "gtest/gtest.h"
#include "proto/manifest.pb.h"
#include "proto/validation_status.pb.h"
#include "validator/tracker.h"

namespace credentio {

class TestValidationTracker {
 public:
  TestValidationTracker()
      : tracker_("urn:uuid:1234", manifest_.mutable_validation()) {}

  ValidationTracker& tracker() { return tracker_; }

  absl::flat_hash_set<std::string> GetFailures() const {
    return tracker_.GetFailures();
  }

  absl::flat_hash_set<std::string> GetSuccesses() const {
    return tracker_.GetSuccesses();
  }

  absl::flat_hash_set<std::string> GetInformationals() const {
    return tracker_.GetInformationals();
  }

  google::protobuf::RepeatedPtrField<ValidationStatus> GetFailureStatuses()
      const {
    return tracker_.GetFailureStatuses();
  }

  google::protobuf::RepeatedPtrField<ValidationStatus> GetSuccessStatuses()
      const {
    return tracker_.GetSuccessStatuses();
  }

  google::protobuf::RepeatedPtrField<ValidationStatus>
  GetInformationalStatuses() const {
    return tracker_.GetInformationalStatuses();
  }

  // Dump all statuses for test debugging.
  const ValidationStatusSet& GetStatusSet() const {
    return manifest_.validation();
  }

 private:
  Manifest manifest_;
  ValidationTracker tracker_;
};

// Matcher for use with the result of `GetFailures`.
inline auto ContainsFailure(FailureStatusCode code) {
  return testing::Contains(absl::StrCat(code));
}

// Matcher for use with the result of `GetSuccesses`.
inline auto ContainsSuccess(SuccessStatusCode code) {
  return testing::Contains(absl::StrCat(code));
}

// Matcher for use with the result of `GetInformationals`.
inline auto ContainsInformational(InformationalStatusCode code) {
  return testing::Contains(absl::StrCat(code));
}

// Matcher that applies to raw status protos (results of `GetFailureStatuses`,
// `GetSuccessStatuses`, or `GetInformationalStatuses`). Note that despite
// acting on protos, this is not a proto matcher, and so cannot be combined with
// proto-matching modifiers such as `IgnoringRepeatedFieldOrdering`, etc.
template <typename StatusCode, typename ExplanationMatcher, typename UrlMatcher>
auto C2paStatusIs(StatusCode code, ExplanationMatcher explanation_matcher,
                  UrlMatcher url_matcher) {
  return testing::AllOf(
      testing::Property("code", &ValidationStatus::code,
                        testing::Eq(absl::StrCat(code))),
      testing::Property("explanation", &ValidationStatus::explanation,
                        explanation_matcher),
      testing::Property("url", &ValidationStatus::url, url_matcher));
}
template <typename StatusCode, typename ExplanationMatcher>
auto C2paStatusIs(StatusCode code, ExplanationMatcher explanation_matcher) {
  return testing::AllOf(
      testing::Property("code", &ValidationStatus::code,
                        testing::Eq(absl::StrCat(code))),
      testing::Property("explanation", &ValidationStatus::explanation,
                        explanation_matcher));
}
template <typename StatusCode>
auto C2paStatusIs(StatusCode code) {
  return testing::Property("code", &ValidationStatus::code,
                           testing::Eq(absl::StrCat(code)));
}

}  // namespace credentio

#endif  // THIRD_PARTY_CREDENTIO_TESTING_TEST_VALIDATION_TRACKER_H_
