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

#include <memory>
#include <string>
#include <variant>

#include "absl/base/no_destructor.h"
#include "absl/functional/overload.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "openssl/bio.h"
#include "openssl/ec.h"
#include "openssl/ec_key.h"
#include "openssl/evp.h"
#include "openssl/mem.h"
#include "openssl/nid.h"
#include "openssl/obj.h"
#include "openssl/pem.h"
#include "openssl/x509.h"
#include "tink/insecure_secret_key_access.h"
#include "tink/key_status.h"
#include "tink/keyset_handle.h"
#include "tink/partial_key_access.h"
#include "tink/pem/signature_key_parser.h"
#include "tink/public_key_sign.h"
#include "tink/signature/config_v0.h"
#include "tink/signature/ecdsa_parameters.h"
#include "tink/signature/ecdsa_private_key.h"
#include "tink/signature/ed25519_parameters.h"
#include "tink/signature/ed25519_private_key.h"
#include "tink/signature/rsa_ssa_pss_parameters.h"
#include "tink/signature/rsa_ssa_pss_private_key.h"
#include "tink/signature/signature_config.h"

namespace credentio {

using ::crypto::tink::EcdsaParameters;
using ::crypto::tink::Ed25519Parameters;
using ::crypto::tink::GetPartialKeyAccess;
using ::crypto::tink::InsecureSecretKeyAccess;
using ::crypto::tink::KeysetHandle;
using ::crypto::tink::KeysetHandleBuilder;
using ::crypto::tink::PublicKeySign;
using ::crypto::tink::RsaSsaPssParameters;

absl::StatusOr<std::unique_ptr<crypto::tink::PublicKeySign>> LoadTestKeyFromPem(
    absl::string_view pem,
    const std::variant<EcdsaParameters, Ed25519Parameters, RsaSsaPssParameters>&
        key_params) {
  static const absl::NoDestructor<absl::Status> registration_status(
      []() { return crypto::tink::SignatureConfig::Register(); }());
  ABSL_RETURN_IF_ERROR(*registration_status);
  using TinkPrivateKey = std::variant<crypto::tink::EcdsaPrivateKey,
                                      crypto::tink::RsaSsaPssPrivateKey,
                                      crypto::tink::Ed25519PrivateKey>;
  absl::StatusOr<TinkPrivateKey> private_key = std::visit(
      absl::Overload(
          [&pem](
              const EcdsaParameters& params) -> absl::StatusOr<TinkPrivateKey> {
            return tink_pem::PemToEcdsaPrivateKey(
                pem, params, InsecureSecretKeyAccess::Get(),
                GetPartialKeyAccess());
          },
          [&pem](const RsaSsaPssParameters& params)
              -> absl::StatusOr<TinkPrivateKey> {
            return tink_pem::PemToRsaSsaPssPrivateKey(
                pem, params, InsecureSecretKeyAccess::Get(),
                GetPartialKeyAccess());
          },
          [&pem](const Ed25519Parameters& params)
              -> absl::StatusOr<TinkPrivateKey> {
            return tink_pem::PemToEd25519PrivateKey(
                pem, params, InsecureSecretKeyAccess::Get(),
                GetPartialKeyAccess());
          }),
      key_params);
  if (!private_key.ok()) {
    return private_key.status();
  }

  KeysetHandleBuilder builder;
  std::visit(
      [&builder](const auto& key) {
        builder.AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey(
            key, crypto::tink::KeyStatus::kEnabled, /*is_primary=*/true));
      },
      *private_key);

  ABSL_ASSIGN_OR_RETURN(KeysetHandle handle, builder.Build());
  return handle.GetPrimitive<crypto::tink::PublicKeySign>(
      crypto::tink::ConfigSignatureV0());
}

absl::StatusOr<std::string> LoadOcspResponseFromPem(absl::string_view pem) {
  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem.data(), pem.size()));
  if (bio == nullptr) {
    return absl::InternalError("Failed to create BIO.");
  }

  std::string response;
  bool found = false;
  while (true) {
    char* name = nullptr;
    char* header = nullptr;
    unsigned char* data = nullptr;
    long len = 0;  // NOLINT: Can't use `int64_t` because on ARM that becomes
                   // long long which is incompatible with `PEM_read_bio(...)`.
    if (!PEM_read_bio(bio.get(), &name, &header, &data, &len)) {
      break;
    }
    bssl::UniquePtr<char> name_ptr(name);
    bssl::UniquePtr<char> header_ptr(header);
    bssl::UniquePtr<unsigned char> data_ptr(data);

    if (absl::string_view(name) == "OCSP RESPONSE") {
      if (found) {
        return absl::InvalidArgumentError(
            "Multiple OCSP RESPONSE blocks found; expected only one.");
      }
      response = std::string(reinterpret_cast<char*>(data), len);
      found = true;
    }
  }

  if (!found) {
    return absl::InvalidArgumentError("No OCSP RESPONSE block found.");
  }

  return response;
}

}  // namespace credentio
