package ru.soune.nocopy.handler; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; 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.tokenoperation.TokenOperationPageDto; import ru.soune.nocopy.dto.tokenoperation.TokenOperationRequest; import ru.soune.nocopy.entity.tokenoperation.OperationType; import ru.soune.nocopy.entity.tokenoperation.TokenOperation; import ru.soune.nocopy.service.register.AuthService; import ru.soune.nocopy.service.tokenoperation.TokenOperationService; import java.util.HashMap; import java.util.Map; @Slf4j @Component @RequiredArgsConstructor public class TokenOperationHandler implements RequestHandler { private final TokenOperationService tokenOperationService; private final ObjectMapper objectMapper; private final AuthService authService; @Override public BaseResponse handle(BaseRequest request) throws Exception { log.info("Handling TokenOperation request: msg_id={}, version={}", request.getMsgId(), request.getVersion()); try { TokenOperationRequest tokenRequest = objectMapper.convertValue( request.getMessageBody(), TokenOperationRequest.class ); String action = tokenRequest.getAction(); if (action == null) { return new BaseResponse( request.getMsgId(), MessageCode.INVALID_ACTION.getCode(), MessageCode.INVALID_ACTION.getDescription(), Map.of("error", "Action is required") ); } switch (action.toLowerCase()) { case "get_list": return handleGetList(request.getMsgId(), tokenRequest); case "get_by_id": return handleGetById(request.getMsgId(), tokenRequest); case "get_by_user": return handleGetByUser(request.getMsgId(), tokenRequest); case "create": return handleCreate(request.getMsgId(), tokenRequest); case "update": return handleUpdate(request.getMsgId(), tokenRequest); case "delete": return handleDelete(request.getMsgId(), tokenRequest); case "delete_all_by_user": return handleDeleteAllByUser(request.getMsgId(), tokenRequest); case "get_stats": return handleGetStats(request.getMsgId(), tokenRequest); case "filter": return handleFilter(request.getMsgId(), tokenRequest); default: return new BaseResponse( request.getMsgId(), MessageCode.INVALID_ACTION.getCode(), MessageCode.INVALID_ACTION.getDescription(), Map.of("available_actions", "get_list, get_by_id, get_by_user, create, update, " + "delete, delete_all_by_user, get_stats, filter") ); } } catch (Exception e) { log.error("Error handling TokenOperation request", e); return new BaseResponse( request.getMsgId(), MessageCode.INTERNAL_ERROR.getCode(), MessageCode.INTERNAL_ERROR.getDescription(), Map.of("error", e.getMessage()) ); } } private BaseResponse handleGetList(Integer msgId, TokenOperationRequest request) { if (request.getToken() == null) { return new BaseResponse( msgId, MessageCode.USER_NOT_FOUND.getCode(), MessageCode.USER_NOT_FOUND.getDescription(), Map.of("error", "User ID is required") ); } Long userId = authService.useUserAuthToken(request.getToken()); try { Page page = tokenOperationService.findByUserId( userId, request.getPage() != null ? request.getPage() : 0, request.getSize() != null ? request.getSize() : 20 ); TokenOperationPageDto pageDto = TokenOperationPageDto.builder() .content(page.getContent()) .pageNumber(page.getNumber()) .pageSize(page.getSize()) .totalElements(page.getTotalElements()) .totalPages(page.getTotalPages()) .last(page.isLast()) .first(page.isFirst()) .build(); Map responseData = new HashMap<>(); responseData.put("operations", pageDto); responseData.put("total_elements", page.getTotalElements()); responseData.put("total_pages", page.getTotalPages()); responseData.put("current_page", page.getNumber()); responseData.put("page_size", page.getSize()); return new BaseResponse( msgId, MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), responseData ); } catch (Exception e) { log.error("Error getting token operations list", e); return new BaseResponse( msgId, MessageCode.INTERNAL_ERROR.getCode(), MessageCode.INTERNAL_ERROR.getDescription(), Map.of("error", "Error getting operations: " + e.getMessage()) ); } } private BaseResponse handleGetById(Integer msgId, TokenOperationRequest request) { log.info("Getting token operation by id: {}", request.getOperationId()); if (request.getOperationId() == null) { return new BaseResponse( msgId, MessageCode.OPERATION_NOT_FOUND.getCode(), MessageCode.OPERATION_NOT_FOUND.getDescription(), Map.of("error", "Operation ID is required") ); } try { TokenOperation operation = tokenOperationService.findById(request.getOperationId()); return new BaseResponse( msgId, MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), operation ); } catch (jakarta.persistence.EntityNotFoundException e) { return new BaseResponse( msgId, MessageCode.NOT_FOUND.getCode(), MessageCode.NOT_FOUND.getDescription(), Map.of("error", "Operation not found with id: " + request.getOperationId()) ); } catch (Exception e) { log.error("Error getting token operation by id", e); return new BaseResponse( msgId, MessageCode.INTERNAL_ERROR.getCode(), MessageCode.INTERNAL_ERROR.getDescription(), Map.of("error", e.getMessage()) ); } } private BaseResponse handleGetByUser(Integer msgId, TokenOperationRequest request) { return handleGetList(msgId, request); } private BaseResponse handleCreate(Integer msgId, TokenOperationRequest request) { if (request.getToken() == null) { return new BaseResponse( msgId, MessageCode.AUTH_TOKEN_NOT_FOUND.getCode(), MessageCode.AUTH_TOKEN_NOT_FOUND.getDescription(), Map.of("error", "User ID is required") ); } Long userId = authService.useUserAuthToken(request.getToken()); try { TokenOperation operation = tokenOperationService.create( request.getOperationType(), userId, request.getSpent() ); return new BaseResponse( msgId, MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), operation ); } catch (Exception e) { log.error("Error creating token operation", e); return new BaseResponse( msgId, MessageCode.INTERNAL_ERROR.getCode(), MessageCode.INTERNAL_ERROR.getDescription(), Map.of("error", "Error creating operation: " + e.getMessage()) ); } } private BaseResponse handleUpdate(Integer msgId, TokenOperationRequest request) { log.info("Updating token operation: {}", request.getOperationId()); if (request.getOperationId() == null) { return new BaseResponse( msgId, MessageCode.OPERATION_NOT_FOUND.getCode(), MessageCode.OPERATION_NOT_FOUND.getDescription(), Map.of("error", "Operation ID is required") ); } try { TokenOperation existing = tokenOperationService.findById(request.getOperationId()); if (request.getOperationType() != null) { existing.setOperationType(request.getOperationType()); } if (request.getSpent() != null) { existing.setSpent(request.getSpent()); } TokenOperation updated = tokenOperationService.update(request.getOperationId(), existing); return new BaseResponse( msgId, MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), updated ); } catch (jakarta.persistence.EntityNotFoundException e) { return new BaseResponse( msgId, MessageCode.NOT_FOUND.getCode(), MessageCode.NOT_FOUND.getDescription(), Map.of("error", "Operation not found with id: " + request.getOperationId()) ); } catch (Exception e) { log.error("Error updating token operation", e); return new BaseResponse( msgId, MessageCode.INTERNAL_ERROR.getCode(), MessageCode.INTERNAL_ERROR.getDescription(), Map.of("error", "Error updating operation: " + e.getMessage()) ); } } private BaseResponse handleDelete(Integer msgId, TokenOperationRequest request) { log.info("Deleting token operation: {}", request.getOperationId()); if (request.getOperationId() == null) { return new BaseResponse( msgId, MessageCode.OPERATION_NOT_FOUND.getCode(), MessageCode.OPERATION_NOT_FOUND.getDescription(), Map.of("error", "Operation ID is required") ); } try { tokenOperationService.deleteById(request.getOperationId()); return new BaseResponse( msgId, MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), Map.of("message", "Operation deleted successfully", "operation_id", request.getOperationId()) ); } catch (jakarta.persistence.EntityNotFoundException e) { return new BaseResponse( msgId, MessageCode.NOT_FOUND.getCode(), MessageCode.NOT_FOUND.getDescription(), Map.of("error", "Operation not found with id: " + request.getOperationId()) ); } catch (Exception e) { log.error("Error deleting token operation", e); return new BaseResponse( msgId, MessageCode.INTERNAL_ERROR.getCode(), MessageCode.INTERNAL_ERROR.getDescription(), Map.of("error", "Error deleting operation: " + e.getMessage()) ); } } private BaseResponse handleDeleteAllByUser(Integer msgId, TokenOperationRequest request) { if (request.getToken() == null) { return new BaseResponse( msgId, MessageCode.AUTH_TOKEN_NOT_FOUND.getCode(), MessageCode.AUTH_TOKEN_NOT_FOUND.getDescription(), Map.of("error", "User ID is required") ); } Long userId = authService.useUserAuthToken(request.getToken()); try { tokenOperationService.deleteByUserId(userId); return new BaseResponse( msgId, MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), Map.of("message", "All operations deleted successfully for user", "user_id", userId) ); } catch (Exception e) { log.error("Error deleting all operations for user", e); return new BaseResponse( msgId, MessageCode.INTERNAL_ERROR.getCode(), MessageCode.INTERNAL_ERROR.getDescription(), Map.of("error", "Error deleting operations: " + e.getMessage()) ); } } private BaseResponse handleGetStats(Integer msgId, TokenOperationRequest request) { if (request.getToken() == null) { return new BaseResponse( msgId, MessageCode.AUTH_TOKEN_NOT_FOUND.getCode(), MessageCode.AUTH_TOKEN_NOT_FOUND.getDescription(), Map.of("error", "User ID is required") ); } Long userId = authService.useUserAuthToken(request.getToken()); if (userId == null) { return new BaseResponse( msgId, MessageCode.USER_NOT_FOUND.getCode(), MessageCode.USER_NOT_FOUND.getDescription(), Map.of("error", "User ID is required") ); } try { Map statsByType = new HashMap<>(); long totalSpent = 0L; for (OperationType type : OperationType.values()) { Long spent = tokenOperationService.getTotalSpentByUserAndType(userId, type); statsByType.put(type.name().toLowerCase(), spent != null ? spent : 0L); totalSpent += spent != null ? spent : 0L; } Map statistics = new HashMap<>(); statistics.put("user_id", userId); statistics.put("total_spent", totalSpent); statistics.put("total_operations", tokenOperationService.countByUserId(userId)); statistics.put("stats_by_type", statsByType); return new BaseResponse( msgId, MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), statistics ); } catch (Exception e) { log.error("Error getting statistics", e); return new BaseResponse( msgId, MessageCode.INTERNAL_ERROR.getCode(), MessageCode.INTERNAL_ERROR.getDescription(), Map.of("error", "Error getting statistics: " + e.getMessage()) ); } } private BaseResponse handleFilter(Integer msgId, TokenOperationRequest request) { if (request.getToken() == null) { return new BaseResponse( msgId, MessageCode.AUTH_TOKEN_NOT_FOUND.getCode(), MessageCode.AUTH_TOKEN_NOT_FOUND.getDescription(), Map.of("error", "User ID is required") ); } Long userId = authService.useUserAuthToken(request.getToken()); try { Page page = tokenOperationService.findByFilters( userId, request.getOperationType(), request.getMinSpent(), request.getMaxSpent(), request.getPage() != null ? request.getPage() : 0, request.getSize() != null ? request.getSize() : 20, request.getSortBy() != null ? request.getSortBy() : "createdAt", request.getSortDirection() != null ? request.getSortDirection() : "desc" ); TokenOperationPageDto pageDto = TokenOperationPageDto.builder() .content(page.getContent()) .pageNumber(page.getNumber()) .pageSize(page.getSize()) .totalElements(page.getTotalElements()) .totalPages(page.getTotalPages()) .last(page.isLast()) .first(page.isFirst()) .build(); Map responseData = new HashMap<>(); responseData.put("operations", pageDto); responseData.put("total_elements", page.getTotalElements()); responseData.put("total_pages", page.getTotalPages()); responseData.put("current_page", page.getNumber()); responseData.put("page_size", page.getSize()); responseData.put("applied_filters", Map.of( "user_id",userId != null ? userId : "all", "operation_type", request.getOperationType() != null ? request.getOperationType() : "all", "min_spent", request.getMinSpent() != null ? request.getMinSpent() : "none", "max_spent", request.getMaxSpent() != null ? request.getMaxSpent() : "none" )); return new BaseResponse( msgId, MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), responseData ); } catch (Exception e) { log.error("Error filtering operations", e); return new BaseResponse( msgId, MessageCode.INTERNAL_ERROR.getCode(), MessageCode.INTERNAL_ERROR.getDescription(), Map.of("error", "Error filtering operations: " + e.getMessage()) ); } } }