use std::path::PathBuf;

use rpki::data_model::aspa::AspaEContent;
use rpki::data_model::aspa::AspaObject;
use rpki::data_model::crl::RpkixCrl;
use rpki::data_model::manifest::ManifestEContent;
use rpki::data_model::manifest::ManifestObject;
use rpki::data_model::rc::ResourceCertificate;
use rpki::data_model::roa::RoaEContent;
use rpki::data_model::roa::RoaObject;
use rpki::data_model::signed_object::RpkiSignedObject;
use rpki::data_model::ta::{TaCertificate, TrustAnchor};
use rpki::data_model::tal::Tal;

#[test]
fn scheme_a_layered_api_smoke() {
    // TAL / TA / TrustAnchor
    let tal_path = PathBuf::from("tests/fixtures/tal/ripe-ncc.tal");
    let tal_bytes = std::fs::read(&tal_path).expect("read TAL fixture");
    let tal = Tal::parse_bytes(&tal_bytes)
        .expect("parse TAL")
        .validate_profile()
        .expect("validate TAL profile");

    let ta_path = PathBuf::from("tests/fixtures/ta/ripe-ncc-ta.cer");
    let ta_der = std::fs::read(&ta_path).expect("read TA cert fixture");
    let ta = TaCertificate::parse_der(&ta_der)
        .expect("parse TA cert")
        .validate_profile()
        .expect("validate TA constraints");
    ta.verify_self_signature()
        .expect("verify TA self-signature");

    let resolved = tal
        .ta_uris
        .first()
        .cloned()
        .expect("TAL must include at least one TA URI");
    let _ta = TrustAnchor::bind(tal, ta, Some(&resolved)).expect("bind trust anchor");

    // A CA resource certificate fixture (used as issuer in other tests).
    let ca_path = PathBuf::from(
        "tests/fixtures/repository/rpki.apnic.net/repository/B527EF581D6611E2BB468F7C72FD1FF2/BfycW4hQb3wNP4YsiJW-1n6fjro.cer",
    );
    let ca_der = std::fs::read(&ca_path).expect("read CA cert fixture");
    let ca_rc = ResourceCertificate::parse_der(&ca_der)
        .expect("parse CA resource certificate")
        .validate_profile()
        .expect("validate CA resource certificate profile");
    ca_rc
        .validate_profile()
        .expect("validate CA resource certificate profile");

    // Signed object wrapper.
    let mft_path = PathBuf::from(
        "tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
    );
    let mft_der = std::fs::read(&mft_path).expect("read MFT fixture");
    let so = RpkiSignedObject::parse_der(&mft_der)
        .expect("parse signed object")
        .validate_profile()
        .expect("validate signed object profile");
    so.verify().expect("verify CMS signature");

    // Manifest object.
    let mft_obj = ManifestObject::parse_der(&mft_der)
        .expect("parse manifest")
        .validate_profile()
        .expect("validate manifest profile");
    mft_obj
        .validate_profile()
        .expect("validate manifest profile");
    mft_obj
        .validate_embedded_ee_cert()
        .expect("validate manifest EE resources");
    mft_obj
        .signed_object
        .verify()
        .expect("verify manifest CMS signature");
    let mft_ec = ManifestEContent::parse_der(
        &mft_obj
            .signed_object
            .signed_data
            .encap_content_info
            .econtent,
    )
    .expect("parse MFT eContent")
    .validate_profile()
    .expect("validate MFT eContent profile");
    mft_ec
        .validate_profile()
        .expect("validate MFT eContent profile");

    // ROA object.
    let roa_path =
        PathBuf::from("tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/AS4538.roa");
    let roa_der = std::fs::read(&roa_path).expect("read ROA fixture");
    let roa_obj = RoaObject::parse_der(&roa_der)
        .expect("parse ROA")
        .validate_profile()
        .expect("validate ROA profile");
    roa_obj
        .validate_embedded_ee_cert()
        .expect("validate ROA EE resources");
    roa_obj
        .signed_object
        .verify()
        .expect("verify ROA CMS signature");
    let roa_ec = RoaEContent::parse_der(
        &roa_obj
            .signed_object
            .signed_data
            .encap_content_info
            .econtent,
    )
    .expect("parse ROA eContent")
    .validate_profile()
    .expect("validate ROA eContent profile");
    roa_ec
        .validate_profile()
        .expect("validate ROA eContent profile");

    // ASPA object.
    let aspa_path = PathBuf::from(
        "tests/fixtures/repository/chloe.sobornost.net/rpki/RIPE-nljobsnijders/5m80fwYws_3FiFD7JiQjAqZ1RYQ.asa",
    );
    let aspa_der = std::fs::read(&aspa_path).expect("read ASPA fixture");
    let aspa_obj = AspaObject::parse_der(&aspa_der)
        .expect("parse ASPA")
        .validate_profile()
        .expect("validate ASPA profile");
    aspa_obj
        .validate_embedded_ee_cert()
        .expect("validate ASPA EE resources");
    aspa_obj
        .signed_object
        .verify()
        .expect("verify ASPA CMS signature");
    let aspa_ec = AspaEContent::parse_der(
        &aspa_obj
            .signed_object
            .signed_data
            .encap_content_info
            .econtent,
    )
    .expect("parse ASPA eContent")
    .validate_profile()
    .expect("validate ASPA eContent profile");
    aspa_ec
        .validate_profile()
        .expect("validate ASPA eContent profile");

    // CRL object.
    let crl_path = PathBuf::from("tests/fixtures/0099DEAB073EFD74C250C0A382B25012B5082AEE.crl");
    let crl_der = std::fs::read(&crl_path).expect("read CRL fixture with revoked entries");
    let crl = RpkixCrl::parse_der(&crl_der)
        .expect("parse CRL")
        .validate_profile()
        .expect("validate CRL profile");
    crl.validate_profile().expect("validate CRL profile");
}
