package com.krylov.refound.service; import com.krylov.refound.dto.ChatDto; import com.krylov.refound.dto.MessageDto; import com.krylov.refound.entity.Chat; import com.krylov.refound.entity.Message; import com.krylov.refound.repository.ChatRepository; import com.krylov.refound.repository.MessageRepository; import com.krylov.refound.repository.UserRepository; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor public class ChatService { private final ChatRepository chatRepository; private final MessageRepository messageRepository; private final SimpMessagingTemplate messagingTemplate; private final UserRepository userRepository; // твой существующий репозиторий юзеров // Создать чат с пользователем (или вернуть существующий) @Transactional public ChatDto getOrCreateChat(Long currentUserId, Long otherUserId, Long postId) { if (currentUserId.equals(otherUserId)) { throw new IllegalArgumentException("Нельзя создать чат с самим собой"); } Long u1 = Math.min(currentUserId, otherUserId); Long u2 = Math.max(currentUserId, otherUserId); Chat chat = chatRepository.findByUsers(u1, u2) .orElseGet(() -> { Chat newChat = new Chat(); newChat.setUserOneId(u1); newChat.setUserTwoId(u2); newChat.setPostId(postId); return chatRepository.save(newChat); }); return toDto(chat, currentUserId); } // Все чаты пользователя public List getUserChats(Long userId) { return chatRepository.findAllByUserId(userId).stream() .map(c -> toDto(c, userId)) .collect(Collectors.toList()); } // История сообщений в чате public List getMessages(Long chatId) { return messageRepository.findByChatIdOrderByCreatedAtAsc(chatId).stream() .map(this::toMessageDto) .collect(Collectors.toList()); } // Отправка сообщения (вызывается из WebSocket контроллера) @Transactional public MessageDto sendMessage(Long senderId, Long chatId, String content) { Chat chat = chatRepository.findById(chatId) .orElseThrow(() -> new IllegalArgumentException("Чат не найден")); if (!chat.getUserOneId().equals(senderId) && !chat.getUserTwoId().equals(senderId)) { throw new SecurityException("Вы не участник этого чата"); } Message message = new Message(); message.setChatId(chatId); message.setSenderId(senderId); message.setContent(content); message = messageRepository.save(message); MessageDto dto = toMessageDto(message); messagingTemplate.convertAndSend("/topic/chat/" + chatId, dto); // Уведомляем получателя об непрочитанных Long recipientId = chat.getUserOneId().equals(senderId) ? chat.getUserTwoId() : chat.getUserOneId(); long unreadCount = messageRepository .countByChatIdAndIsReadFalseAndSenderIdNot(chatId, recipientId); messagingTemplate.convertAndSend( "/topic/user/" + recipientId + "/unread", Map.of("chatId", chatId, "unreadCount", unreadCount) ); return dto; } private ChatDto toDto(Chat chat, Long currentUserId) { Long otherUserId = chat.getUserOneId().equals(currentUserId) ? chat.getUserTwoId() : chat.getUserOneId(); ChatDto dto = new ChatDto(); dto.setId(chat.getId()); dto.setOtherUserId(otherUserId); dto.setPostId(chat.getPostId()); // Подтягиваем имя/аватар собеседника из твоего UserRepository userRepository.findById(otherUserId).ifPresent(user -> { dto.setOtherUserName(user.getName() + " " + user.getLastName()); dto.setOtherUserAvatar(user.getAvatarUrl()); }); List messages = messageRepository.findByChatIdOrderByCreatedAtAsc(chat.getId()); if (!messages.isEmpty()) { Message last = messages.getLast(); dto.setLastMessage(last.getContent()); dto.setLastMessageAt(last.getCreatedAt()); } dto.setUnreadCount( messageRepository.countByChatIdAndIsReadFalseAndSenderIdNot(chat.getId(), currentUserId) ); return dto; } private MessageDto toMessageDto(Message m) { MessageDto dto = new MessageDto(); dto.setId(m.getId()); dto.setChatId(m.getChatId()); dto.setSenderId(m.getSenderId()); dto.setContent(m.getContent()); dto.setRead(m.isRead()); dto.setCreatedAt(m.getCreatedAt()); return dto; } public void deleteChat(Long chatId) { chatRepository.deleteById(chatId); } @Transactional public void markAsRead(Long chatId, Long userId) { messageRepository.markAsReadByChatIdAndRecipient(chatId, userId); } }