package com.example.demo.service; import com.example.demo.dto.UserStatsResponse; import com.example.demo.exception.DuplicateEmailException; import com.example.demo.exception.ResourceNotFoundException; import com.example.demo.model.User; import org.springframework.stereotype.Service; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; @Service public class UserService { private final List users = new CopyOnWriteArrayList<>(); private final AtomicLong idGenerator = new AtomicLong(1); public UserService() { users.add(new User(idGenerator.getAndIncrement(), "Alice Chen", "alice@example.com", 25)); users.add(new User(idGenerator.getAndIncrement(), "Brandon Li", "brandon@example.com", 30)); users.add(new User(idGenerator.getAndIncrement(), "Carol Wang", "carol@example.com", 28)); } public List findAll() { return users.stream() .sorted((left, right) -> Long.compare(left.getId(), right.getId())) .collect(Collectors.toList()); } public User findById(Long id) { return users.stream() .filter(user -> user.getId().equals(id)) .findFirst() .orElseThrow(() -> new ResourceNotFoundException("User not found: id=" + id)); } public List search(String keyword) { if (keyword == null || keyword.isBlank()) { return findAll(); } String normalizedKeyword = keyword.trim().toLowerCase(); return users.stream() .filter(user -> user.getName().toLowerCase().contains(normalizedKeyword) || user.getEmail().toLowerCase().contains(normalizedKeyword)) .sorted((left, right) -> Long.compare(left.getId(), right.getId())) .collect(Collectors.toList()); } public User create(User user) { ensureEmailAvailable(user.getEmail(), null); User normalized = normalize(user, idGenerator.getAndIncrement()); users.add(normalized); return normalized; } public User update(Long id, User user) { findById(id); ensureEmailAvailable(user.getEmail(), id); User normalized = normalize(user, id); for (int index = 0; index < users.size(); index++) { if (users.get(index).getId().equals(id)) { users.set(index, normalized); return normalized; } } throw new ResourceNotFoundException("User not found: id=" + id); } public void delete(Long id) { boolean removed = users.removeIf(user -> user.getId().equals(id)); if (!removed) { throw new ResourceNotFoundException("User not found: id=" + id); } } public UserStatsResponse getStats() { long totalUsers = users.size(); long adults = users.stream().filter(user -> user.getAge() >= 18).count(); long underThirty = users.stream().filter(user -> user.getAge() < 30).count(); double averageAge = users.stream() .mapToInt(User::getAge) .average() .orElse(0.0); return new UserStatsResponse(totalUsers, adults, underThirty, averageAge); } private void ensureEmailAvailable(String email, Long currentUserId) { String normalizedEmail = email == null ? "" : email.trim().toLowerCase(); boolean exists = users.stream() .anyMatch(user -> user.getEmail().equalsIgnoreCase(normalizedEmail) && (currentUserId == null || !user.getId().equals(currentUserId))); if (exists) { throw new DuplicateEmailException("A user with email " + normalizedEmail + " already exists."); } } private User normalize(User user, Long id) { return new User( id, user.getName().trim(), user.getEmail().trim().toLowerCase(), user.getAge() ); } }