use std::path::PathBuf;

use rpki::data_model::crl::Asn1TimeEncoding;
use rpki::data_model::crl::RpkixCrl;

#[test]
fn decode_and_validate_crl_fixture() {
    let path = PathBuf::from("tests/fixtures/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.crl");
    let der = std::fs::read(&path).expect("read CRL fixture");

    let crl = RpkixCrl::decode_der(&der).expect("decode CRL");

    assert_eq!(crl.version, 2);
    assert_eq!(crl.signature_algorithm_oid, "1.2.840.113549.1.1.11");
    assert_eq!(crl.this_update.encoding, Asn1TimeEncoding::UtcTime);
    assert_eq!(crl.next_update.encoding, Asn1TimeEncoding::UtcTime);
    assert_eq!(
        hex::encode_upper(&crl.extensions.authority_key_identifier),
        "05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA"
    );
    assert_eq!(crl.extensions.crl_number.bytes_be, vec![12]);
    assert!(crl.revoked_certs.is_empty());

    println!("{crl:#?}");
}

#[test]
fn crl_signature_verification_succeeds_with_issuer_cert() {
    let crl_der = std::fs::read(
        "tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.crl",
    )
    .expect("read CRL fixture");
    let issuer_cert_der = std::fs::read(
        "tests/fixtures/repository/rpki.apnic.net/repository/B527EF581D6611E2BB468F7C72FD1FF2/BfycW4hQb3wNP4YsiJW-1n6fjro.cer",
    )
    .expect("read issuer certificate fixture");

    let crl = RpkixCrl::decode_der(&crl_der).expect("decode CRL");
    crl.verify_signature_with_issuer_certificate_der(&issuer_cert_der)
        .expect("CRL signature must verify with issuer certificate");
}

#[test]
fn decode_crl_with_revoked_entries() {
    let der = std::fs::read("tests/fixtures/0099DEAB073EFD74C250C0A382B25012B5082AEE.crl")
        .expect("read CRL fixture with revoked entries");

    let crl = RpkixCrl::decode_der(&der).expect("decode CRL");

    assert_eq!(crl.revoked_certs.len(), 21);
    for entry in &crl.revoked_certs {
        assert!(!entry.serial_number.bytes_be.is_empty());
        // 0 should be encoded as [0], otherwise no leading zero bytes.
        if entry.serial_number.bytes_be.len() > 1 {
            assert_ne!(entry.serial_number.bytes_be[0], 0);
        }
        let year = entry.revocation_date.utc.year();
        let expected = if year <= 2049 {
            Asn1TimeEncoding::UtcTime
        } else {
            Asn1TimeEncoding::GeneralizedTime
        };
        assert_eq!(entry.revocation_date.encoding, expected);
    }

    println!("{crl:#?}");
}
