//! X.509 example — build a self-signed certificate and inspect its fields.
//!
//! Run with: cargo run --example x509 -p native-ossl

use native_ossl::pkey::KeygenCtx;
use native_ossl::x509::{X509Builder, X509NameOwned};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // ── Generate an Ed25519 key pair ──────────────────────────────────────────

    let mut kgen = KeygenCtx::new(c"ED25519")?;
    let priv_key = kgen.generate()?;
    let pub_key = native_ossl::pkey::Pkey::<native_ossl::pkey::Public>::from(priv_key.clone());

    // ── Build a self-signed certificate ──────────────────────────────────────

    let mut name = X509NameOwned::new()?;
    name.add_entry_by_txt(c"CN", b"example.com")?;
    name.add_entry_by_txt(c"O", b"Example Org")?;
    name.add_entry_by_txt(c"C", b"US")?;

    let cert = X509Builder::new()?
        .set_version(2)? // X.509 v3
        .set_serial_number(42)?
        .set_not_before_offset(0)? // valid from now
        .set_not_after_offset(365 * 86400)? // valid for 1 year
        .set_subject_name(&name)?
        .set_issuer_name(&name)? // self-signed
        .set_public_key(&pub_key)?
        .sign(&priv_key, None)? // Ed25519 (no explicit digest needed)
        .build();

    // ── Inspect fields ────────────────────────────────────────────────────────

    if let Some(subject) = cert.subject_name().to_string() {
        println!("Subject:  {subject}");
    }
    if let Some(issuer) = cert.issuer_name().to_string() {
        println!("Issuer:   {issuer}");
    }
    if let Some(serial) = cert.serial_number() {
        println!("Serial:   {serial}");
    }
    if let Some(nb) = cert.not_before_str() {
        println!("NotBefore: {nb}");
    }
    if let Some(na) = cert.not_after_str() {
        println!("NotAfter:  {na}");
    }
    println!("Valid now: {}", cert.is_valid_now());
    println!("Self-signed: {}", cert.is_self_signed());

    // ── DER round-trip ────────────────────────────────────────────────────────

    let der = cert.to_der()?;
    let reloaded = native_ossl::x509::X509::from_der(&der)?;
    assert_eq!(cert.to_der()?, reloaded.to_der()?);
    println!("DER round-trip: OK ({} bytes)", der.len());

    // ── PEM output ────────────────────────────────────────────────────────────

    let pem = cert.to_pem()?;
    println!("\nPEM certificate:\n{}", std::str::from_utf8(&pem)?);

    // ── Signature verification ────────────────────────────────────────────────

    cert.verify(&pub_key)?;
    println!("Signature verification: OK");

    Ok(())
}
