// 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 "crypto/default/cms/cms_test_helper.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>

#include "absl/log/check.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "crypto/default/cms/cms_parser.h"
#include "openssl/base.h"
#include "openssl/bio.h"
#include "openssl/bytestring.h"
#include "openssl/obj.h"
#include "openssl/pem.h"
#include "openssl/x509.h"
#include "testing/test_file_utils.h"

namespace credentio_cms {

constexpr absl::string_view kTestRepoDir = "c2pa/";

std::string GetRawFileContents(const std::string& filename) {
  std::string path =
      absl::StrCat(kTestRepoDir, "crypto/default/cms/testdata/", filename);
  auto contents = credentio_testing::GetContents(path);
  CHECK(contents.ok()) << "Failed to load: " << path << ", "
                       << contents.status();
  return *contents;
}

std::string GetFileContents(const std::string& filename) {
  std::string contents = GetRawFileContents(filename);
  // Normalize line endings by replacing \n with \r\n when needed.
  std::string normalized_contents;
  bool has_cr = false;
  for (char c : contents) {
    if (c == '\r') {
      has_cr = true;
    } else {
      if (c == '\n' && !has_cr) {
        normalized_contents += '\r';
      }
      has_cr = false;
    }
    normalized_contents += c;
  }
  return normalized_contents;
}

// Quick and dirty functions to extract the CMS object. It probably only works
// on the test cases.
std::string GetCms(const std::string& message) {
  auto pos = message.find("name=\"smime.p7s\"");
  if (pos == std::string::npos) {
    pos = message.find("name=\"smime.p7m\"");
  }
  if (pos == std::string::npos) {
    pos = message.find("name=smime.p7s");
  }
  if (pos == std::string::npos) {
    pos = message.find("name=smime.p7m");
  }
  if (pos == std::string::npos) {
    pos = message.find("name=smime.p7c");
  }
  CHECK(pos != std::string::npos);
  auto start = message.find("\x0d\x0a\x0d\x0a", pos);
  CHECK(start != std::string::npos);
  start += 2;
  auto end = message.find('-', start);
  if (end == std::string::npos) {
    end = message.find("\x0d\x0a\x0d\x0a", start);
  }
  if (end == std::string::npos) {
    end = message.size();
  }
  std::string decoded;
  CHECK(absl::Base64Unescape(message.substr(start, end - start), &decoded));
  return decoded;
}

std::string GetFirstMimePart(const std::string& contents) {
  const char kBoundary[] = "boundary=\"";
  const char kUnquotedBoundary[] = "boundary=";
  int boundary_start = contents.find(kBoundary);
  int boundary_end;
  if (boundary_start == std::string::npos) {
    boundary_start = contents.find(kUnquotedBoundary);
    CHECK_NE(std::string::npos, boundary_start);
    boundary_start += sizeof(kUnquotedBoundary) - 1;
    boundary_end = contents.find_first_of(";\r", boundary_start);
  } else {
    boundary_start += sizeof(kBoundary) - 1;
    boundary_end = contents.find('\"', boundary_start);
  }
  CHECK_NE(std::string::npos, boundary_end);
  std::string boundary =
      "--" + contents.substr(boundary_start, boundary_end - boundary_start);

  int part_start = contents.find(boundary, boundary_end);
  CHECK_NE(std::string::npos, part_start);
  part_start = contents.find("\r\n", part_start + boundary.size());
  CHECK_NE(std::string::npos, part_start);
  part_start += 2;
  int part_end = contents.find(boundary, part_start);
  CHECK_NE(std::string::npos, part_end);
  CHECK_GT(part_end, part_start + 2);
  // String the CRLF that is right before the boundary end.
  return contents.substr(part_start, part_end - part_start - 2);
}

// Convert an ASN.1 X509 name to a single line string.
std::string CBSToName(const ByteString& raw_name) {
  X509_NAME* name = nullptr;
  const unsigned char* p = CBS_data(raw_name.cbs_ptr());
  d2i_X509_NAME(&name, &p, CBS_len(raw_name.cbs_ptr()));
  std::string line;
  BIO* bio = BIO_new(BIO_s_mem());
  X509_NAME_print_ex(bio, name, 0 /* indent */, 0 /* flags */);
  int size = BIO_pending(bio);
  std::unique_ptr<char[]> buffer(new char[size]);
  CHECK_EQ(size, BIO_read(bio, buffer.get(), size));
  line.assign(&buffer[0], size);
  X509_NAME_free(name);
  BIO_free_all(bio);
  return line;
}

X509* PemToCertificate(const std::string& pem) {
  bssl::UniquePtr<BIO> bio(
      BIO_new_mem_buf(const_cast<char*>(pem.data()), pem.size()));
  return PEM_read_bio_X509(bio.get(), nullptr /* existing key */,
                           nullptr /* password callback */,
                           nullptr /* password */);
}

EVP_PKEY* PemToKey(const std::string& pem) {
  bssl::UniquePtr<BIO> bio(
      BIO_new_mem_buf(const_cast<char*>(pem.data()), pem.size()));
  return PEM_read_bio_PrivateKey(bio.get(), nullptr /* existing key */,
                                 nullptr /* password callback */,
                                 nullptr /* password */);
}

std::string NidToDerString(int nid) {
  // Encode the OID as an ASN.1 OBJECT.
  CBB cbb;
  CHECK(CBB_init(&cbb, 0));
  CHECK(OBJ_nid2cbb(&cbb, nid));
  CBS asn1_cbs;
  CBS_init(&asn1_cbs, CBB_data(&cbb), CBB_len(&cbb));
  // Copy the raw OID into the return value and discard the ASN.1 headers.
  CBS raw_oid_cbs;
  CHECK(CBS_get_asn1(&asn1_cbs, &raw_oid_cbs, CBS_ASN1_OBJECT));
  size_t raw_oid_len = CBS_len(&raw_oid_cbs);
  std::string ret(raw_oid_len, '\0');
  CHECK(CBS_copy_bytes(&raw_oid_cbs, reinterpret_cast<uint8_t*>(ret.data()),
                       raw_oid_len));
  CBB_cleanup(&cbb);
  return ret;
}

}  // namespace credentio_cms
