package dev.lions.unionflow.server.api.dto.auth.request;

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

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

/**
 * Tests unitaires pour LoginRequest (record).
 * Couvre constructeur via builder, accesseurs, et tous les champs.
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-01
 */
@DisplayName("Tests LoginRequest")
class LoginRequestTest {

    @Nested
    @DisplayName("Builder et construction")
    class Builder {

        @Test
        @DisplayName("builder avec tous les champs")
        void testBuilderComplet() {
            LoginRequest request = LoginRequest.builder()
                .username("admin@test.com")
                .password("secret123")
                .typeCompte("ADMIN")
                .rememberMe(true)
                .build();

            assertThat(request.username()).isEqualTo("admin@test.com");
            assertThat(request.password()).isEqualTo("secret123");
            assertThat(request.typeCompte()).isEqualTo("ADMIN");
            assertThat(request.rememberMe()).isTrue();
        }

        @Test
        @DisplayName("builder avec champs minimum (rememberMe null)")
        void testBuilderMinimum() {
            LoginRequest request = LoginRequest.builder()
                .username("user@test.com")
                .password("pass123")
                .typeCompte("MEMBRE")
                .build();

            assertThat(request.username()).isEqualTo("user@test.com");
            assertThat(request.password()).isEqualTo("pass123");
            assertThat(request.typeCompte()).isEqualTo("MEMBRE");
            assertThat(request.rememberMe()).isNull();
        }

        @Test
        @DisplayName("builder avec rememberMe false")
        void testBuilderRememberMeFalse() {
            LoginRequest request = LoginRequest.builder()
                .username("test@test.com")
                .password("test123")
                .typeCompte("ADMIN_ENTITE")
                .rememberMe(false)
                .build();

            assertThat(request.rememberMe()).isFalse();
        }
    }

    @Nested
    @DisplayName("Accesseurs (record)")
    class Accesseurs {

        @Test
        @DisplayName("username() retourne la valeur")
        void testUsername() {
            LoginRequest request = LoginRequest.builder()
                .username("john.doe@test.com")
                .password("pass")
                .typeCompte("MEMBRE")
                .build();

            assertThat(request.username()).isEqualTo("john.doe@test.com");
        }

        @Test
        @DisplayName("password() retourne la valeur")
        void testPassword() {
            LoginRequest request = LoginRequest.builder()
                .username("user")
                .password("mySecretPass123!")
                .typeCompte("MEMBRE")
                .build();

            assertThat(request.password()).isEqualTo("mySecretPass123!");
        }

        @Test
        @DisplayName("typeCompte() retourne la valeur")
        void testTypeCompte() {
            LoginRequest request = LoginRequest.builder()
                .username("super@test.com")
                .password("pass")
                .typeCompte("SUPER_ADMIN")
                .build();

            assertThat(request.typeCompte()).isEqualTo("SUPER_ADMIN");
        }

        @Test
        @DisplayName("rememberMe() retourne la valeur")
        void testRememberMe() {
            LoginRequest request = LoginRequest.builder()
                .username("user")
                .password("pass")
                .typeCompte("MEMBRE")
                .rememberMe(true)
                .build();

            assertThat(request.rememberMe()).isTrue();
        }
    }

    @Nested
    @DisplayName("Equals et HashCode")
    class EqualsHashCode {

        @Test
        @DisplayName("equals retourne true pour même instance")
        void testEqualsMemeInstance() {
            LoginRequest request = LoginRequest.builder()
                .username("user")
                .password("pass")
                .typeCompte("MEMBRE")
                .build();

            assertThat(request).isEqualTo(request);
        }

        @Test
        @DisplayName("equals retourne true pour mêmes valeurs")
        void testEqualsMemeValeurs() {
            LoginRequest r1 = LoginRequest.builder()
                .username("user")
                .password("pass")
                .typeCompte("MEMBRE")
                .rememberMe(true)
                .build();

            LoginRequest r2 = LoginRequest.builder()
                .username("user")
                .password("pass")
                .typeCompte("MEMBRE")
                .rememberMe(true)
                .build();

            assertThat(r1).isEqualTo(r2);
            assertThat(r1.hashCode()).isEqualTo(r2.hashCode());
        }

        @Test
        @DisplayName("equals retourne false pour valeurs différentes")
        void testEqualsValeursDifferentes() {
            LoginRequest r1 = LoginRequest.builder()
                .username("user1")
                .password("pass")
                .typeCompte("MEMBRE")
                .build();

            LoginRequest r2 = LoginRequest.builder()
                .username("user2")
                .password("pass")
                .typeCompte("MEMBRE")
                .build();

            assertThat(r1).isNotEqualTo(r2);
        }

        @Test
        @DisplayName("equals retourne false pour null")
        void testEqualsNull() {
            LoginRequest request = LoginRequest.builder()
                .username("user")
                .password("pass")
                .typeCompte("MEMBRE")
                .build();

            assertThat(request).isNotEqualTo(null);
        }
    }

    @Nested
    @DisplayName("ToString")
    class ToString {

        @Test
        @DisplayName("toString contient tous les champs")
        void testToString() {
            LoginRequest request = LoginRequest.builder()
                .username("admin")
                .password("secret")
                .typeCompte("ADMIN")
                .rememberMe(true)
                .build();

            String str = request.toString();
            assertThat(str).contains("username=admin");
            assertThat(str).contains("password=secret");
            assertThat(str).contains("typeCompte=ADMIN");
            assertThat(str).contains("rememberMe=true");
        }
    }
}
