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

#include <memory>
#include <optional>
#include <string>
#include <utility>

#include "absl/base/nullability.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "bindings/validator.h"
#include "formats/core_registry.h"
#include "formats/extractor.h"
#include "formats/format.h"
#include "formats/registry.h"
#include "proto/validation_result.pb.h"
#include "riegeli/bytes/reader.h"
#include "validator/manifest_store_validator.h"
#include "validator/manifest_store_validator_impl.h"
#include "validator/result.h"
#include "validator/validation_result_internal.h"
#include "validator/validator_metrics.h"
#include "validator/validator_options.h"

namespace credentio {
namespace {

absl::StatusOr<std::unique_ptr<ValidationResult>> FinalizePartialResult(
    std::unique_ptr<PartialValidationResultProto> partial_validation_result,
    riegeli::Reader& input, const Format& format,
    std::optional<absl::string_view> media_type,
    ValidatorMetrics* absl_nullable metrics, std::string manifest_store_bytes) {
  std::unique_ptr<ValidationResultProto> validation_result;
  if (partial_validation_result->has_hard_binding_uri()) {
    if (!input.Seek(0)) {
      return absl::InternalError(
          "Failed to seek to the beginning of the input.");
    }
    ABSL_ASSIGN_OR_RETURN(
        validation_result,
        ContentBindingValidator().Validate(
            input, format, std::move(partial_validation_result)));
  } else {
    ABSL_ASSIGN_OR_RETURN(
        validation_result,
        MakeFullValidationResult(std::move(partial_validation_result)));
  }
  if (media_type.has_value()) {
    validation_result->set_media_type(*media_type);
  }

  if (metrics != nullptr) {
    metrics->RecordValidationResult(
        media_type.has_value() ? *media_type : format.mime_types()[0],
        *validation_result);
  }

  return std::make_unique<ValidationResult>(std::move(validation_result),
                                            std::move(manifest_store_bytes));
}

ValidatorOptions OptionsWithoutMetrics(ValidatorOptions options) {
  options.metrics = nullptr;
  return options;
}

}  // namespace

absl::StatusOr<std::unique_ptr<ValidationResult>> AssetValidatorImpl::Validate(
    riegeli::Reader& input, std::optional<absl::string_view> media_type) const {
  if (!input.SupportsSize() || !input.SupportsRandomAccess()) {
    return absl::InvalidArgumentError(
        "The input does not support backwards seeks, it is required.");
  }

  if (!input.Seek(0)) {
    return absl::InternalError("Failed to seek to the beginning of the input.");
  }
  const Format* format;
  if (media_type.has_value()) {
    ABSL_ASSIGN_OR_RETURN(format,
                          format_registry_->GetFormat(*media_type, input));
  } else {
    ABSL_ASSIGN_OR_RETURN(format, format_registry_->GetFormat(input));
  }

  if (!input.Seek(0)) {
    return absl::InternalError("Failed to seek to the beginning of the input.");
  }
  ABSL_ASSIGN_OR_RETURN(auto manifest_store,
                        format->extractor()->ExtractManifestStore(input));

  absl::string_view manifest_str = manifest_store;

  ABSL_ASSIGN_OR_RETURN(
      std::unique_ptr<PartialValidationResultProto> partial_validation_result,
      manifest_store_validator_->Validate(manifest_str));

  return FinalizePartialResult(std::move(partial_validation_result), input,
                               *format, media_type, options_.metrics,
                               std::move(manifest_store));
}

AssetValidatorImpl::AssetValidatorImpl(ValidatorOptions options)
    : options_(options),
      format_registry_(CreateCoreFormatRegistry()),
      manifest_store_validator_(std::make_unique<ManifestStoreValidatorImpl>(
          OptionsWithoutMetrics(std::move(options)))) {}

}  // namespace credentio
