use rpki::data_model::manifest::{ManifestObject, ManifestValidateError};
use rpki::data_model::rc::{
    Afi, AsIdOrRange, AsIdentifierChoice, AsResourceSet, IpAddressChoice, IpAddressFamily,
    IpResourceSet,
};

fn load_manifest_fixture() -> ManifestObject {
    let der = std::fs::read(
        "tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
    )
    .expect("read MFT fixture");
    ManifestObject::decode_der(&der).expect("decode manifest")
}

#[test]
fn manifest_embedded_ee_cert_resources_validate() {
    let mft = load_manifest_fixture();
    mft.validate_embedded_ee_cert()
        .expect("manifest EE cert resources must validate");
}

#[test]
fn validate_rejects_when_ip_and_as_resources_missing() {
    let mft = load_manifest_fixture();
    let mut ee = mft.signed_object.signed_data.certificates[0]
        .resource_cert
        .clone();
    ee.tbs.extensions.ip_resources = None;
    ee.tbs.extensions.as_resources = None;
    let err = mft.validate_against_ee_cert(&ee).unwrap_err();
    assert!(matches!(err, ManifestValidateError::EeResourcesMissing));
}

#[test]
fn validate_rejects_when_ip_resources_not_inherit() {
    let mft = load_manifest_fixture();
    let mut ee = mft.signed_object.signed_data.certificates[0]
        .resource_cert
        .clone();
    ee.tbs.extensions.ip_resources = Some(IpResourceSet {
        families: vec![IpAddressFamily {
            afi: Afi::Ipv4,
            choice: IpAddressChoice::AddressesOrRanges(vec![]),
        }],
    });
    ee.tbs.extensions.as_resources = None;
    let err = mft.validate_against_ee_cert(&ee).unwrap_err();
    assert!(matches!(
        err,
        ManifestValidateError::EeIpResourcesNotInherit
    ));
}

#[test]
fn validate_rejects_when_as_rdi_present_or_asnum_not_inherit() {
    let mft = load_manifest_fixture();

    // rdi present is rejected.
    let mut ee = mft.signed_object.signed_data.certificates[0]
        .resource_cert
        .clone();
    ee.tbs.extensions.ip_resources = None;
    ee.tbs.extensions.as_resources = Some(AsResourceSet {
        asnum: Some(AsIdentifierChoice::Inherit),
        rdi: Some(AsIdentifierChoice::Inherit),
    });
    let err = mft.validate_against_ee_cert(&ee).unwrap_err();
    assert!(matches!(
        err,
        ManifestValidateError::EeAsResourcesRdiPresent
    ));

    // asnum not inherit is rejected.
    let mut ee = mft.signed_object.signed_data.certificates[0]
        .resource_cert
        .clone();
    ee.tbs.extensions.ip_resources = None;
    ee.tbs.extensions.as_resources = Some(AsResourceSet {
        asnum: Some(AsIdentifierChoice::AsIdsOrRanges(vec![AsIdOrRange::Id(
            64496,
        )])),
        rdi: None,
    });
    let err = mft.validate_against_ee_cert(&ee).unwrap_err();
    assert!(matches!(
        err,
        ManifestValidateError::EeAsResourcesNotInherit
    ));
}
