package com.openisle.service; import com.openisle.dto.ChannelDto; import com.openisle.dto.MessageDto; import com.openisle.dto.UserSummaryDto; import com.openisle.model.Message; import com.openisle.model.MessageConversation; import com.openisle.model.MessageParticipant; import com.openisle.model.User; import com.openisle.repository.MessageConversationRepository; import com.openisle.repository.MessageParticipantRepository; import com.openisle.repository.MessageRepository; import com.openisle.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.List; import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class ChannelService { private final MessageConversationRepository conversationRepository; private final MessageParticipantRepository participantRepository; private final MessageRepository messageRepository; private final UserRepository userRepository; @Transactional(readOnly = true) public List listChannels(Long userId) { List channels = conversationRepository.findByChannelTrue(); return channels.stream().map(c -> toDto(c, userId)).collect(Collectors.toList()); } @Transactional public ChannelDto joinChannel(Long channelId, Long userId) { MessageConversation channel = conversationRepository.findById(channelId) .orElseThrow(() -> new IllegalArgumentException("Channel not found")); User user = userRepository.findById(userId) .orElseThrow(() -> new IllegalArgumentException("User not found")); participantRepository.findByConversationIdAndUserId(channelId, userId) .orElseGet(() -> { MessageParticipant p = new MessageParticipant(); p.setConversation(channel); p.setUser(user); MessageParticipant saved = participantRepository.save(p); channel.getParticipants().add(saved); return saved; }); return toDto(channel, userId); } private ChannelDto toDto(MessageConversation channel, Long userId) { ChannelDto dto = new ChannelDto(); dto.setId(channel.getId()); dto.setName(channel.getName()); dto.setDescription(channel.getDescription()); dto.setAvatar(channel.getAvatar()); if (channel.getLastMessage() != null) { dto.setLastMessage(toMessageDto(channel.getLastMessage())); } dto.setMemberCount(channel.getParticipants().size()); boolean joined = channel.getParticipants().stream() .anyMatch(p -> p.getUser().getId().equals(userId)); dto.setJoined(joined); if (joined) { MessageParticipant participant = channel.getParticipants().stream() .filter(p -> p.getUser().getId().equals(userId)) .findFirst().orElse(null); LocalDateTime lastRead = participant.getLastReadAt() == null ? LocalDateTime.of(1970, 1, 1, 0, 0) : participant.getLastReadAt(); long unread = messageRepository .countByConversationIdAndCreatedAtAfterAndSenderIdNot(channel.getId(), lastRead, userId); dto.setUnreadCount(unread); } else { dto.setUnreadCount(0); } return dto; } private MessageDto toMessageDto(Message message) { MessageDto dto = new MessageDto(); dto.setId(message.getId()); dto.setContent(message.getContent()); dto.setConversationId(message.getConversation().getId()); dto.setCreatedAt(message.getCreatedAt()); UserSummaryDto userDto = new UserSummaryDto(); userDto.setId(message.getSender().getId()); userDto.setUsername(message.getSender().getUsername()); userDto.setAvatar(message.getSender().getAvatar()); dto.setSender(userDto); return dto; } }