package dev.lions.unionflow.server.service;

import dev.lions.unionflow.server.api.dto.communication.request.SendMessageRequest;
import dev.lions.unionflow.server.api.dto.communication.response.MessageResponse;
import dev.lions.unionflow.server.api.enums.communication.MessagePriority;
import dev.lions.unionflow.server.api.enums.communication.MessageStatus;
import dev.lions.unionflow.server.api.enums.communication.MessageType;
import dev.lions.unionflow.server.entity.Conversation;
import dev.lions.unionflow.server.entity.Membre;
import dev.lions.unionflow.server.entity.Message;
import dev.lions.unionflow.server.repository.ConversationRepository;
import dev.lions.unionflow.server.repository.MembreRepository;
import dev.lions.unionflow.server.repository.MessageRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.NotFoundException;
import org.jboss.logging.Logger;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * Service de gestion des messages
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-16
 */
@ApplicationScoped
public class MessageService {

    private static final Logger LOG = Logger.getLogger(MessageService.class);

    @Inject
    MessageRepository messageRepository;

    @Inject
    ConversationRepository conversationRepository;

    @Inject
    MembreRepository membreRepository;

    /**
     * Récupère les messages d'une conversation
     */
    public List<MessageResponse> getMessages(UUID conversationId, UUID membreId, int limit) {
        LOG.infof("Récupération messages pour conversation %s (limit: %d)", conversationId, limit);

        // Vérifier accès
        conversationRepository.findByIdAndParticipant(conversationId, membreId)
            .orElseThrow(() -> new NotFoundException("Conversation non trouvée ou accès refusé"));

        List<Message> messages = messageRepository.findByConversation(conversationId, limit);

        return messages.stream()
            .map(this::convertToResponse)
            .collect(Collectors.toList());
    }

    /**
     * Envoie un message
     */
    @Transactional
    public MessageResponse sendMessage(SendMessageRequest request, UUID senderId) {
        LOG.infof("Envoi message dans conversation %s", request.conversationId());

        // Vérifier accès conversation
        Conversation conversation = conversationRepository.findByIdAndParticipant(request.conversationId(), senderId)
            .orElseThrow(() -> new NotFoundException("Conversation non trouvée ou accès refusé"));

        Membre sender = membreRepository.findById(senderId);
        if (sender == null) {
            throw new NotFoundException("Expéditeur non trouvé");
        }

        Message message = new Message();
        message.setConversation(conversation);
        message.setSender(sender);
        message.setSenderName(sender.getPrenom() + " " + sender.getNom());
        message.setSenderAvatar(sender.getPhotoUrl());
        message.setContent(request.content());
        message.setType(request.type() != null ? request.type() : MessageType.INDIVIDUAL);
        message.setStatus(MessageStatus.SENT);
        message.setPriority(request.priority() != null ? request.priority() : MessagePriority.NORMAL);

        // Destinataires (pour targeted messages)
        if (request.recipientIds() != null && !request.recipientIds().isEmpty()) {
            message.setRecipientIds(request.recipientIds().stream()
                .map(UUID::toString)
                .collect(Collectors.joining(",")));
        }

        // Rôles destinataires
        if (request.recipientRoles() != null && !request.recipientRoles().isEmpty()) {
            message.setRecipientRoles(String.join(",", request.recipientRoles()));
        }

        // Pièces jointes
        if (request.attachments() != null && !request.attachments().isEmpty()) {
            message.setAttachments(String.join(",", request.attachments()));
        }

        message.setOrganisation(conversation.getOrganisation());

        messageRepository.persist(message);

        // Mettre à jour la conversation
        conversation.setUpdatedAt(LocalDateTime.now());
        conversationRepository.persist(conversation);

        LOG.infof("Message %s créé avec succès", message.getId());
        return convertToResponse(message);
    }

    /**
     * Édite un message
     */
    @Transactional
    public MessageResponse editMessage(UUID messageId, UUID senderId, String newContent) {
        Message message = messageRepository.findById(messageId);
        if (message == null) {
            throw new NotFoundException("Message non trouvé");
        }

        if (!message.getSender().getId().equals(senderId)) {
            throw new IllegalStateException("Vous ne pouvez éditer que vos propres messages");
        }

        message.setContent(newContent);
        message.markAsEdited();
        messageRepository.persist(message);

        return convertToResponse(message);
    }

    /**
     * Supprime un message (soft delete)
     */
    @Transactional
    public void deleteMessage(UUID messageId, UUID senderId) {
        Message message = messageRepository.findById(messageId);
        if (message == null) {
            throw new NotFoundException("Message non trouvé");
        }

        if (!message.getSender().getId().equals(senderId)) {
            throw new IllegalStateException("Vous ne pouvez supprimer que vos propres messages");
        }

        message.setIsDeleted(true);
        message.setContent("[Message supprimé]");
        messageRepository.persist(message);
    }

    /**
     * Convertit Message en DTO
     */
    private MessageResponse convertToResponse(Message m) {
        // Parser recipient IDs
        List<UUID> recipientIds = null;
        if (m.getRecipientIds() != null && !m.getRecipientIds().isEmpty()) {
            recipientIds = List.of(m.getRecipientIds().split(",")).stream()
                .map(UUID::fromString)
                .collect(Collectors.toList());
        }

        // Parser roles
        List<String> roles = null;
        if (m.getRecipientRoles() != null && !m.getRecipientRoles().isEmpty()) {
            roles = List.of(m.getRecipientRoles().split(","));
        }

        // Parser attachments
        List<String> attachments = null;
        if (m.getAttachments() != null && !m.getAttachments().isEmpty()) {
            attachments = List.of(m.getAttachments().split(","));
        }

        return MessageResponse.builder()
            .id(m.getId())
            .conversationId(m.getConversation().getId())
            .senderId(m.getSender().getId())
            .senderName(m.getSenderName())
            .senderAvatar(m.getSenderAvatar())
            .content(m.getContent())
            .type(m.getType())
            .status(m.getStatus())
            .priority(m.getPriority())
            .recipientIds(recipientIds)
            .recipientRoles(roles)
            .organisationId(m.getOrganisation() != null ? m.getOrganisation().getId() : null)
            .createdAt(m.getDateCreation())
            .readAt(m.getReadAt())
            .attachments(attachments)
            .isEdited(m.getIsEdited())
            .editedAt(m.getEditedAt())
            .isDeleted(m.getIsDeleted())
            .build();
    }
}
