//! The `TokenProvider` trait and concrete implementations.

use std::sync::Arc;

use chrono::{DateTime, Utc};

#[cfg(any(test, feature = "oauth-token-provider"))]
pub mod oauth;
mod renewing;

pub use renewing::RenewingTokenProvider;

/// A `TokenProvider` is something that, when invoked, gives a valid, unexpired access token.
#[cfg_attr(any(test, feature = "mocks"), mockall::automock)]
#[async_trait::async_trait]
pub trait TokenProvider: Send + Sync {
    /// Returns new JWT-formatted access token.
    async fn get_token(&self) -> anyhow::Result<Arc<Token>>;
}

/// A access token and its expiry.
#[derive(Clone)]
#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
pub struct Token {
    /// The JWT-formatted token.
    pub token: String,

    /// The token's expiry.
    pub expiry: DateTime<Utc>,
}

impl Default for Token {
    fn default() -> Self {
        Self {
            token: Default::default(),
            expiry: DateTime::from_utc(chrono::NaiveDateTime::from_timestamp(0, 0), Utc),
        }
    }
}

impl AsRef<str> for Token {
    fn as_ref(&self) -> &str {
        &self.token
    }
}
