// 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 <fstream>
#include <iostream>
#include <memory>
#include <optional>
#include <sstream>
#include <string>
#include <utility>

#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/flags/usage.h"
#include "absl/log/initialize.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "crypto/crypto_read_handler.h"
#include "crypto/default/default_crypto_read_handler.h"
#include "formats/core_registry.h"
#include "google/protobuf/text_format.h"
#include "nlohmann/json_fwd.hpp"
#include "riegeli/bytes/cfile_reader.h"
#include "riegeli/bytes/reader.h"
#include "utils/crjson.h"
#include "utils/media_type.h"
#include "validator/asset_validator_impl.h"
#include "validator/result.h"
#include "validator/validator_options.h"

ABSL_FLAG(std::string, asset, "",
          "Path to the asset file to validate (Required).");
ABSL_FLAG(
    std::string, claim_signer_trust, "",
    "Path to PEM file containing claim signer trust anchors (for C2PA "
    "2.2+ strict EKU compliance). If not provided, then the validator will "
    "default to skip trust checks.");
ABSL_FLAG(std::string, tsa_trust, "",
          "Path to PEM file containing TSA trust anchors. If not provided, "
          "then the validator will default to skip TSA trust checks.");
ABSL_FLAG(std::string, output_format, "crjson",
          "The format to output the validation results in. [txtpb, crjson] "
          "(Default: crjson)");

namespace {

absl::StatusOr<std::string> GetContents(absl::string_view file_path) {
  std::ifstream f(std::string(file_path), std::ios::binary);
  if (!f.is_open()) {
    return absl::NotFoundError(
        absl::StrCat("Failed to open file: ", file_path));
  }
  std::stringstream buffer;
  buffer << f.rdbuf();
  return buffer.str();
}

absl::Status PrintResultInTxtpb(const credentio::ValidationResult& result) {
  std::string text_format;
  if (google::protobuf::TextFormat::PrintToString(result.proto(),
                                                  &text_format)) {
    std::cout << "Validation Result:\n" << text_format << "\n";
  } else {
    return absl::InternalError("Failed to convert result proto to text format");
  }
  return absl::OkStatus();
}

absl::Status PrintResultInCrJson(
    riegeli::Reader& reader, std::optional<absl::string_view> media_type_opt,
    const credentio::ValidationResult& result) {
  if (!media_type_opt.has_value()) {
    return absl::InvalidArgumentError("Media type is required");
  }

  auto registry = credentio::CreateCoreFormatRegistry();
  auto format = registry->GetFormat(*media_type_opt);
  if (!format.ok()) {
    return format.status();
  }
  if (!reader.Seek(0) || reader.pos() != 0) {
    return absl::DataLossError("Failed to seek to start of reader");
  }
  auto manifest_store = (*format)->extractor()->ExtractManifestStore(reader);
  if (!manifest_store.ok()) {
    return manifest_store.status();
  }

  absl::StatusOr<nlohmann::json> crjson =
      credentio::ConvertToCrJson(*manifest_store, result.proto());
  if (!crjson.ok()) {
    return crjson.status();
  }
  std::cout << "Validation Result (crjson):\n" << crjson->dump(2) << "\n";
  return absl::OkStatus();
}

}  // namespace

int main(int argc, char* argv[]) {
  absl::SetProgramUsageMessage(
      "Validates C2PA asset files and prints validation results.\n"
      "Usage:\n  c2pa_validate --asset=<path_to_asset> "
      "[--claim_signer_trust=<pem_path>] [--tsa_trust=<pem_path>] "
      "[--output_format=<txtpb, crjson>]");
  absl::InitializeLog();
  absl::ParseCommandLine(argc, argv);

  const std::string asset_path = absl::GetFlag(FLAGS_asset);
  if (asset_path.empty()) {
    std::cerr << "Error: --asset flag is required.\n";
    return 1;
  }

  const std::string output_format = absl::GetFlag(FLAGS_output_format);
  if (output_format != "txtpb" && output_format != "crjson") {
    std::cerr << "Error: --output_format must be txtpb or crjson.\n";
    return 1;
  }

  const std::string claim_signer_trust_path =
      absl::GetFlag(FLAGS_claim_signer_trust);
  const std::string tsa_trust_path = absl::GetFlag(FLAGS_tsa_trust);

  credentio::DefaultCryptoReadHandlerOptions crypto_options;
  std::string claim_signer_trust_pem;
  std::string tsa_trust_pem;

  if (!claim_signer_trust_path.empty()) {
    absl::StatusOr<std::string> pem = GetContents(claim_signer_trust_path);
    if (!pem.ok()) {
      std::cerr << "Error reading claim signer trust file: " << pem.status()
                << "\n";
      return 1;
    }
    claim_signer_trust_pem = *std::move(pem);
    crypto_options.claim_signer_trust_anchors_pem = claim_signer_trust_pem;
  } else {
    std::cerr << "WARNING: --claim_signer_trust is not provided. Skipping "
                 "claim signer trust checks.\n";
    crypto_options.skip_claim_signer_trust_checks_for_test = true;
  }

  if (!tsa_trust_path.empty()) {
    absl::StatusOr<std::string> pem = GetContents(tsa_trust_path);
    if (!pem.ok()) {
      std::cerr << "Error reading TSA trust file: " << pem.status() << "\n";
      return 1;
    }
    tsa_trust_pem = *std::move(pem);
    crypto_options.tsa_trust_anchors_pem = tsa_trust_pem;
  } else {
    std::cerr
        << "WARNING: --tsa_trust is not provided. Skipping TSA trust checks.\n";
    crypto_options.skip_tsa_trust_checks_for_test = true;
  }

  absl::StatusOr<std::unique_ptr<credentio::CryptoReadHandler>>
      crypto_read_handler =
          credentio::CreateDefaultCryptoReadHandler(crypto_options);
  if (!crypto_read_handler.ok()) {
    std::cerr << "Error creating crypto read handler: "
              << crypto_read_handler.status() << "\n";
    return 1;
  }

  credentio::AssetValidatorImpl validator(credentio::ValidatorOptions{
      .crypto_read_handler = *std::move(crypto_read_handler),
  });

  riegeli::CFileReader<> reader(asset_path);
  if (!reader.ok()) {
    std::cerr << "Error opening asset file: " << reader.status() << "\n";
    return 1;
  }

  std::optional<absl::string_view> media_type_opt;
  const absl::StatusOr<std::string> media_type =
      credentio::MediaType(asset_path);
  if (media_type.ok()) {
    media_type_opt = *media_type;
  } else {
    std::cerr << "Error determining media type: " << media_type.status()
              << "\n";
  }

  const absl::StatusOr<std::unique_ptr<credentio::ValidationResult>> result =
      validator.Validate(reader, media_type_opt);
  if (!result.ok()) {
    std::cerr << "Validation failed: " << result.status() << "\n";
    return 1;
  }

  std::cout << "Validation successful!\n";

  if (output_format == "crjson") {
    absl::Status status = PrintResultInCrJson(reader, media_type_opt, **result);
    if (status.ok()) {
      return 0;
    }
    std::cerr << "Failed to print result in crjson, reverting to txtpb: "
              << status << "\n";
  }

  absl::Status status = PrintResultInTxtpb(**result);
  if (!status.ok()) {
    std::cerr << "Failed to print result in txtpb: " << status << "\n";
    return 1;
  }

  return 0;
}
