package postgres import ( "context" "database/sql" "counter/internal/domain/entities" "counter/internal/domain/repositories" ) // UserRepository implements the UserRepository interface for PostgreSQL type UserRepository struct { db *sql.DB } // NewUserRepository creates a new user repository func NewUserRepository(db *sql.DB) repositories.UserRepository { return &UserRepository{db: db} } // Create creates a new user func (r *UserRepository) Create(ctx context.Context, user *entities.User) error { query := ` INSERT INTO users (username, email, password) VALUES ($1, $2, $3) RETURNING id, created_at, updated_at ` err := r.db.QueryRowContext(ctx, query, user.Username, user.Email, user.Password). Scan(&user.ID, &user.CreatedAt, &user.UpdatedAt) if err != nil { return err } return nil } // FindByID finds a user by ID func (r *UserRepository) FindByID(ctx context.Context, id int) (*entities.User, error) { query := ` SELECT id, username, email, password, created_at, updated_at FROM users WHERE id = $1 ` user := &entities.User{} err := r.db.QueryRowContext(ctx, query, id). Scan(&user.ID, &user.Username, &user.Email, &user.Password, &user.CreatedAt, &user.UpdatedAt) if err == sql.ErrNoRows { return nil, entities.ErrUserNotFound } if err != nil { return nil, err } return user, nil } // FindByUsername finds a user by username func (r *UserRepository) FindByUsername(ctx context.Context, username string) (*entities.User, error) { query := ` SELECT id, username, email, password, created_at, updated_at FROM users WHERE username = $1 ` user := &entities.User{} err := r.db.QueryRowContext(ctx, query, username). Scan(&user.ID, &user.Username, &user.Email, &user.Password, &user.CreatedAt, &user.UpdatedAt) if err == sql.ErrNoRows { return nil, entities.ErrUserNotFound } if err != nil { return nil, err } return user, nil } // FindByEmail finds a user by email func (r *UserRepository) FindByEmail(ctx context.Context, email string) (*entities.User, error) { query := ` SELECT id, username, email, password, created_at, updated_at FROM users WHERE email = $1 ` user := &entities.User{} err := r.db.QueryRowContext(ctx, query, email). Scan(&user.ID, &user.Username, &user.Email, &user.Password, &user.CreatedAt, &user.UpdatedAt) if err == sql.ErrNoRows { return nil, entities.ErrUserNotFound } if err != nil { return nil, err } return user, nil } // Update updates a user func (r *UserRepository) Update(ctx context.Context, user *entities.User) error { query := ` UPDATE users SET username = $1, email = $2, password = $3, updated_at = CURRENT_TIMESTAMP WHERE id = $4 RETURNING updated_at ` err := r.db.QueryRowContext(ctx, query, user.Username, user.Email, user.Password, user.ID). Scan(&user.UpdatedAt) if err == sql.ErrNoRows { return entities.ErrUserNotFound } if err != nil { return err } return nil } // Delete deletes a user func (r *UserRepository) Delete(ctx context.Context, id int) error { query := `DELETE FROM users WHERE id = $1` result, err := r.db.ExecContext(ctx, query, id) if err != nil { return err } rowsAffected, err := result.RowsAffected() if err != nil { return err } if rowsAffected == 0 { return entities.ErrUserNotFound } return nil }