use rpki::data_model::manifest::{
    ManifestDecodeError, ManifestEContent, ManifestObject, ManifestProfileError,
};
use rpki::data_model::signed_object::RpkiSignedObject;

#[test]
fn decode_manifest_fixture_smoke() {
    let der = std::fs::read(
        "tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
    )
    .expect("read MFT fixture");
    let mft = ManifestObject::decode_der(&der).expect("decode manifest object");
    mft.validate_profile().expect("validate manifest profile");

    assert_eq!(mft.manifest.version, 0);
    assert_eq!(
        mft.manifest.file_hash_alg,
        rpki::data_model::oid::OID_SHA256
    );
    assert!(mft.manifest.next_update > mft.manifest.this_update);
    assert!(mft.manifest.file_count() > 0);
    // The manifest file MUST NOT be listed in its own fileList.
    let entries = mft
        .manifest
        .parse_files()
        .expect("parse validated manifest fileList");
    assert!(
        entries
            .iter()
            .all(|f| !f.file_name.as_str().to_ascii_lowercase().ends_with(".mft"))
    );
}

#[test]
fn decode_rejects_non_manifest_econtent_type() {
    let der = std::fs::read("tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/AS4538.roa")
        .expect("read ROA fixture");
    let err = ManifestObject::decode_der(&der).unwrap_err();
    assert!(matches!(
        err,
        ManifestDecodeError::Validate(ManifestProfileError::InvalidEContentType(_))
    ));
}

#[test]
fn from_signed_object_accepts_manifest_fixture() {
    let so_der = std::fs::read(
        "tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
    )
    .expect("read MFT fixture");
    let so = RpkiSignedObject::decode_der(&so_der).expect("decode signed object");
    let mft = ManifestObject::from_signed_object(so).expect("from_signed_object");
    mft.validate_profile().expect("validate manifest profile");
}

#[test]
fn decode_manifest_econtent_from_fixture_signed_object() {
    let so_der = std::fs::read(
        "tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
    )
    .expect("read MFT fixture");
    let so = rpki::data_model::signed_object::RpkiSignedObject::decode_der(&so_der)
        .expect("decode signed object");
    let e = ManifestEContent::decode_der(&so.signed_data.encap_content_info.econtent)
        .expect("decode manifest eContent");
    assert_eq!(e.version, 0);
}
