package dev.lions.unionflow.server.entity;

import dev.lions.unionflow.server.api.enums.communication.ConversationType;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

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

@DisplayName("Conversation")
class ConversationTest {

    @Test
    @DisplayName("getters/setters de base")
    void gettersSetters() {
        Conversation c = new Conversation();
        c.setName("Groupe Test");
        c.setDescription("Description groupe");
        c.setType(ConversationType.GROUP);
        c.setIsMuted(false);
        c.setIsPinned(true);
        c.setIsArchived(false);

        assertThat(c.getName()).isEqualTo("Groupe Test");
        assertThat(c.getDescription()).isEqualTo("Description groupe");
        assertThat(c.getType()).isEqualTo(ConversationType.GROUP);
        assertThat(c.getIsMuted()).isFalse();
        assertThat(c.getIsPinned()).isTrue();
        assertThat(c.getIsArchived()).isFalse();
    }

    @Test
    @DisplayName("onUpdate (PreUpdate) - met à jour updatedAt via réflexion")
    void onUpdate_setsUpdatedAt() throws Exception {
        Conversation c = new Conversation();
        assertThat(c.getUpdatedAt()).isNull();

        Method onUpdate = Conversation.class.getDeclaredMethod("onUpdate");
        onUpdate.setAccessible(true);

        LocalDateTime before = LocalDateTime.now().minusSeconds(1);
        onUpdate.invoke(c);
        LocalDateTime after = LocalDateTime.now().plusSeconds(1);

        assertThat(c.getUpdatedAt()).isNotNull();
        assertThat(c.getUpdatedAt()).isAfter(before);
        assertThat(c.getUpdatedAt()).isBefore(after);
    }

    @Test
    @DisplayName("onUpdate appelé deux fois met à jour updatedAt à chaque fois")
    void onUpdate_calledTwice_updatesEachTime() throws Exception {
        Conversation c = new Conversation();

        Method onUpdate = Conversation.class.getDeclaredMethod("onUpdate");
        onUpdate.setAccessible(true);

        onUpdate.invoke(c);
        LocalDateTime first = c.getUpdatedAt();

        // petit délai pour différencier les timestamps
        Thread.sleep(5);

        onUpdate.invoke(c);
        LocalDateTime second = c.getUpdatedAt();

        assertThat(second).isAfterOrEqualTo(first);
    }

    @Test
    @DisplayName("participants initialisé à liste vide")
    void participants_initializedEmpty() {
        Conversation c = new Conversation();
        assertThat(c.getParticipants()).isNotNull().isEmpty();
    }

    @Test
    @DisplayName("messages initialisé à liste vide")
    void messages_initializedEmpty() {
        Conversation c = new Conversation();
        assertThat(c.getMessages()).isNotNull().isEmpty();
    }

    @Test
    @DisplayName("isMuted et isPinned et isArchived défaut false")
    void defaultFlags_areFalse() {
        Conversation c = new Conversation();
        assertThat(c.getIsMuted()).isFalse();
        assertThat(c.getIsPinned()).isFalse();
        assertThat(c.getIsArchived()).isFalse();
    }
}
