use async_trait::async_trait;
use pbbson::Model;

#[async_trait]
#[allow(unused)]
pub trait TokenFactory {
    async fn create_access_token(&self, access_token: Model) -> Result<Model, Box<dyn std::error::Error>>;

    async fn create_access_and_refresh_tokens(
        &self,
        access_token: Model,
        refresh_token: Model,
    ) -> Result<(Model, Model), Box<dyn std::error::Error>>;
}

#[derive(Default)]
pub struct XidTokenFactory {}

#[async_trait]
impl TokenFactory for XidTokenFactory {
    async fn create_access_token(&self, mut access_token: Model) -> Result<Model, Box<dyn std::error::Error>> {
        if let Err(_e) = access_token.id() {
            access_token.insert("id", xid::new().to_string());
        }
        Ok(access_token)
    }

    async fn create_access_and_refresh_tokens(
        &self,
        access_token: Model,
        mut refresh_token: Model,
    ) -> Result<(Model, Model), Box<dyn std::error::Error>> {
        let access_token = self.create_access_token(access_token).await?;
        if let Err(_e) = refresh_token.id() {
            refresh_token.insert("id", xid::new().to_string());
        }
        Ok((access_token, refresh_token))
    }
}
