//! Token manager trait definitions.
//!
//! Provides a trait abstraction for token management, enabling:
//! - Testing with mock implementations
//! - Platform-specific implementations
//! - Dependency injection patterns

use async_trait::async_trait;

use crate::error::LastIDError;

/// Token manager trait for OAuth 2.0 authentication with `DPoP`.
///
/// This trait abstracts token management operations, enabling mock
/// implementations for testing and ensuring consistency with other SDK traits
/// like `IdpClient` and `TrustRegistry`.
///
/// # Example
///
/// ```rust,ignore
/// use lastid_sdk::auth::TokenManagerTrait;
///
/// async fn get_auth_token(manager: &impl TokenManagerTrait) -> Result<String, LastIDError> {
///     manager.get_token().await
/// }
/// ```
#[cfg(not(target_arch = "wasm32"))]
#[async_trait]
pub trait TokenManagerTrait: Send + Sync {
    /// Get a valid access token, acquiring or refreshing as needed.
    ///
    /// If a cached token exists and is not expired, returns it.
    /// Otherwise, acquires a new token from the IDP.
    ///
    /// # Returns
    ///
    /// The Bearer access token string.
    ///
    /// # Errors
    ///
    /// * `LastIDError::Http` - Token acquisition failed
    /// * `LastIDError::Crypto` - `DPoP` proof generation failed
    async fn get_token(&self) -> Result<String, LastIDError>;

    /// Create a `DPoP` proof for a specific request.
    ///
    /// # Arguments
    ///
    /// * `method` - HTTP method (GET, POST, etc.)
    /// * `url` - Full request URL
    /// * `access_token` - Optional access token for ath claim binding
    ///
    /// # Errors
    ///
    /// Returns `LastIDError::Crypto` if proof generation fails.
    fn create_dpop_proof(
        &self,
        method: &str,
        url: &str,
        access_token: Option<&str>,
    ) -> Result<String, LastIDError>;

    /// Get the `DPoP` public key as JWK.
    fn public_jwk(&self) -> serde_json::Value;

    /// Get the JWK thumbprint of the `DPoP` key.
    fn thumbprint(&self) -> &str;
}

/// Token manager trait for WASM (single-threaded, no Send + Sync).
#[cfg(target_arch = "wasm32")]
#[async_trait(?Send)]
pub trait TokenManagerTrait {
    /// Get a valid access token, acquiring or refreshing as needed.
    ///
    /// If a cached token exists and is not expired, returns it.
    /// Otherwise, acquires a new token from the IDP.
    ///
    /// # Returns
    ///
    /// The Bearer access token string.
    ///
    /// # Errors
    ///
    /// * `LastIDError::Http` - Token acquisition failed
    /// * `LastIDError::Crypto` - `DPoP` proof generation failed
    async fn get_token(&self) -> Result<String, LastIDError>;

    /// Create a `DPoP` proof for a specific request.
    ///
    /// # Arguments
    ///
    /// * `method` - HTTP method (GET, POST, etc.)
    /// * `url` - Full request URL
    /// * `access_token` - Optional access token for ath claim binding
    ///
    /// # Errors
    ///
    /// Returns `LastIDError::Crypto` if proof generation fails.
    fn create_dpop_proof(
        &self,
        method: &str,
        url: &str,
        access_token: Option<&str>,
    ) -> Result<String, LastIDError>;

    /// Get the `DPoP` public key as JWK.
    fn public_jwk(&self) -> serde_json::Value;

    /// Get the JWK thumbprint of the `DPoP` key.
    fn thumbprint(&self) -> &str;
}
