use rpki::data_model::common::{
    Asn1TimeEncoding, Asn1TimeUtc, BigUnsigned, algorithm_params_absent_or_null,
};
use x509_parser::prelude::FromDer;
use x509_parser::time::ASN1Time;
use x509_parser::x509::AlgorithmIdentifier;

#[test]
fn big_unsigned_helpers() {
    let n = BigUnsigned { bytes_be: vec![0] };
    assert_eq!(n.to_u64(), Some(0));
    assert_eq!(n.to_hex_upper(), "00");

    let n = BigUnsigned {
        bytes_be: vec![0x01, 0x02, 0x03],
    };
    assert_eq!(n.to_u64(), Some(0x010203));
    assert_eq!(n.to_hex_upper(), "010203");

    let n = BigUnsigned {
        bytes_be: vec![0; 9],
    };
    assert_eq!(n.to_u64(), None);
}

#[test]
fn time_encoding_validation() {
    let t = Asn1TimeUtc {
        utc: time::OffsetDateTime::from_unix_timestamp(0).unwrap(),
        encoding: Asn1TimeEncoding::UtcTime,
    };
    t.validate_encoding_rfc5280("t").expect("utc ok");

    let t = Asn1TimeUtc {
        utc: time::OffsetDateTime::parse(
            "2050-01-01T00:00:00Z",
            &time::format_description::well_known::Rfc3339,
        )
        .unwrap(),
        encoding: Asn1TimeEncoding::UtcTime,
    };
    assert!(t.validate_encoding_rfc5280("t").is_err());
}

#[test]
fn algorithm_params_absent_or_null_helper() {
    // AlgorithmIdentifier ::= SEQUENCE { algorithm OID, parameters ANY OPTIONAL }
    // Using sha256WithRSAEncryption with NULL parameters.
    let alg_null = hex::decode("300D06092A864886F70D01010B0500").unwrap();
    let (_rem, id) = AlgorithmIdentifier::from_der(&alg_null).expect("parse AlgorithmIdentifier");
    assert!(algorithm_params_absent_or_null(&id));

    // Same OID, but parameters = INTEGER 1 (invalid for our helper).
    let alg_int = hex::decode("300E06092A864886F70D01010B020101").unwrap();
    let (_rem, id) = AlgorithmIdentifier::from_der(&alg_int).expect("parse AlgorithmIdentifier");
    assert!(!algorithm_params_absent_or_null(&id));

    // parameters absent
    let oid = der_parser::Oid::from(&[1u64, 2, 3]).unwrap();
    let id = AlgorithmIdentifier::new(oid, None);
    assert!(algorithm_params_absent_or_null(&id));
}

#[test]
fn asn1_time_to_model_helper_covers_branches() {
    let dt_utc = time::OffsetDateTime::parse(
        "2024-01-01T00:00:00Z",
        &time::format_description::well_known::Rfc3339,
    )
    .unwrap();
    let t = ASN1Time::new_utc(dt_utc);
    let m = rpki::data_model::common::asn1_time_to_model(t);
    assert_eq!(m.encoding, Asn1TimeEncoding::UtcTime);

    let dt_gen = time::OffsetDateTime::parse(
        "2050-01-01T00:00:00Z",
        &time::format_description::well_known::Rfc3339,
    )
    .unwrap();
    let t = ASN1Time::new_generalized(dt_gen);
    let m = rpki::data_model::common::asn1_time_to_model(t);
    assert_eq!(m.encoding, Asn1TimeEncoding::GeneralizedTime);
}

#[test]
fn big_unsigned_from_biguint_zero_encodes_as_single_zero_byte() {
    let z = der_parser::num_bigint::BigUint::from(0u32);
    let n = BigUnsigned::from_biguint(&z);
    assert_eq!(n.bytes_be, vec![0]);
}
