package database import ( "context" "errors" "time" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" "github.com/noteapp/backend/internal/domain/entities" ) // UserRepository implements the user repository interface type UserRepository struct { collection *mongo.Collection } // NewUserRepository creates a new user repository func NewUserRepository(db *mongo.Database) *UserRepository { return &UserRepository{ collection: db.Collection("users"), } } // CreateUser creates a new user func (r *UserRepository) CreateUser(ctx context.Context, user *entities.User) error { user.ID = bson.NewObjectID() user.CreatedAt = time.Now() user.UpdatedAt = time.Now() _, err := r.collection.InsertOne(ctx, user) return err } // GetUserByID retrieves a user by ID func (r *UserRepository) GetUserByID(ctx context.Context, id bson.ObjectID) (*entities.User, error) { var user entities.User err := r.collection.FindOne(ctx, bson.M{"_id": id}).Decode(&user) if err != nil { if err == mongo.ErrNoDocuments { return nil, errors.New("user not found") } return nil, err } return &user, nil } // GetUserByEmail retrieves a user by email func (r *UserRepository) GetUserByEmail(ctx context.Context, email string) (*entities.User, error) { var user entities.User err := r.collection.FindOne(ctx, bson.M{"email": email}).Decode(&user) if err != nil { if err == mongo.ErrNoDocuments { return nil, errors.New("user not found") } return nil, err } return &user, nil } // GetUserByUsername retrieves a user by username func (r *UserRepository) GetUserByUsername(ctx context.Context, username string) (*entities.User, error) { var user entities.User err := r.collection.FindOne(ctx, bson.M{"username": username}).Decode(&user) if err != nil { if err == mongo.ErrNoDocuments { return nil, errors.New("user not found") } return nil, err } return &user, nil } // UpdateUser updates a user func (r *UserRepository) UpdateUser(ctx context.Context, user *entities.User) error { user.UpdatedAt = time.Now() _, err := r.collection.ReplaceOne(ctx, bson.M{"_id": user.ID}, user) return err } // DeleteUser deletes a user func (r *UserRepository) DeleteUser(ctx context.Context, id bson.ObjectID) error { _, err := r.collection.DeleteOne(ctx, bson.M{"_id": id}) return err } // ListAllUsers retrieves all users sorted by creation date descending func (r *UserRepository) ListAllUsers(ctx context.Context) ([]*entities.User, error) { opts := options.Find().SetSort(bson.D{bson.E{Key: "created_at", Value: -1}}) cursor, err := r.collection.Find(ctx, bson.M{}, opts) if err != nil { return nil, err } defer cursor.Close(ctx) var users []*entities.User if err := cursor.All(ctx, &users); err != nil { return nil, err } return users, nil } // EnsureIndexes creates necessary indexes for users collection func (r *UserRepository) EnsureIndexes(ctx context.Context) error { indexModel := []mongo.IndexModel{ { Keys: bson.D{bson.E{Key: "email", Value: 1}}, Options: options.Index().SetUnique(true), }, { Keys: bson.D{bson.E{Key: "username", Value: 1}}, Options: options.Index().SetUnique(true), }, } _, err := r.collection.Indexes().CreateMany(ctx, indexModel) return err }