package dev.lions.unionflow.server.repository;

import dev.lions.unionflow.server.entity.Conversation;
import dev.lions.unionflow.server.api.enums.messagerie.StatutConversation;
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * Repository pour les conversations de la messagerie.
 *
 * @author UnionFlow Team
 * @version 4.0
 * @since 2026-04-13
 */
@ApplicationScoped
public class ConversationRepository implements PanacheRepositoryBase<Conversation, UUID> {

    /**
     * Trouve une conversation par son ID avec Optional.
     */
    public Optional<Conversation> findConversationById(UUID id) {
        return find("id", id).firstResultOptional();
    }

    /**
     * Liste toutes les conversations d'un membre (via les participants).
     * Triées par date du dernier message décroissante.
     */
    public List<Conversation> findByMembreId(UUID membreId) {
        return find(
            "SELECT DISTINCT c FROM Conversation c " +
            "JOIN c.participants p " +
            "WHERE p.membre.id = ?1 AND p.actif = true " +
            "ORDER BY c.dernierMessageAt DESC NULLS LAST",
            membreId
        ).list();
    }

    /**
     * Trouve une conversation directe existante entre deux membres dans une organisation.
     */
    public Optional<Conversation> findConversationDirecte(UUID membreAId, UUID membreBId, UUID organisationId) {
        return find(
            "SELECT DISTINCT c FROM Conversation c " +
            "JOIN c.participants p1 " +
            "JOIN c.participants p2 " +
            "WHERE c.typeConversation = 'DIRECTE' " +
            "AND c.organisation.id = ?3 " +
            "AND p1.membre.id = ?1 AND p1.actif = true " +
            "AND p2.membre.id = ?2 AND p2.actif = true",
            membreAId, membreBId, organisationId
        ).firstResultOptional();
    }

    /**
     * Trouve le canal d'un rôle dans une organisation.
     */
    public Optional<Conversation> findCanalRole(UUID organisationId, String roleCible) {
        return find(
            "organisation.id = ?1 AND roleCible = ?2 AND typeConversation = 'ROLE_CANAL' AND actif = true",
            organisationId, roleCible
        ).firstResultOptional();
    }

    /**
     * Liste les conversations actives d'un membre.
     */
    public List<Conversation> findActivesByMembre(UUID membreId) {
        return find(
            "SELECT DISTINCT c FROM Conversation c " +
            "JOIN c.participants p " +
            "WHERE p.membre.id = ?1 AND p.actif = true AND c.statut = ?2 " +
            "ORDER BY c.dernierMessageAt DESC NULLS LAST",
            membreId, StatutConversation.ACTIVE
        ).list();
    }
}
