package com.kifi.api.service; import com.kifi.api.entity.project.Project; import com.kifi.api.entity.project.ProjectTask; import com.kifi.api.entity.project.ProjectTaskComment; import com.kifi.api.repository.ProjectRepository; import com.kifi.api.repository.ProjectTaskRepository; import com.kifi.api.repository.ProjectTaskCommentRepository; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.core.type.TypeReference; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.HashMap; import java.util.UUID; import java.util.stream.Collectors; @Service @RequiredArgsConstructor @Slf4j public class ProjectService { private final ProjectRepository projectRepository; private final ProjectTaskRepository projectTaskRepository; private final ProjectTaskCommentRepository projectTaskCommentRepository; private final MinioServiceClient minioServiceClient; private final ObjectMapper objectMapper = new ObjectMapper(); // ... existing code ... public Mono addComment(Long taskId, Long userId, String content, String imagesJson) { ProjectTaskComment comment = new ProjectTaskComment(); comment.setTaskId(taskId); comment.setUserId(userId); comment.setContent(content); comment.setCreatedAt(LocalDateTime.now()); if (imagesJson == null || imagesJson.trim().isEmpty() || imagesJson.equals("[]")) { return projectTaskCommentRepository.save(comment); } try { List> attachments = objectMapper.readValue(imagesJson, new TypeReference>>() {}); // Check if it's the old format (just base64 strings) if (!attachments.isEmpty() && attachments.get(0).containsKey("base64Content") == false) { // It's just strings (old format), we shouldn't really hit this with the new app version comment.setImages(imagesJson); return projectTaskCommentRepository.save(comment); } return Flux.fromIterable(attachments) .flatMap(att -> { String fileName = att.get("fileName"); String contentType = att.get("contentType"); String base64Content = att.get("base64Content"); String uniqueFileName = UUID.randomUUID().toString() + "_" + fileName; String directoryPath = "tasks/" + taskId; return minioServiceClient.uploadFile(directoryPath, contentType, uniqueFileName, base64Content) .map(minioResponse -> { Map result = new HashMap<>(); result.put("fileName", fileName); result.put("contentType", contentType); if (minioResponse.isSuccess()) { result.put("filePath", minioResponse.getFilePath()); } return result; }); }) .collectList() .flatMap(uploadedAttachments -> { try { String newImagesJson = objectMapper.writeValueAsString(uploadedAttachments); comment.setImages(newImagesJson); return projectTaskCommentRepository.save(comment); } catch (Exception e) { return Mono.error(e); } }); } catch (Exception e) { // Fallback for old simple string array comment.setImages(imagesJson); return projectTaskCommentRepository.save(comment); } }