// 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_FAKE_CLAIM_VALIDATOR_H_
#define THIRD_PARTY_CREDENTIO_TESTING_FAKE_CLAIM_VALIDATOR_H_

#include <optional>
#include <string>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "claim/validator.h"
#include "constants/status_codes.h"
#include "jumbf/box.h"
#include "validator/tracker.h"

namespace credentio {

class FakeClaimValidator : public ClaimValidator {
 public:
  // Constructs a `FakeClaimValidator` with a set of failure, informational and
  // success codes to be recorded for every `Validate` call of the fake.
  FakeClaimValidator(absl::Span<const FailureStatusCode> failures,
                     absl::Span<const InformationalStatusCode> informationals,
                     absl::Span<const SuccessStatusCode> successes)
      : common_failures_(failures.begin(), failures.end()),
        common_informationals_(informationals.begin(), informationals.end()),
        common_successes_(successes.begin(), successes.end()) {}

  std::optional<Claim> Validate(
      const jumbf::SuperBox& manifest,
      ValidationTracker& validation_tracker) const override {
    // Record failures and successes.
    for (const auto& failure : common_failures_) {
      validation_tracker.RecordFailure(failure, {});
    }
    for (const auto& informational : common_informationals_) {
      validation_tracker.RecordInformational(informational, {});
    }
    for (const auto& success : common_successes_) {
      validation_tracker.RecordSuccess(success, {});
    }
    absl::string_view label = manifest.description.label.value_or("");
    if (auto it = results_.find(label); it != results_.end()) {
      if (auto failures = claim_failures_.find(label);
          failures != claim_failures_.end()) {
        for (const auto& failure : failures->second) {
          validation_tracker.RecordFailure(failure, {});
        }
      }
      if (auto informationals = claim_informationals_.find(label);
          informationals != claim_informationals_.end()) {
        for (const auto& informational : informationals->second) {
          validation_tracker.RecordInformational(informational, {});
        }
      }
      if (auto successes = claim_successes_.find(label);
          successes != claim_successes_.end()) {
        for (const auto& success : successes->second) {
          validation_tracker.RecordSuccess(success, {});
        }
      }
      return it->second;
    }
    return std::nullopt;
  }

  void SetClaimResult(absl::string_view label, const Claim& claim) {
    results_[label] = claim;
  }

  // Specifies a list of failure codes that will be recorded when the claim with
  // label provided in the parameter `label` is validated.
  void SetClaimFailures(absl::string_view label,
                        absl::Span<const FailureStatusCode> failures) {
    claim_failures_[label] =
        std::vector<FailureStatusCode>(failures.begin(), failures.end());
  }

  // Specifies a list of informational codes that will be recorded when the
  // claim with label provided in the parameter `label` is validated.
  void SetClaimInformationals(
      absl::string_view label,
      absl::Span<const InformationalStatusCode> informationals) {
    claim_informationals_[label] = std::vector<InformationalStatusCode>(
        informationals.begin(), informationals.end());
  }

  // Specifies a list of success codes that will be recorded when the claim with
  // label provided in the parameter `label` is validated.
  void SetClaimSuccesses(absl::string_view label,
                         absl::Span<const SuccessStatusCode> failures) {
    claim_successes_[label] =
        std::vector<SuccessStatusCode>(failures.begin(), failures.end());
  }

 private:
  absl::flat_hash_map<std::string, Claim> results_;
  absl::flat_hash_map<std::string, std::vector<FailureStatusCode>>
      claim_failures_;
  absl::flat_hash_map<std::string, std::vector<InformationalStatusCode>>
      claim_informationals_;
  absl::flat_hash_map<std::string, std::vector<SuccessStatusCode>>
      claim_successes_;
  std::vector<FailureStatusCode> common_failures_;
  std::vector<InformationalStatusCode> common_informationals_;
  std::vector<SuccessStatusCode> common_successes_;
};

}  // namespace credentio

#endif  // THIRD_PARTY_CREDENTIO_TESTING_FAKE_CLAIM_VALIDATOR_H_
