//! Core traits for cryptographic operations.
//!
//! Defines zero-trust authentication, proof-of-possession, continuous
//! verification, and scheme-selection interfaces. All traits are pure Rust
//! with zero FFI dependencies.
//!
//! # Historical note
//!
//! Earlier revisions of this module defined a much broader catalogue of
//! generic traits (`Encryptable`, `Decryptable`, `Signable`, `Verifiable`,
//! `KeyDerivable`, `AsyncEncryptable`, ..., `HardwareAware`,
//! `HardwareAccelerator`, ...). None of them had any implementors in the
//! crate, and they diverged from the actually-used APIs exposed by
//! [`primitives`](crate::primitives) and [`unified_api`](crate::unified_api).
//! They were removed as part of the design-pattern consistency cleanup
//! (P4.1). The traits below are the only ones that currently have live
//! implementors.

// Traits use `std::result::Result<T, Self::Error>` with generic associated error types,
// which cannot use the crate's `Result<T>` alias (fixed to `TypeError`).
#![allow(unused_qualifications)]

use crate::types::types::CryptoContext;

/// Trait for zero-trust authentication with challenge-response proofs.
pub trait ZeroTrustAuthenticable {
    /// The proof type generated by this authenticator.
    type Proof;
    /// The error type for authentication failures.
    type Error;

    /// Generates a proof for the given challenge.
    ///
    /// # Errors
    /// Returns an error if proof generation fails (implementation-defined).
    fn generate_proof(&self, challenge: &[u8]) -> std::result::Result<Self::Proof, Self::Error>;

    /// Verifies a proof against the given challenge.
    ///
    /// # Errors
    /// Returns an error if verification fails (implementation-defined).
    fn verify_proof(
        &self,
        proof: &Self::Proof,
        challenge: &[u8],
    ) -> std::result::Result<bool, Self::Error>;
}

/// Trait for proof-of-possession verification.
pub trait ProofOfPossession {
    /// The proof-of-possession type.
    type Pop;
    /// The error type for PoP operations.
    type Error;

    /// Generates a proof of possession.
    ///
    /// # Errors
    /// Returns an error if PoP generation fails (implementation-defined).
    fn generate_pop(&self) -> std::result::Result<Self::Pop, Self::Error>;

    /// Verifies a proof of possession.
    ///
    /// # Errors
    /// Returns an error if verification fails (implementation-defined).
    fn verify_pop(&self, pop: &Self::Pop) -> std::result::Result<bool, Self::Error>;
}

/// Trait for continuous session verification.
pub trait ContinuousVerifiable {
    /// The error type for verification failures.
    type Error;

    /// Checks the current verification status of the session.
    ///
    /// # Errors
    /// Returns an error if status check fails (implementation-defined).
    fn verify_continuously(&self) -> std::result::Result<VerificationStatus, Self::Error>;

    /// Performs reauthentication to refresh the session.
    ///
    /// # Errors
    /// Returns an error if reauthentication fails (implementation-defined).
    fn reauthenticate(&self) -> std::result::Result<(), Self::Error>;
}

/// Status of continuous verification.
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(kani, derive(kani::Arbitrary))]
pub enum VerificationStatus {
    /// Session is verified and valid.
    Verified,
    /// Session has expired.
    Expired,
    /// Verification failed.
    Failed,
    /// Verification is pending.
    Pending,
}

impl VerificationStatus {
    /// Returns `true` if the status is [`Verified`](VerificationStatus::Verified).
    #[must_use]
    pub fn is_verified(&self) -> bool {
        matches!(self, Self::Verified)
    }
}

// Formal verification with Kani
#[cfg(kani)]
mod kani_proofs {
    use super::*;

    /// Proves is_verified() returns true IFF status is Verified.
    /// Security: expired/failed/pending sessions must never be "verified".
    #[kani::proof]
    fn verification_status_is_verified_iff_verified() {
        let status: VerificationStatus = kani::any();
        let method = status.is_verified();
        let expected = matches!(status, VerificationStatus::Verified);
        kani::assert(method == expected, "is_verified() iff Verified variant");
    }
}

/// Type of hardware accelerator.
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum HardwareType {
    /// CPU with SIMD extensions.
    Cpu,
    /// GPU acceleration.
    Gpu,
    /// FPGA acceleration.
    Fpga,
    /// TPM hardware security module.
    Tpu,
    /// Intel SGX enclave.
    Sgx,
}

/// Information about available hardware.
#[derive(Debug, Clone)]
pub struct HardwareInfo {
    /// List of available hardware accelerators.
    pub available_accelerators: Vec<HardwareType>,
    /// Preferred accelerator based on capabilities.
    pub preferred_accelerator: Option<HardwareType>,
    /// Hardware capabilities.
    pub capabilities: HardwareCapabilities,
}

/// Hardware capability information.
#[derive(Debug, Clone)]
pub struct HardwareCapabilities {
    /// Whether SIMD instructions are supported.
    pub simd_support: bool,
    /// Whether AES-NI instructions are available.
    pub aes_ni: bool,
    /// Number of available threads.
    pub threads: usize,
    /// Available memory in bytes.
    pub memory: usize,
}

impl HardwareInfo {
    /// Returns the best available accelerator, preferring the configured preference.
    #[must_use]
    pub fn best_accelerator(&self) -> Option<&HardwareType> {
        self.preferred_accelerator.as_ref().or_else(|| self.available_accelerators.first())
    }

    /// Returns a human-readable summary of the hardware info.
    #[must_use]
    pub fn summary(&self) -> String {
        format!(
            "Available: {:?}, Preferred: {:?}, Capabilities: {:?}",
            self.available_accelerators, self.preferred_accelerator, self.capabilities
        )
    }
}

/// Trait for cryptographic scheme selection.
pub trait SchemeSelector {
    /// The error type for selection failures.
    type Error;

    /// Selects an encryption scheme based on data and context.
    ///
    /// # Errors
    /// Returns an error if scheme selection fails (implementation-defined).
    fn select_encryption_scheme(
        &self,
        data: &[u8],
        ctx: &CryptoContext,
    ) -> std::result::Result<String, Self::Error>;

    /// Selects a signature scheme based on context.
    ///
    /// # Errors
    /// Returns an error if scheme selection fails (implementation-defined).
    fn select_signature_scheme(
        &self,
        ctx: &CryptoContext,
    ) -> std::result::Result<String, Self::Error>;

    /// Analyzes characteristics of the input data.
    fn analyze_data_characteristics(&self, data: &[u8]) -> DataCharacteristics;
}

/// Characteristics of data for scheme selection.
#[derive(Debug, Clone)]
pub struct DataCharacteristics {
    /// Size of the data in bytes.
    pub size: usize,
    /// Estimated entropy (0.0 to 8.0 bits per byte).
    pub entropy: f64,
    /// Detected pattern type.
    pub pattern_type: PatternType,
}

/// Type of pattern detected in data.
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum PatternType {
    /// High-entropy random data.
    Random,
    /// Data with detectable structure.
    Structured,
    /// Data with repetitive patterns.
    Repetitive,
    /// Human-readable text.
    Text,
    /// Binary data without clear patterns.
    Binary,
}
