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

#include <string>

#include "absl/container/flat_hash_set.h"
#include "absl/log/check.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "constants/labels.h"
#include "constants/status_codes.h"
#include "proto/manifest.pb.h"
#include "proto/validation_status.pb.h"

namespace credentio {
namespace {

std::string CreateUrl(absl::string_view manifest_label,
                      absl::string_view assertion_label,
                      absl::string_view url) {
  if (url.empty()) {
    if (assertion_label.empty()) {
      return absl::StrCat("self#jumbf=/c2pa/", manifest_label);
    }
    return absl::StrCat("self#jumbf=/c2pa/", manifest_label,
                        "/c2pa.assertions/", assertion_label);
  }
  if (absl::StartsWith(url, "self#jumbf=")) {
    return std::string(url);
  }
  return absl::StrCat("self#jumbf=/c2pa/", manifest_label,
                      kManifestLabelDelimiter, url);
}

// Returns true if the label is well-formed. Used in DCHECKs to help catch bugs
// where a URI or path is provided instead of a label.
bool ValidLabel(absl::string_view label) {
  return !label.empty() && !absl::StrContains(label, "/");
}

}  // namespace

ValidationTracker::ValidationTracker(Manifest* manifest)
    : manifest_label_(manifest->label()),
      status_set_(manifest->mutable_validation()),
      id_("root") {
  DCHECK(ValidLabel(manifest_label_)) << "label: " << manifest_label_;
}

ValidationTracker::ValidationTracker(absl::string_view manifest_label,
                                     ValidationStatusSet* status_set)
    : manifest_label_(manifest_label), status_set_(status_set), id_("root") {
  DCHECK(ValidLabel(manifest_label_)) << "label: " << manifest_label_;
}

ValidationTracker ValidationTracker::AssertionTracker(
    absl::string_view assertion_label) {
  ValidationTracker new_tracker = *this;
  new_tracker.assertion_label_ = assertion_label;
  return new_tracker;
}

void ValidationTracker::RecordFailure(FailureStatusCode status,
                                      RecordOptions options) {
  ValidationStatus* failure = status_set_->mutable_failures()->Add();
  failure->set_code(absl::StrCat(status));
  failure->set_url(CreateUrl(manifest_label_, assertion_label_, options.url));
  if (!options.explanation.empty()) {
    failure->set_explanation(options.explanation);
  }
}

void ValidationTracker::RecordSuccess(SuccessStatusCode status,
                                      RecordOptions options) {
  ValidationStatus* success = status_set_->mutable_successes()->Add();
  success->set_code(absl::StrCat(status));
  success->set_url(CreateUrl(manifest_label_, assertion_label_, options.url));
  if (!options.explanation.empty()) {
    success->set_explanation(options.explanation);
  }
}

void ValidationTracker::RecordInformational(InformationalStatusCode status,
                                            RecordOptions options) {
  ValidationStatus* informational =
      status_set_->mutable_informationals()->Add();
  informational->set_code(absl::StrCat(status));
  informational->set_url(
      CreateUrl(manifest_label_, assertion_label_, options.url));
  if (!options.explanation.empty()) {
    informational->set_explanation(options.explanation);
  }
}

bool ValidationTracker::HasFailures() const {
  return status_set_->failures_size() > 0;
}

absl::flat_hash_set<std::string> ValidationTracker::GetFailures() const {
  absl::flat_hash_set<std::string> failures;
  for (const auto& failure_status : status_set_->failures()) {
    failures.insert(std::string(failure_status.code()));
  }
  return failures;
}

absl::flat_hash_set<std::string> ValidationTracker::GetSuccesses() const {
  absl::flat_hash_set<std::string> successes;
  for (const auto& success_status : status_set_->successes()) {
    successes.insert(std::string(success_status.code()));
  }
  return successes;
}

absl::flat_hash_set<std::string> ValidationTracker::GetInformationals() const {
  absl::flat_hash_set<std::string> informational;
  for (const auto& informational_status : status_set_->informationals()) {
    informational.insert(std::string(informational_status.code()));
  }
  return informational;
}

void ValidationTracker::MergeStatuses(const ValidationStatusSet& statuses) {
  for (const auto& failure : statuses.failures()) {
    ValidationStatus* f = status_set_->mutable_failures()->Add();
    *f = failure;
    f->set_url(CreateUrl(manifest_label_, assertion_label_, failure.url()));
  }
  for (const auto& success : statuses.successes()) {
    ValidationStatus* s = status_set_->mutable_successes()->Add();
    *s = success;
    s->set_url(CreateUrl(manifest_label_, assertion_label_, success.url()));
  }
  for (const auto& info : statuses.informationals()) {
    ValidationStatus* i = status_set_->mutable_informationals()->Add();
    *i = info;
    i->set_url(CreateUrl(manifest_label_, assertion_label_, info.url()));
  }
}

}  // namespace credentio
