use indieweb::standards::indieauth::{ClientId, RedirectUri, Scopes};
use url::Url;

/// Authorization code data stored by the server
#[allow(dead_code)]
#[derive(Clone, Debug)]
pub struct AuthorizationCode {
    pub code: String,
    pub client_id: ClientId,
    pub redirect_uri: RedirectUri,
    pub code_challenge: String,
    pub code_challenge_method: String,
    pub me: Option<Url>,
    pub scope: Scopes,
    pub created_at: std::time::Instant,
    pub expires_at: std::time::Instant,
}

/// Access token data stored by the server
#[allow(dead_code)]
#[derive(Clone, Debug)]
pub struct AccessToken {
    pub token: String,
    pub me: Url,
    pub scope: Scopes,
    pub client_id: ClientId,
    pub issued_at: std::time::Instant,
    pub expires_at: std::time::Instant,
}

/// Claims for JWT tokens
#[derive(Debug, Clone)]
pub struct TokenClaims {
    pub me: Url,
    pub scope: Scopes,
    pub client_id: ClientId,
    pub issued_at: u64,
    pub expires_at: u64,
}

impl AuthorizationCode {
    pub fn new(
        code: String,
        client_id: ClientId,
        redirect_uri: RedirectUri,
        code_challenge: String,
        code_challenge_method: String,
        me: Option<Url>,
        scope: Scopes,
        expires_in: std::time::Duration,
    ) -> Self {
        let now = std::time::Instant::now();
        Self {
            code,
            client_id,
            redirect_uri,
            code_challenge,
            code_challenge_method,
            me,
            scope,
            created_at: now,
            expires_at: now + expires_in,
        }
    }

    pub fn is_expired(&self) -> bool {
        std::time::Instant::now() >= self.expires_at
    }
}

impl AccessToken {
    pub fn new(
        token: String,
        me: Url,
        scope: Scopes,
        client_id: ClientId,
        expires_in: std::time::Duration,
    ) -> Self {
        let now = std::time::Instant::now();
        Self {
            token,
            me,
            scope,
            client_id,
            issued_at: now,
            expires_at: now + expires_in,
        }
    }

    pub fn is_expired(&self) -> bool {
        std::time::Instant::now() >= self.expires_at
    }
}
