//! # nwep
//!
//! `nwep` is a Rust library for building decentralized, authenticated network services
//! using the NWEP (Network Web Protocol) stack. It provides:
//!
//! - **Mutually-authenticated QUIC transport** via [`Server`] / [`Client`] — both sides
//!   prove their identity using Ed25519 keypairs; the connection is rejected if either
//!   end cannot authenticate.
//! - **Decentralized identity** via [`Keypair`], [`ManagedIdentity`](keypair::ManagedIdentity),
//!   and the Merkle log ([`MerkleLog`]) — identities are keys bound to append-only logs
//!   whose integrity is attested by a quorum of [`AnchorSet`] signers.
//! - **Trust verification** via [`TrustStore`] — validates that a peer's key was
//!   legitimately registered in the log and not revoked.
//! - **BLS threshold signatures** via [`BlsKeypair`] / [`AnchorSet`] — used by anchor
//!   nodes to co-sign [`Checkpoint`]s that commit the Merkle log root.
//!
//! ## Quick Start
//!
//! ```rust,no_run
//! use nwep::{init, Keypair, ServerBuilder, ClientBuilder, Router, ResponseWriter, Request};
//!
//! fn main() -> Result<(), nwep::Error> {
//!     init()?;
//!
//!     // Server
//!     let server_kp = Keypair::generate()?;
//!     let mut router = Router::new();
//!     router.handle_func("/hello", |w: &mut ResponseWriter, _r: &Request| {
//!         w.respond("ok", b"hello").unwrap();
//!     });
//!     let (srv, ev) = ServerBuilder::new("0.0.0.0:0", server_kp).build(router)?;
//!     let url = srv.url("/hello");
//!     std::thread::spawn(move || ev.run().unwrap());
//!
//!     // Client
//!     let client_kp = Keypair::generate()?;
//!     let client = ClientBuilder::new().connect(client_kp, &url)?;
//!     let resp = client.get("/hello")?;
//!     assert_eq!(resp.status, "ok");
//!     Ok(())
//! }
//! ```
//!
//! ## Initialization
//!
//! [`init`] must be called exactly once before any other function in this crate. It
//! initializes the underlying C library (OpenSSL, QUIC stack, etc.). Calling any
//! other function before [`init`] will return an error or produce undefined behaviour.
//!
//! ## Feature Flags
//!
//! - **`regenerate-bindings`** — Re-run `bindgen` at build time to regenerate
//!   `src/bindings.rs` from `nwep.h`. Requires `clang`/`libclang` to be installed.
//!   Normal consumers do not need this flag; the pre-generated bindings are checked in.

pub(crate) mod ffi;
pub mod error;
pub mod types;
pub mod protocol;
pub mod role;
pub mod log;
pub mod encoding;
pub mod crypto;
pub mod keypair;
pub mod bls;
pub mod addr;
pub(crate) mod msg;
pub mod server;
pub mod client;
pub mod merkle;
pub mod logindex;
pub mod checkpoint;
pub mod anchor;
pub mod logserver;
pub mod anchorserver;
pub mod trust;
pub mod cache;
pub mod pool;

pub use error::Error;
pub use types::{NodeId, MerkleHash, Tstamp, Duration, Header, Identity};
pub use role::ServerRole;
pub use keypair::Keypair;
pub use bls::{BlsKeypair, BlsPubkey, BlsSig};
pub use addr::{Addr, Url};
pub use checkpoint::Checkpoint;
pub use anchor::AnchorSet;
pub use merkle::{MerkleEntry, MerkleProof, MerkleLog};
pub use logindex::LogIndex;
pub use trust::{TrustStore, TrustSettings, TrustStorage, VerifiedIdentity, Staleness};
pub use cache::{IdentityCache, IdentityCacheSettings, CachedIdentity, CacheStats};
pub use pool::{LogServerPool, PoolSettings, PoolServer, PoolStrategy, ServerHealth};
pub use server::{Server, ServerBuilder, Handler, ResponseWriter, Request, Router, Settings as ServerSettings};
pub use client::{Client, ClientBuilder, Response, Notification};
pub use logserver::{LogServer, LogServerSettings};
pub use anchorserver::{AnchorServer, AnchorServerSettings};

/// Initialize the nwep library. Must be called before any other nwep functions.
pub fn init() -> Result<(), Error> {
    error::check(unsafe { ffi::nwep_init() })
}

/// Return the nwep library version string.
pub fn version() -> &'static str {
    unsafe {
        let ptr = ffi::nwep_version();
        if ptr.is_null() {
            ""
        } else {
            std::ffi::CStr::from_ptr(ptr)
                .to_str()
                .unwrap_or("")
        }
    }
}
