use async_trait::async_trait; use bson::oid::ObjectId; use crate::models::user::User; // Define custom error type #[derive(Debug)] pub enum UserError { MongoError(mongodb::error::Error), NotFound, ValidationError(String), DuplicateKey(String), } impl std::fmt::Display for UserError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { UserError::MongoError(e) => write!(f, "MongoDB error: {}", e), UserError::NotFound => write!(f, "User not found"), UserError::ValidationError(msg) => write!(f, "Validation error: {}", msg), UserError::DuplicateKey(field) => write!(f, "Duplicate key error: {}", field), } } } impl std::error::Error for UserError {} impl From for UserError { fn from(error: mongodb::error::Error) -> Self { UserError::MongoError(error) } } // Repository trait #[async_trait] pub trait UserRepository { async fn create(&self, user: User) -> Result; async fn get(&self, id: ObjectId) -> Result; async fn update(&self, id: ObjectId, user: User) -> Result; async fn delete(&self, id: ObjectId) -> Result<(), UserError>; async fn list(&self, limit: Option, skip: Option) -> Result, UserError>; async fn search(&self, query: String) -> Result, UserError>; async fn count(&self) -> Result; async fn count_by_name(&self, name: String) -> Result; async fn count_by_email(&self, email: String) -> Result; async fn count_by_phone(&self, phone: String) -> Result; async fn count_by_id(&self, id: ObjectId) -> Result; async fn find_by_email(&self, email: String) -> Result, UserError>; async fn find_by_username(&self, username: String) -> Result, UserError>; async fn exists_by_email(&self, email: String) -> Result; async fn exists_by_username(&self, username: String) -> Result; async fn get_active_users(&self) -> Result, UserError>; async fn get_users_by_role(&self, role: String) -> Result, UserError>; }