package dev.lions.unionflow.server.entity;

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

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

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

@DisplayName("Message")
class MessageTest {

    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 — message texte")
    void gettersSetters_texte() {
        Message msg = new Message();
        Conversation conv = newConversation();
        Membre expediteur = newMembre();
        msg.setConversation(conv);
        msg.setExpediteur(expediteur);
        msg.setTypeMessage(TypeContenu.TEXTE);
        msg.setContenu("Bonjour tout le monde !");

        assertThat(msg.getConversation()).isEqualTo(conv);
        assertThat(msg.getExpediteur()).isEqualTo(expediteur);
        assertThat(msg.getTypeMessage()).isEqualTo(TypeContenu.TEXTE);
        assertThat(msg.getContenu()).isEqualTo("Bonjour tout le monde !");
    }

    @Test
    @DisplayName("getters/setters — note vocale")
    void gettersSetters_vocal() {
        Message msg = new Message();
        msg.setConversation(newConversation());
        msg.setExpediteur(newMembre());
        msg.setTypeMessage(TypeContenu.VOCAL);
        msg.setUrlFichier("https://storage.example.com/audio.opus");
        msg.setDureeAudio(45);

        assertThat(msg.getTypeMessage()).isEqualTo(TypeContenu.VOCAL);
        assertThat(msg.getUrlFichier()).isEqualTo("https://storage.example.com/audio.opus");
        assertThat(msg.getDureeAudio()).isEqualTo(45);
    }

    @Test
    @DisplayName("estTextuel — TEXTE → true")
    void estTextuel_true() {
        Message msg = buildMinimal(TypeContenu.TEXTE);
        assertThat(msg.estTextuel()).isTrue();
        assertThat(msg.estVocal()).isFalse();
    }

    @Test
    @DisplayName("estVocal — VOCAL → true")
    void estVocal_true() {
        Message msg = buildMinimal(TypeContenu.VOCAL);
        assertThat(msg.estVocal()).isTrue();
        assertThat(msg.estTextuel()).isFalse();
    }

    @Test
    @DisplayName("estSupprime — null → false")
    void estSupprime_nullFalse() {
        Message msg = buildMinimal(TypeContenu.TEXTE);
        msg.setSupprimeLe(null);
        assertThat(msg.estSupprime()).isFalse();
    }

    @Test
    @DisplayName("supprimer — contenu remplacé par marqueur, urlFichier null")
    void supprimer() {
        Message msg = buildMinimal(TypeContenu.TEXTE);
        msg.setContenu("Message secret");
        msg.setUrlFichier("https://example.com/file");

        msg.supprimer();

        assertThat(msg.estSupprime()).isTrue();
        assertThat(msg.getContenu()).isEqualTo("[Message supprimé]");
        assertThat(msg.getUrlFichier()).isNull();
        assertThat(msg.getSupprimeLe()).isNotNull();
    }

    @Test
    @DisplayName("onCreate — initialise typeMessage si null")
    void onCreate_initDefaults() {
        Message msg = new Message();
        msg.setConversation(newConversation());
        msg.setExpediteur(newMembre());
        msg.setContenu("Test");

        msg.onCreate();

        assertThat(msg.getTypeMessage()).isEqualTo(TypeContenu.TEXTE);
        assertThat(msg.getDateCreation()).isNotNull();
        assertThat(msg.getActif()).isTrue();
    }

    @Test
    @DisplayName("onCreate — préserve typeMessage existant")
    void onCreate_preservesType() {
        Message msg = new Message();
        msg.setConversation(newConversation());
        msg.setExpediteur(newMembre());
        msg.setTypeMessage(TypeContenu.VOCAL);
        msg.setUrlFichier("url");
        msg.setDureeAudio(30);

        msg.onCreate();

        assertThat(msg.getTypeMessage()).isEqualTo(TypeContenu.VOCAL);
    }

    @Test
    @DisplayName("equals et hashCode")
    void equalsHashCode() {
        UUID id = UUID.randomUUID();
        // Partage Conversation et Membre pour que Lombok equals
        // (récursif sur les champs) donne true — sinon les UUIDs aléatoires
        // dans newConversation/newMembre cassent l'égalité.
        Conversation sharedConv = newConversation();
        Membre sharedExpediteur = newMembre();
        Message a = new Message();
        a.setId(id);
        a.setConversation(sharedConv);
        a.setExpediteur(sharedExpediteur);
        a.setTypeMessage(TypeContenu.TEXTE);
        a.setContenu("Texte test");
        Message b = new Message();
        b.setId(id);
        b.setConversation(sharedConv);
        b.setExpediteur(sharedExpediteur);
        b.setTypeMessage(TypeContenu.TEXTE);
        b.setContenu("Texte test");
        assertThat(a).isEqualTo(b);
        assertThat(a.hashCode()).isEqualTo(b.hashCode());
    }

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

    private Message buildMinimal(TypeContenu type) {
        Message msg = new Message();
        msg.setConversation(newConversation());
        msg.setExpediteur(newMembre());
        msg.setTypeMessage(type);
        if (TypeContenu.TEXTE.equals(type)) {
            msg.setContenu("Texte test");
        } else if (TypeContenu.VOCAL.equals(type)) {
            msg.setUrlFichier("https://example.com/audio.opus");
            msg.setDureeAudio(30);
        }
        return msg;
    }
}
