// 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 <ostream>
#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/status_macros.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 "google/protobuf/text_format.h"
#include "nlohmann/json_fwd.hpp"
#include "riegeli/bytes/cfile_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)");
ABSL_FLAG(std::string, output_file, "",
          "Path to the output file to write validation results to (Optional; "
          "defaults to stdout).");

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::ostream& out) {
  std::string text_format;
  if (google::protobuf::TextFormat::PrintToString(result.proto(),
                                                  &text_format)) {
    out << text_format;
  } else {
    return absl::InternalError("Failed to convert result proto to text format");
  }
  return absl::OkStatus();
}

absl::Status PrintResultInCrJson(const credentio::ValidationResult& result,
                                 std::ostream& out) {
  ABSL_ASSIGN_OR_RETURN(nlohmann::json crjson,
                        credentio::ConvertToCrJson(result));
  out << crjson.dump(2);
  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>] [--output_file=<output_path>]");
  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;
  }

  const std::string output_path = absl::GetFlag(FLAGS_output_file);

  std::ofstream file_out;
  std::ostream* out = &std::cout;
  if (!output_path.empty()) {
    file_out.open(output_path);
    if (!file_out.is_open()) {
      std::cerr << "Error: Failed to open output file: " << output_path << "\n";
      return 1;
    }
    out = &file_out;
  }

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

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

  return 0;
}
