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.*; import ru.soune.nocopy.dto.file.*; import ru.soune.nocopy.entity.file.FileEntity; import ru.soune.nocopy.entity.file.FileStatus; import ru.soune.nocopy.exception.FileEntityNotFoundException; import ru.soune.nocopy.exception.NotFoundAuthToken; import ru.soune.nocopy.repository.FileEntityRepository; import ru.soune.nocopy.service.auth.AuthService; import ru.soune.nocopy.service.file.FileEntityService; import ru.soune.nocopy.service.file.FileStatsService; import java.util.Arrays; import java.util.List; @Slf4j @Component @RequiredArgsConstructor public class FileEntityHandler implements RequestHandler { private final FileEntityService fileEntityService; private final AuthService authService; private final FileStatsService fileStatsService; private final ObjectMapper objectMapper; private final FileEntityRepository fileEntityRepository; @Override public BaseResponse handle(BaseRequest request) { try { FileEntityRequest fileRequest = objectMapper.convertValue( request.getMessageBody(), FileEntityRequest.class); String action = fileRequest.getAction(); switch (action) { case "file_info": return handleGetFileInfo(request, fileRequest); case "user_files_info": return handleGetFilesUserInfo(request, fileRequest); case "file_by_session": return handleGetFileBySession(request, fileRequest); case "user_files": return handleGetUserFiles(request, fileRequest); case "search_files": return handleSearchFiles(request, fileRequest); case "storage_usage": return handleGetStorageUsage(request, fileRequest); case "delete_file": return handleDeleteFile(request, fileRequest); default: ActionResponse response = ActionResponse.builder() .action(action) .availableActions(Arrays.asList( "file_info", "file_by_session", "user_files", "search_files", "storage_usage", "delete_file", "user_files_info")) .build(); return new BaseResponse(request.getMsgId(), MessageCode.INVALID_ACTION.getCode(), "Invalid action: " + action, response); } } catch (Exception e) { log.error("Error in FileEntityHandler", e); return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(), "Handler error: " + e.getMessage(), null); } } private BaseResponse handleGetFilesUserInfo(BaseRequest request, FileEntityRequest fileRequest) { Long userId = authService.useUserAuthToken(fileRequest.getToken()); FileInfoUserResponse userFileStats = fileStatsService.getUserFileStats(userId); return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), userFileStats); } private BaseResponse handleGetFileInfo(BaseRequest request, FileEntityRequest fileRequest) { try { Long userId = authService.useUserAuthToken(fileRequest.getToken()); FileEntityResponse fileInfo = fileEntityService.getById(fileRequest.getFileId(), request.getVersion()); if (!fileInfo.getUserId().equals(userId)) { return new BaseResponse(request.getMsgId(), MessageCode.ACCESS_DENIED.getCode(), "Access denied", null); } return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), fileInfo); } catch (NotFoundAuthToken e) { return new BaseResponse(request.getMsgId(), MessageCode.INVALID_TOKEN.getCode(), "Authentication required", null); } catch (Exception e) { log.error("Error getting file info", e); return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(), "Failed to get file info: " + e.getMessage(), null); } } private BaseResponse handleGetFileBySession(BaseRequest request, FileEntityRequest fileRequest) { try { Long userId = authService.useUserAuthToken(fileRequest.getToken()); FileEntityResponse fileInfo = fileEntityService.getByUploadSessionId(fileRequest.getUploadSessionId(), request.getVersion()); if (!fileInfo.getUserId().equals(userId)) { return new BaseResponse(request.getMsgId(), MessageCode.ACCESS_DENIED.getCode(), "Access denied", null); } return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), fileInfo); } catch (NotFoundAuthToken e) { return new BaseResponse(request.getMsgId(), MessageCode.INVALID_TOKEN.getCode(), "Authentication required", null); } catch (Exception e) { log.error("Error getting file by session", e); return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(), "Failed to get file: " + e.getMessage(), null); } } private BaseResponse handleGetUserFiles(BaseRequest request, FileEntityRequest fileRequest) { try { Long userId = authService.useUserAuthToken(fileRequest.getToken()); int page = fileRequest.getPage() != null ? fileRequest.getPage() : 1; int pageSize = fileRequest.getPageSize() != null ? fileRequest.getPageSize() : 20; FileResponse files = fileEntityService.getUserFiles(userId, page, pageSize, request.getVersion()); return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), files); } catch (NotFoundAuthToken e) { return new BaseResponse(request.getMsgId(), MessageCode.INVALID_TOKEN.getCode(), "Authentication required", null); } catch (Exception e) { log.error("Error getting user files", e); return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(), "Failed to get files: " + e.getMessage(), null); } } private BaseResponse handleSearchFiles(BaseRequest request, FileEntityRequest fileRequest) { try { Long userId = authService.useUserAuthToken(fileRequest.getToken()); int page = fileRequest.getPage() != null ? fileRequest.getPage() : 1; int pageSize = fileRequest.getPageSize() != null ? fileRequest.getPageSize() : 20; if (fileRequest.getQuery() == null || fileRequest.getQuery().isBlank()) { return handleGetUserFiles(request, fileRequest); } FileResponse allFiles = fileEntityService.getUserFiles(userId, 1, 1000, request.getVersion()); var filteredFiles = allFiles.getFiles().stream() .filter(f -> (f.getOriginalFileName() + f.getFileExtension()).toLowerCase() .contains(fileRequest.getQuery().toLowerCase())) .toList(); int start = (page - 1) * pageSize; int end = Math.min(start + pageSize, filteredFiles.size()); List fileEntityResponses = filteredFiles.subList(start, Math.min(end, filteredFiles.size())); long sumSize = fileEntityResponses.stream() .mapToLong(FileEntityResponse::getFileSize) .sum(); FileListResponse response = FileListResponse.builder() .files(fileEntityResponses) .totalCount(filteredFiles.size()) .totalSize(sumSize) .formattedTotalSize(fileEntityService.formatFileSize(sumSize)) .page(page) .pageSize(pageSize) .build(); return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), response); } catch (NotFoundAuthToken e) { return new BaseResponse(request.getMsgId(), MessageCode.INVALID_TOKEN.getCode(), "Authentication required", null); } catch (Exception e) { log.error("Error searching files", e); return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(), "Failed to search files: " + e.getMessage(), null); } } private BaseResponse handleGetStorageUsage(BaseRequest request, FileEntityRequest fileRequest) { try { Long userId = authService.useUserAuthToken(fileRequest.getToken()); long usage = fileEntityService.getUserStorageUsed(userId); StorageUsageResponse response = StorageUsageResponse.builder() .userId(userId) .storageUsed(usage) .formattedStorageUsed(formatFileSize(usage)) .build(); return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), MessageCode.SUCCESS.getDescription(), response); } catch (NotFoundAuthToken e) { return new BaseResponse(request.getMsgId(), MessageCode.INVALID_TOKEN.getCode(), "Authentication required", null); } catch (Exception e) { log.error("Error getting storage usage", e); return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(), "Failed to get storage usage: " + e.getMessage(), null); } } private BaseResponse handleDeleteFile(BaseRequest request, FileEntityRequest fileRequest) { try { Long userId = authService.useUserAuthToken(fileRequest.getToken()); String fileId = fileRequest.getFileId(); FileEntityResponse fileInfo = fileEntityService.getById(fileId, request.getVersion()); DeleteFileResponse response; if (!fileInfo.getUserId().equals(userId)) { return new BaseResponse(request.getMsgId(), MessageCode.ACCESS_DENIED.getCode(), "Access denied", null); } FileEntity fileEntity = fileEntityRepository.findById(fileId) .orElseThrow(() -> new FileEntityNotFoundException(fileId)); if (fileEntity.getStatus().equals(FileStatus.DELETED)) { fileEntityService.deleteFromDisk(fileEntity); response = DeleteFileResponse.builder() .fileId(fileRequest.getFileId()) .message("File deleted from disk") .build(); } else { fileEntityService.markAsDeleted(fileEntity); response = DeleteFileResponse.builder() .fileId(fileRequest.getFileId()) .message("File marked as deleted") .build(); } return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), "File marked as deleted", response); } catch (NotFoundAuthToken e) { return new BaseResponse(request.getMsgId(), MessageCode.INVALID_TOKEN.getCode(), "Authentication required", null); } catch (Exception e) { log.error("Error deleting file", e); return new BaseResponse(request.getMsgId(), MessageCode.FILE_UPLOAD_ERROR.getCode(), "Failed to delete file: " + e.getMessage(), null); } } private String formatFileSize(long size) { if (size < 1024) return size + " B"; int exp = (int) (Math.log(size) / Math.log(1024)); String pre = "KMGTPE".charAt(exp-1) + ""; return String.format("%.1f %sB", size / Math.pow(1024, exp), pre); } }