//! Convenience API for cryptographic operations
//!
//! This module provides a unified, high-level API for encryption, decryption,
//! signing, and verification with automatic algorithm selection.
//!
//! ## Security: `_unverified` variants
//!
//! Most operations in this module come in two forms:
//!
//! 1. A **Zero-Trust-aware** form that takes `SecurityMode` (or an equivalent
//!    parameter) and performs session validation before executing the
//!    cryptographic operation — e.g.
//!    `encrypt_aes_gcm(data, key, SecurityMode::Verified(&session))`.
//!
//! 2. An **`_unverified` shortcut** that skips session validation and executes
//!    the operation directly — e.g. `encrypt_aes_gcm_unverified(data, key)`.
//!    These wrappers exist for contexts where Zero Trust verification is not
//!    applicable (e.g. local-only encryption, internal dispatch layers, KAT
//!    reproduction) and for direct invocation from tests.
//!
//! ### What `_unverified` does NOT mean
//!
//! Crucially, `_unverified` refers ONLY to the absence of a `VerifiedSession`
//! audit chain. It does NOT mean any of:
//!
//! - **Skips cryptographic input validation.** Key length, nonce size,
//!   AEAD tag length, signature shape, etc., are all still validated.
//! - **Skips constant-time guarantees.** Secret comparisons in `_unverified`
//!   helpers still go through `subtle::ConstantTimeEq`.
//! - **Skips weak-key rejection.** `AeadError::WeakKey` still fires on the
//!   all-zero key whether you call `encrypt_aes_gcm` or
//!   `encrypt_aes_gcm_unverified`.
//! - **Skips Pattern 6 error opacity.** Adversary-reachable failures still
//!   collapse to opaque variants in both forms.
//!
//! Treat the suffix as the moral equivalent of "no audit trail attached."
//!
//! **Production guidance:** prefer the `SecurityMode::Verified` form. Reach for
//! `_unverified` only when you have an explicit reason not to involve a
//! `VerifiedSession` — and make that reason reviewable at the call site.
//! The verified form also requires a `VerifiedSession` reference, which is
//! type-enforced and cannot be stumbled into; the `_unverified` form carries
//! the word "unverified" in its name so that code review can catch accidental
//! use.
//!
//! ## Unified API
//!
//! All operations use `CryptoConfig` for configuration:
//!
//! ```no_run
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! use latticearc::unified_api::{
//!     encrypt, decrypt, generate_signing_keypair, sign_with_key, verify,
//!     CryptoConfig, UseCase, EncryptKey, DecryptKey,
//! };
//! # let message = b"example message";
//!
//! // Hybrid encryption (recommended - ML-KEM-768 + X25519 + AES-256-GCM)
//! let (pk, sk) = latticearc::generate_hybrid_keypair()?;
//! let encrypted = encrypt(b"data", EncryptKey::Hybrid(&pk),
//!     CryptoConfig::new().use_case(UseCase::FileStorage))?;
//! let plaintext = decrypt(&encrypted, DecryptKey::Hybrid(&sk), CryptoConfig::new())?;
//!
//! // Symmetric encryption (AES-256-GCM). Generate a fresh key — `[0u8; 32]`
//! // is rejected by the AEAD constructor as a weak key.
//! let key = latticearc::primitives::rand::random_bytes(32);
//! let encrypted = encrypt(b"data", EncryptKey::Symmetric(&key),
//!     CryptoConfig::new().force_scheme(latticearc::CryptoScheme::Symmetric))?;
//! let plaintext = decrypt(&encrypted, DecryptKey::Symmetric(&key), CryptoConfig::new())?;
//!
//! // Sign (generate keypair once, sign with persistent key)
//! let (pk, sk, scheme) = generate_signing_keypair(CryptoConfig::new())?.into_parts();
//! let signed = sign_with_key(message, sk.as_ref(), pk.as_ref(), CryptoConfig::new())?;
//!
//! // Verify
//! let is_valid = verify(&signed, CryptoConfig::new())?;
//! # Ok(())
//! # }
//! ```
//!
//! ## With Zero Trust Session
//!
//! ```no_run
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! use latticearc::unified_api::{encrypt, CryptoConfig, UseCase, VerifiedSession, EncryptKey};
//! # let pk_ed = [0u8; 32];
//! # let sk_ed = [0u8; 32];
//!
//! let session = VerifiedSession::establish(&pk_ed, &sk_ed)?;
//! let (pk, _sk) = latticearc::generate_hybrid_keypair()?;
//! let encrypted = encrypt(b"data", EncryptKey::Hybrid(&pk),
//!     CryptoConfig::new()
//!         .session(&session)
//!         .use_case(UseCase::FileStorage))?;
//! # Ok(())
//! # }
//! ```

mod aes_gcm;
mod api;
pub(crate) mod ecdsa_p384;
pub(crate) mod ed25519;
mod hashing;
mod hybrid;
mod hybrid_sig;
mod keygen;
mod pq_kem;
mod pq_sig;

// ============================================================================
// Unified API
// ============================================================================

pub use api::{
    SigningKeypair, decrypt, encrypt, generate_signing_keypair, sign_with_key, verify,
    verify_with_anchor,
};

// ============================================================================
// Hybrid Key Generation (ML-KEM + X25519)
// ============================================================================

pub use hybrid::{generate_hybrid_keypair, generate_hybrid_keypair_with_level};

// ============================================================================
// Hybrid Signatures (ML-DSA-65 + Ed25519)
// ============================================================================

pub use hybrid_sig::{
    generate_hybrid_signing_keypair, generate_hybrid_signing_keypair_with_config, sign_hybrid,
    sign_hybrid_with_config, verify_hybrid_signature, verify_hybrid_signature_with_config,
};

// ============================================================================
// Key Generation (no options needed - creates credentials)
// ============================================================================

pub use keygen::{
    generate_fn_dsa_keypair, generate_fn_dsa_keypair_with_config,
    generate_fn_dsa_keypair_with_level, generate_keypair, generate_keypair_with_config,
    generate_ml_dsa_keypair, generate_ml_dsa_keypair_with_config, generate_ml_kem_keypair,
    generate_ml_kem_keypair_with_config, generate_slh_dsa_keypair,
    generate_slh_dsa_keypair_with_config,
};

// ============================================================================
// Hashing (stateless operations)
// ============================================================================

pub use hashing::{
    derive_key, derive_key_with_config, derive_key_with_info, hash_data, hmac, hmac_check,
    hmac_check_with_config, hmac_with_config,
};

// ============================================================================
// Low-Level Primitives (for advanced use cases)
// ============================================================================

// Ed25519
pub use ed25519::{
    sign_ed25519, sign_ed25519_with_config, verify_ed25519, verify_ed25519_with_config,
};
// ECDSA-P384
pub use ecdsa_p384::{
    ECDSA_P384_SIGNATURE_LEN, generate_ecdsa_p384_keypair, sign_ecdsa_p384, verify_ecdsa_p384,
    verify_ecdsa_p384_prehash, verify_ecdsa_p384_prehash_der,
};

// AES-GCM
pub use aes_gcm::{
    decrypt_aes_gcm, decrypt_aes_gcm_with_config, encrypt_aes_gcm, encrypt_aes_gcm_with_config,
};
pub use aes_gcm::{decrypt_aes_gcm_with_aad, encrypt_aes_gcm_with_aad};

// Post-Quantum KEM (ML-KEM)
pub use pq_kem::{
    decrypt_pq_ml_kem, decrypt_pq_ml_kem_with_config, encrypt_pq_ml_kem,
    encrypt_pq_ml_kem_with_config,
};

// Post-Quantum Signatures (ML-DSA, SLH-DSA, FN-DSA)
pub use pq_sig::{
    sign_pq_fn_dsa, sign_pq_fn_dsa_with_config, sign_pq_ml_dsa, sign_pq_ml_dsa_with_config,
    sign_pq_slh_dsa, sign_pq_slh_dsa_with_config, verify_pq_fn_dsa, verify_pq_fn_dsa_with_config,
    verify_pq_ml_dsa, verify_pq_ml_dsa_with_config, verify_pq_slh_dsa,
    verify_pq_slh_dsa_with_config,
};

// ============================================================================
// Unverified Variants (for low-level primitives)
// ============================================================================

pub use hashing::{
    derive_key_unverified, derive_key_with_config_unverified, derive_key_with_info_unverified,
    hmac_check_unverified, hmac_check_with_config_unverified, hmac_unverified,
    hmac_with_config_unverified,
};

pub use ed25519::{
    sign_ed25519_unverified, sign_ed25519_with_config_unverified, verify_ed25519_unverified,
    verify_ed25519_with_config_unverified,
};

pub use aes_gcm::{
    decrypt_aes_gcm_unverified, decrypt_aes_gcm_with_aad_unverified,
    decrypt_aes_gcm_with_config_unverified, encrypt_aes_gcm_unverified,
    encrypt_aes_gcm_with_aad_unverified, encrypt_aes_gcm_with_config_unverified,
};

pub use pq_kem::{
    decrypt_pq_ml_kem_unverified, decrypt_pq_ml_kem_with_config_unverified,
    encrypt_pq_ml_kem_unverified, encrypt_pq_ml_kem_with_config_unverified,
};

pub use pq_sig::{
    sign_pq_fn_dsa_unverified, sign_pq_fn_dsa_with_config_unverified, sign_pq_ml_dsa_unverified,
    sign_pq_ml_dsa_with_config_unverified, sign_pq_slh_dsa_unverified,
    sign_pq_slh_dsa_with_config_unverified, verify_pq_fn_dsa_unverified,
    verify_pq_fn_dsa_with_config_unverified, verify_pq_ml_dsa_unverified,
    verify_pq_ml_dsa_with_config_unverified, verify_pq_slh_dsa_unverified,
    verify_pq_slh_dsa_with_config_unverified,
};

pub use hybrid_sig::{
    generate_hybrid_signing_keypair_unverified, sign_hybrid_unverified,
    verify_hybrid_signature_unverified,
};
