package dev.lions.unionflow.server.entity;

import dev.lions.unionflow.server.api.enums.messagerie.StatutConversation;
import dev.lions.unionflow.server.api.enums.messagerie.TypeConversation;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;

@DisplayName("ConversationParticipant")
class ConversationParticipantTest {

    private static Membre newMembre() {
        Membre m = new Membre();
        m.setId(UUID.randomUUID());
        m.setNumeroMembre("M1");
        m.setPrenom("Alpha");
        m.setNom("Diallo");
        m.setEmail("alpha@test.com");
        m.setDateNaissance(LocalDate.now());
        return m;
    }

    private static Conversation newConversation() {
        Organisation org = new Organisation();
        org.setId(UUID.randomUUID());
        org.setNom("Org Test");
        Conversation c = new Conversation();
        c.setId(UUID.randomUUID());
        c.setOrganisation(org);
        c.setTypeConversation(TypeConversation.DIRECTE);
        c.setStatut(StatutConversation.ACTIVE);
        c.setNombreMessages(0);
        return c;
    }

    @Test
    @DisplayName("getters/setters")
    void gettersSetters() {
        ConversationParticipant p = new ConversationParticipant();
        Conversation conv = newConversation();
        Membre membre = newMembre();
        p.setConversation(conv);
        p.setMembre(membre);
        p.setRoleDansConversation("INITIATEUR");
        p.setNotifier(true);

        assertThat(p.getConversation()).isEqualTo(conv);
        assertThat(p.getMembre()).isEqualTo(membre);
        assertThat(p.getRoleDansConversation()).isEqualTo("INITIATEUR");
        assertThat(p.getNotifier()).isTrue();
    }

    @Test
    @DisplayName("estInitiateur — INITIATEUR → true")
    void estInitiateur_true() {
        ConversationParticipant p = buildMinimal("INITIATEUR");
        assertThat(p.estInitiateur()).isTrue();
    }

    @Test
    @DisplayName("estInitiateur — PARTICIPANT → false")
    void estInitiateur_false() {
        ConversationParticipant p = buildMinimal("PARTICIPANT");
        assertThat(p.estInitiateur()).isFalse();
    }

    @Test
    @DisplayName("marquerLu — luJusqua mis à jour")
    void marquerLu() {
        ConversationParticipant p = buildMinimal("PARTICIPANT");
        p.setLuJusqua(null);
        p.marquerLu();
        assertThat(p.getLuJusqua()).isNotNull();
    }

    @Test
    @DisplayName("marquerLu — luJusqua remplace l'ancien")
    void marquerLu_replaceOld() {
        ConversationParticipant p = buildMinimal("PARTICIPANT");
        LocalDateTime old = LocalDateTime.now().minusDays(1);
        p.setLuJusqua(old);
        p.marquerLu();
        assertThat(p.getLuJusqua()).isAfter(old);
    }

    @Test
    @DisplayName("builder — valeurs par défaut")
    void builder_defaults() {
        ConversationParticipant p = ConversationParticipant.builder()
            .conversation(newConversation())
            .membre(newMembre())
            .build();
        assertThat(p.getRoleDansConversation()).isEqualTo("PARTICIPANT");
        assertThat(p.getNotifier()).isTrue();
    }

    @Test
    @DisplayName("equals et hashCode")
    void equalsHashCode() {
        UUID id = UUID.randomUUID();
        // Partage les mêmes Conversation et Membre pour que Lombok equals
        // sur les champs imbriqués donne true (les IDs imbriqués sont aléatoires
        // dans newConversation/newMembre, donc il faut réutiliser les instances).
        Conversation sharedConv = newConversation();
        Membre sharedMembre = newMembre();
        ConversationParticipant a = new ConversationParticipant();
        a.setId(id);
        a.setConversation(sharedConv);
        a.setMembre(sharedMembre);
        a.setRoleDansConversation("PARTICIPANT");
        a.setNotifier(true);
        ConversationParticipant b = new ConversationParticipant();
        b.setId(id);
        b.setConversation(sharedConv);
        b.setMembre(sharedMembre);
        b.setRoleDansConversation("PARTICIPANT");
        b.setNotifier(true);
        assertThat(a).isEqualTo(b);
        assertThat(a.hashCode()).isEqualTo(b.hashCode());
    }

    @Test
    @DisplayName("toString non null")
    void toString_nonNull() {
        assertThat(buildMinimal("PARTICIPANT").toString()).isNotNull().isNotEmpty();
    }

    private ConversationParticipant buildMinimal(String role) {
        ConversationParticipant p = new ConversationParticipant();
        p.setConversation(newConversation());
        p.setMembre(newMembre());
        p.setRoleDansConversation(role);
        p.setNotifier(true);
        return p;
    }
}
