package repositories import ( "errors" "fmt" "attune-heart-therapy/internal/models" "gorm.io/gorm" ) // userRepository implements the UserRepository interface type userRepository struct { db *gorm.DB } // NewUserRepository creates a new instance of UserRepository func NewUserRepository(db *gorm.DB) UserRepository { return &userRepository{ db: db, } } // Create creates a new user in the database func (r *userRepository) Create(user *models.User) error { if user == nil { return errors.New("user cannot be nil") } if err := r.db.Create(user).Error; err != nil { if errors.Is(err, gorm.ErrDuplicatedKey) { return fmt.Errorf("user with email %s already exists", user.Email) } return fmt.Errorf("failed to create user: %w", err) } return nil } // GetByID retrieves a user by their ID func (r *userRepository) GetByID(id uint) (*models.User, error) { if id == 0 { return nil, errors.New("invalid user ID") } var user models.User if err := r.db.First(&user, id).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, fmt.Errorf("user with ID %d not found", id) } return nil, fmt.Errorf("failed to get user by ID: %w", err) } return &user, nil } // GetByEmail retrieves a user by their email address func (r *userRepository) GetByEmail(email string) (*models.User, error) { if email == "" { return nil, errors.New("email cannot be empty") } var user models.User if err := r.db.Where("email = ?", email).First(&user).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, fmt.Errorf("user with email %s not found", email) } return nil, fmt.Errorf("failed to get user by email: %w", err) } return &user, nil } // Update updates an existing user in the database func (r *userRepository) Update(user *models.User) error { if user == nil { return errors.New("user cannot be nil") } if user.ID == 0 { return errors.New("user ID is required for update") } // Check if user exists var existingUser models.User if err := r.db.First(&existingUser, user.ID).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return fmt.Errorf("user with ID %d not found", user.ID) } return fmt.Errorf("failed to check user existence: %w", err) } // Update the user if err := r.db.Save(user).Error; err != nil { if errors.Is(err, gorm.ErrDuplicatedKey) { return fmt.Errorf("user with email %s already exists", user.Email) } return fmt.Errorf("failed to update user: %w", err) } return nil } // GetActiveUsersCount returns the count of active (non-deleted) users func (r *userRepository) GetActiveUsersCount() (int64, error) { var count int64 if err := r.db.Model(&models.User{}).Count(&count).Error; err != nil { return 0, fmt.Errorf("failed to get active users count: %w", err) } return count, nil } // GetAllUsers retrieves all users with pagination func (r *userRepository) GetAllUsers(limit, offset int) ([]models.User, int64, error) { var users []models.User var total int64 // Get total count if err := r.db.Model(&models.User{}).Count(&total).Error; err != nil { return nil, 0, fmt.Errorf("failed to get users count: %w", err) } // Get users with pagination if err := r.db.Limit(limit).Offset(offset).Order("created_at DESC").Find(&users).Error; err != nil { return nil, 0, fmt.Errorf("failed to get users: %w", err) } // Clear password hashes for security for i := range users { users[i].PasswordHash = "" } return users, total, nil }