package dev.lions.unionflow.server.entity;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

import java.util.UUID;

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

@DisplayName("MembreSuivi entity")
class MembreSuiviTest {

    // -------------------------------------------------------------------------
    // No-args constructor
    // -------------------------------------------------------------------------
    @Test
    @DisplayName("no-args constructor creates instance with null UUIDs")
    void noArgsConstructor_createsInstanceWithNullFields() {
        MembreSuivi suivi = new MembreSuivi();

        assertThat(suivi).isNotNull();
        assertThat(suivi.getFollowerUtilisateurId()).isNull();
        assertThat(suivi.getSuiviUtilisateurId()).isNull();
    }

    // -------------------------------------------------------------------------
    // All-args constructor
    // -------------------------------------------------------------------------
    @Test
    @DisplayName("all-args constructor sets all fields")
    void allArgsConstructor_setsAllFields() {
        UUID followerId = UUID.randomUUID();
        UUID suiviId = UUID.randomUUID();

        MembreSuivi suivi = new MembreSuivi(followerId, suiviId);

        assertThat(suivi.getFollowerUtilisateurId()).isEqualTo(followerId);
        assertThat(suivi.getSuiviUtilisateurId()).isEqualTo(suiviId);
    }

    // -------------------------------------------------------------------------
    // Builder
    // -------------------------------------------------------------------------
    @Nested
    @DisplayName("Builder")
    class BuilderTests {

        @Test
        @DisplayName("builder sets followerUtilisateurId")
        void builder_setsFollowerUtilisateurId() {
            UUID id = UUID.randomUUID();
            MembreSuivi suivi = MembreSuivi.builder()
                    .followerUtilisateurId(id)
                    .build();

            assertThat(suivi.getFollowerUtilisateurId()).isEqualTo(id);
        }

        @Test
        @DisplayName("builder sets suiviUtilisateurId")
        void builder_setsSuiviUtilisateurId() {
            UUID id = UUID.randomUUID();
            MembreSuivi suivi = MembreSuivi.builder()
                    .suiviUtilisateurId(id)
                    .build();

            assertThat(suivi.getSuiviUtilisateurId()).isEqualTo(id);
        }

        @Test
        @DisplayName("builder sets both UUID fields")
        void builder_setsBothUuidFields() {
            UUID followerId = UUID.fromString("11111111-1111-1111-1111-111111111111");
            UUID suiviId    = UUID.fromString("22222222-2222-2222-2222-222222222222");

            MembreSuivi suivi = MembreSuivi.builder()
                    .followerUtilisateurId(followerId)
                    .suiviUtilisateurId(suiviId)
                    .build();

            assertThat(suivi.getFollowerUtilisateurId()).isEqualTo(followerId);
            assertThat(suivi.getSuiviUtilisateurId()).isEqualTo(suiviId);
        }
    }

    // -------------------------------------------------------------------------
    // Getters / Setters
    // -------------------------------------------------------------------------
    @Nested
    @DisplayName("Getters and Setters")
    class GettersSettersTests {

        @Test
        @DisplayName("setFollowerUtilisateurId / getFollowerUtilisateurId round-trips")
        void followerUtilisateurId_roundTrips() {
            UUID id = UUID.randomUUID();
            MembreSuivi suivi = new MembreSuivi();
            suivi.setFollowerUtilisateurId(id);
            assertThat(suivi.getFollowerUtilisateurId()).isEqualTo(id);
        }

        @Test
        @DisplayName("setSuiviUtilisateurId / getSuiviUtilisateurId round-trips")
        void suiviUtilisateurId_roundTrips() {
            UUID id = UUID.randomUUID();
            MembreSuivi suivi = new MembreSuivi();
            suivi.setSuiviUtilisateurId(id);
            assertThat(suivi.getSuiviUtilisateurId()).isEqualTo(id);
        }

        @Test
        @DisplayName("follower and suivi IDs can be different")
        void followerAndSuivi_canBeDifferent() {
            UUID followerId = UUID.randomUUID();
            UUID suiviId    = UUID.randomUUID();
            MembreSuivi suivi = new MembreSuivi();
            suivi.setFollowerUtilisateurId(followerId);
            suivi.setSuiviUtilisateurId(suiviId);

            assertThat(suivi.getFollowerUtilisateurId()).isNotEqualTo(suivi.getSuiviUtilisateurId());
        }
    }

    // -------------------------------------------------------------------------
    // UUID id (inherited from BaseEntity)
    // -------------------------------------------------------------------------
    @Test
    @DisplayName("UUID id field is settable and gettable")
    void uuidId_settableAndGettable() {
        UUID id = UUID.randomUUID();
        MembreSuivi suivi = new MembreSuivi();
        suivi.setId(id);
        assertThat(suivi.getId()).isEqualTo(id);
    }

    // -------------------------------------------------------------------------
    // equals / hashCode
    // -------------------------------------------------------------------------
    @Test
    @DisplayName("two instances with the same field values are equal")
    void equals_sameValues_areEqual() {
        UUID followerId = UUID.randomUUID();
        UUID suiviId    = UUID.randomUUID();

        MembreSuivi a = new MembreSuivi(followerId, suiviId);
        MembreSuivi b = new MembreSuivi(followerId, suiviId);

        assertThat(a).isEqualTo(b);
        assertThat(a.hashCode()).isEqualTo(b.hashCode());
    }

    @Test
    @DisplayName("two instances with different follower IDs are not equal")
    void equals_differentFollowerId_notEqual() {
        UUID suiviId = UUID.randomUUID();
        MembreSuivi a = new MembreSuivi(UUID.randomUUID(), suiviId);
        MembreSuivi b = new MembreSuivi(UUID.randomUUID(), suiviId);

        assertThat(a).isNotEqualTo(b);
    }

    @Test
    @DisplayName("toString contains field values")
    void toString_containsFields() {
        UUID followerId = UUID.fromString("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
        MembreSuivi suivi = MembreSuivi.builder().followerUtilisateurId(followerId).build();
        assertThat(suivi.toString()).contains("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa");
    }
}
