package ru.soune.nocopy.handler; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import ru.soune.nocopy.dto.BaseRequest; import ru.soune.nocopy.dto.BaseResponse; import ru.soune.nocopy.dto.MessageCode; import ru.soune.nocopy.dto.user.UserAdditionalInfoBody; import ru.soune.nocopy.entity.user.UserAdditionalInfo; import ru.soune.nocopy.entity.user.UserAdditionalInfoAnswer; import ru.soune.nocopy.entity.user.UserAdditionalInfoListAnswer; import ru.soune.nocopy.exception.UserAdditionalInfoNotFound; import ru.soune.nocopy.service.user.AdditionalInfoService; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @Component @Slf4j @RequiredArgsConstructor public class UserInfoHandler implements RequestHandler { private final AdditionalInfoService additionalInfoService; private final ObjectMapper objectMapper; @Override public BaseResponse handle(BaseRequest request) throws Exception { try { UserAdditionalInfoBody body = objectMapper.convertValue(request.getMessageBody(), UserAdditionalInfoBody.class); log.info("Processing UserInfoHandler with action: {}", body.getAction()); return switch (body.getAction()) { case "getAll" -> getAllAdditionalInfos(request); case "getById" -> getAdditionalInfoById(request, body.getUserId()); case "update" -> updateAdditionalInfo(request, body); case "delete" -> deleteAdditionalInfo(request, body.getUserId()); default -> new BaseResponse( request.getMsgId(), MessageCode.INVALID_ACTION.getCode(), "Invalid action: " + body.getAction(), null ); }; } catch (IllegalArgumentException e) { log.error("Validation error in UserInfoHandler", e); return new BaseResponse( request.getMsgId(), MessageCode.VALIDATION_ERROR.getCode(), e.getMessage(), null); } catch (UserAdditionalInfoNotFound e) { log.error("User additional info not found", e); return new BaseResponse( request.getMsgId(), MessageCode.NOT_FOUND.getCode(), e.getMessage(), null); } catch (Exception e) { log.error("Unexpected error in UserInfoHandler", e); return new BaseResponse( request.getMsgId(), MessageCode.INTERNAL_ERROR.getCode(), "Internal server error: " + e.getMessage(), null); } } private BaseResponse getAllAdditionalInfos(BaseRequest request) { log.info("Getting all additional infos"); List infos = additionalInfoService.getAllAdditionalInfos(); List answerItems = infos.stream() .map(this::convertToAnswer) .collect(Collectors.toList()); UserAdditionalInfoListAnswer listAnswer = UserAdditionalInfoListAnswer.builder() .items(answerItems) .count(answerItems.size()) .build(); return new BaseResponse( request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), listAnswer ); } private BaseResponse getAdditionalInfoById(BaseRequest request, Long userId) { log.info("Getting additional info for user: {}", userId); if (userId == null) { throw new IllegalArgumentException("User ID is required for getById action"); } UserAdditionalInfo info = additionalInfoService.getAdditionalInfoByUser(userId); if (info == null) { throw new UserAdditionalInfoNotFound( String.format("User additional info not found for userId: %d", userId) ); } UserAdditionalInfoAnswer answer = convertToAnswer(info); return new BaseResponse( request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), answer ); } private BaseResponse updateAdditionalInfo(BaseRequest request, UserAdditionalInfoBody body) { log.info("Updating additional info for user: {}", body.getUserId()); if (body.getUserId() == null) { throw new IllegalArgumentException("User ID is required for update action"); } validateIpAddress(body.getIpAddress()); validateUserAgent(body.getUserAgent()); Optional updatedInfo = additionalInfoService.updateAdditionalInfo( body.getUserId(), body.getIpAddress(), body.getUserAgent() ); if (updatedInfo.isEmpty()) { throw new UserAdditionalInfoNotFound( String.format("User additional info not found for userId: %d", body.getUserId()) ); } UserAdditionalInfoAnswer answer = convertToAnswer(updatedInfo.get()); return new BaseResponse( request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), answer ); } private BaseResponse deleteAdditionalInfo(BaseRequest request, Long userId) { log.info("Deleting additional info for user: {}", userId); if (userId == null) { throw new IllegalArgumentException("User ID is required for delete action"); } UserAdditionalInfo existingInfo = additionalInfoService.getAdditionalInfoByUser(userId); if (existingInfo == null) { throw new UserAdditionalInfoNotFound( String.format("User additional info not found for userId: %d", userId) ); } additionalInfoService.deleteAdditionalInfo(userId); return new BaseResponse( request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), Map.of("deleted", true, "user_id", userId) ); } private UserAdditionalInfoAnswer convertToAnswer(UserAdditionalInfo info) { return UserAdditionalInfoAnswer.builder() .id(info.getId()) .userId(info.getUser() != null ? info.getUser().getId() : null) .ipAddress(info.getIpAddress()) .userAgent(info.getUserAgent()) .registrationDate(info.getRegistrationDate()) .build(); } private void validateIpAddress(String ip) { if (ip == null || ip.trim().isEmpty()) { throw new IllegalArgumentException("IP address is required for update action"); } String ipv4Pattern = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"; if (!ip.trim().matches(ipv4Pattern)) { log.warn("Invalid IP address format: {}", ip); throw new IllegalArgumentException("Invalid IP address format"); } } private void validateUserAgent(String userAgent) { if (userAgent == null || userAgent.trim().isEmpty()) { throw new IllegalArgumentException("User agent is required for update action"); } if (userAgent.length() > 500) { throw new IllegalArgumentException("User agent must not exceed 500 characters"); } } }