package sqlite import ( "context" "database/sql" "fmt" "messenger/internal/models" //"time" ) type UserRepository struct { db *DB } func NewUserRepository(db *DB) *UserRepository { return &UserRepository{db: db} } func (r *UserRepository) Create(ctx context.Context, user *models.User) error { query := ` INSERT INTO users (login, password_hash, role, created_at) VALUES (?, ?, ?, ?) RETURNING id ` err := r.db.QueryRowContext(ctx, query, user.Login, user.PasswordHash, user.Role, user.CreatedAt).Scan(&user.ID) if err != nil { return fmt.Errorf("failed to create user: %w", err) } return nil } func (r *UserRepository) FindByID(ctx context.Context, id int64) (*models.User, error) { query := ` SELECT id, login, password_hash, role, last_seen, created_at FROM users WHERE id = ? ` var user models.User var lastSeen sql.NullTime err := r.db.QueryRowContext(ctx, query, id).Scan( &user.ID, &user.Login, &user.PasswordHash, &user.Role, &lastSeen, &user.CreatedAt, ) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, fmt.Errorf("failed to find user by id: %w", err) } if lastSeen.Valid { user.LastSeen = &lastSeen.Time } return &user, nil } func (r *UserRepository) FindByLogin(ctx context.Context, login string) (*models.User, error) { query := ` SELECT id, login, password_hash, role, last_seen, created_at FROM users WHERE login = ? ` var user models.User var lastSeen sql.NullTime err := r.db.QueryRowContext(ctx, query, login).Scan( &user.ID, &user.Login, &user.PasswordHash, &user.Role, &lastSeen, &user.CreatedAt, ) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, fmt.Errorf("failed to find user by login: %w", err) } if lastSeen.Valid { user.LastSeen = &lastSeen.Time } return &user, nil } func (r *UserRepository) SearchByLogin(ctx context.Context, query string, limit int) ([]*models.User, error) { sqlQuery := ` SELECT id, login, role, last_seen, created_at FROM users WHERE login LIKE ? || '%' ORDER BY login LIMIT ? ` rows, err := r.db.QueryContext(ctx, sqlQuery, query, limit) if err != nil { return nil, fmt.Errorf("failed to search users: %w", err) } defer rows.Close() var users []*models.User for rows.Next() { var user models.User var lastSeen sql.NullTime err := rows.Scan(&user.ID, &user.Login, &user.Role, &lastSeen, &user.CreatedAt) if err != nil { return nil, fmt.Errorf("failed to scan user: %w", err) } if lastSeen.Valid { user.LastSeen = &lastSeen.Time } users = append(users, &user) } return users, nil } func (r *UserRepository) UpdateLastSeen(ctx context.Context, userID int64) error { query := `UPDATE users SET last_seen = CURRENT_TIMESTAMP WHERE id = ?` result, err := r.db.ExecContext(ctx, query, userID) if err != nil { return fmt.Errorf("failed to update last_seen: %w", err) } rows, err := result.RowsAffected() if err != nil { return err } if rows == 0 { return fmt.Errorf("user not found: %d", userID) } return nil } func (r *UserRepository) UpdateRole(ctx context.Context, userID int64, role models.UserRole) error { query := `UPDATE users SET role = ? WHERE id = ?` result, err := r.db.ExecContext(ctx, query, role, userID) if err != nil { return fmt.Errorf("failed to update role: %w", err) } rows, err := result.RowsAffected() if err != nil { return err } if rows == 0 { return fmt.Errorf("user not found: %d", userID) } return nil } func (r *UserRepository) Delete(ctx context.Context, userID int64) error { query := `DELETE FROM users WHERE id = ?` result, err := r.db.ExecContext(ctx, query, userID) if err != nil { return fmt.Errorf("failed to delete user: %w", err) } rows, err := result.RowsAffected() if err != nil { return err } if rows == 0 { return fmt.Errorf("user not found: %d", userID) } return nil } func (r *UserRepository) Exists(ctx context.Context, login string) (bool, error) { query := `SELECT EXISTS(SELECT 1 FROM users WHERE login = ?)` var exists bool err := r.db.QueryRowContext(ctx, query, login).Scan(&exists) if err != nil { return false, fmt.Errorf("failed to check user existence: %w", err) } return exists, nil }