use super::super::models::user::*;
use std::future::Future;

pub trait UserRepository: Clone + Send + Sync + 'static {
    // Create
    fn create_user(
        &self,
        req: CreateUserRequest,
    ) -> impl Future<Output = Result<User, CreateUserError>> + Send;

    fn create_activation_token(
        &self,
        ent: &User,
    ) -> impl Future<Output = Result<ActivationToken, anyhow::Error>> + Send;

    fn create_password_reset_token(
        &self,
        ent: &User,
    ) -> impl Future<Output = Result<PasswordResetToken, anyhow::Error>> + Send;

    // Read
    fn all_users(&self) -> impl Future<Output = Vec<User>> + Send;

    fn find_user_by_id(
        &self,
        id: uuid::Uuid,
    ) -> impl Future<Output = Result<Option<User>, anyhow::Error>> + Send;

    fn find_user_by_email(
        &self,
        email: &EmailAddress,
    ) -> impl Future<Output = Result<Option<User>, anyhow::Error>> + Send;

    fn find_user_by_activation_token(
        &self,
        token: &ActivationToken,
    ) -> impl Future<Output = Result<Option<User>, anyhow::Error>> + Send;

    fn find_user_by_password_reset_token(
        &self,
        token: &PasswordResetToken,
    ) -> impl Future<Output = Result<Option<User>, anyhow::Error>> + Send;

    // // Update
    fn update_user(
        &self,
        ent: &User,
        req: UpdateUserRequest,
    ) -> impl Future<Output = Result<(User, User), UpdateUserError>> + Send;

    // Delete
    // fn delete_user(&self, ent: User) -> impl Future<Output = Result<User, DeleteUserError>> + Send;
    fn delete_activation_token_for_user(
        &self,
        ent: &User,
    ) -> impl Future<Output = Result<(), anyhow::Error>> + Send;

    fn delete_password_reset_tokens_for_user(
        &self,
        ent: &User,
    ) -> impl Future<Output = Result<(), anyhow::Error>> + Send;
}
