//! Library context example — isolated `LibCtx` with explicit provider loading.
//!
//! An isolated library context lets you load a specific set of providers
//! without affecting the process-wide default context. This is useful for
//! FIPS isolation or for loading a custom provider alongside the built-in one.
//!
//! Run with: `cargo run --example lib_ctx -p native-ossl`

use native_ossl::digest::DigestAlg;
use native_ossl::lib_ctx::LibCtx;
use std::sync::Arc;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // ── Default global context ─────────────────────────────────────────────────

    // Algorithms fetched with `None` as the library context use the global
    // default context, which already has the built-in provider loaded.
    let sha256 = DigestAlg::fetch(c"SHA2-256", None)?;
    let mut ctx = sha256.new_context()?;
    ctx.update(b"hello")?;
    let mut out = [0u8; 32];
    ctx.finish(&mut out)?;
    println!(
        "Global context SHA-256: {}",
        native_ossl::util::hex_encode(out)
    );

    // ── Isolated library context ───────────────────────────────────────────────

    // `LibCtx::new()` creates a fresh context with NO providers loaded.
    // Load `default` explicitly to get the built-in algorithms.
    let lib_ctx = Arc::new(LibCtx::new()?);
    let _default_provider = lib_ctx.load_provider(c"default")?;

    // Algorithms fetched in the isolated context are independent of the global one.
    let sha256_isolated = DigestAlg::fetch_in(&lib_ctx, c"SHA2-256", None)?;
    let mut ctx2 = sha256_isolated.new_context()?;
    ctx2.update(b"hello")?;
    let mut out2 = [0u8; 32];
    ctx2.finish(&mut out2)?;
    println!(
        "Isolated context SHA-256: {}",
        native_ossl::util::hex_encode(out2)
    );

    assert_eq!(out, out2, "both contexts must produce the same digest");
    println!("Results agree: OK");

    // ── FIPS isolation ─────────────────────────────────────────────────────────

    // To load only the FIPS provider, skip `load_provider("default")` and
    // load `fips` instead.  Algorithms not approved by FIPS will fail to fetch.
    //
    //   let fips_ctx = Arc::new(LibCtx::new()?);
    //   let _fips  = fips_ctx.load_provider(c"fips")?;
    //   let _base  = fips_ctx.load_provider(c"base")?;
    //   let md = DigestAlg::fetch_in(&fips_ctx, c"SHA2-256", None)?;
    //   // DigestAlg::fetch_in(&fips_ctx, c"MD5", None) would fail — MD5 is not FIPS-approved.
    println!("(FIPS isolation example is shown as a comment — requires fips provider installed)");

    Ok(())
}
