package dev.lions.user.manager.dto.user;

import dev.lions.user.manager.enums.user.StatutUser;
import org.junit.jupiter.api.Test;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;

class UserDTOTest {

    @Test
    void testGetNomComplet_withPrenomAndNom() {
        UserDTO user = new UserDTO();
        user.setPrenom("Jean");
        user.setNom("Dupont");
        user.setUsername("jdupont");
        assertEquals("Jean Dupont", user.getNomComplet());
    }

    @Test
    void testGetNomComplet_withNullPrenom() {
        UserDTO user = new UserDTO();
        user.setPrenom(null);
        user.setNom("Dupont");
        user.setUsername("jdupont");
        assertEquals("jdupont", user.getNomComplet());
    }

    @Test
    void testGetNomComplet_withNullNom() {
        UserDTO user = new UserDTO();
        user.setPrenom("Jean");
        user.setNom(null);
        user.setUsername("jdupont");
        assertEquals("jdupont", user.getNomComplet());
    }

    @Test
    void testGetNomComplet_withBothNull() {
        UserDTO user = new UserDTO();
        user.setPrenom(null);
        user.setNom(null);
        user.setUsername("jdupont");
        assertEquals("jdupont", user.getNomComplet());
    }

    @Test
    void testIsActif_true() {
        UserDTO user = new UserDTO();
        user.setStatut(StatutUser.ACTIF);
        user.setEnabled(true);
        assertTrue(user.isActif());
    }

    @Test
    void testIsActif_falseWhenNotActif() {
        UserDTO user = new UserDTO();
        user.setStatut(StatutUser.INACTIF);
        user.setEnabled(true);
        assertFalse(user.isActif());
    }

    @Test
    void testIsActif_falseWhenNotEnabled() {
        UserDTO user = new UserDTO();
        user.setStatut(StatutUser.ACTIF);
        user.setEnabled(false);
        assertFalse(user.isActif());
    }

    @Test
    void testIsActif_falseWhenEnabledNull() {
        UserDTO user = new UserDTO();
        user.setStatut(StatutUser.ACTIF);
        user.setEnabled(null);
        assertFalse(user.isActif());
    }

    @Test
    void testIsExpire_true() {
        UserDTO user = new UserDTO();
        user.setDateExpiration(LocalDateTime.now().minusDays(1));
        assertTrue(user.isExpire());
    }

    @Test
    void testIsExpire_false() {
        UserDTO user = new UserDTO();
        user.setDateExpiration(LocalDateTime.now().plusDays(1));
        assertFalse(user.isExpire());
    }

    @Test
    void testIsExpire_nullDate() {
        UserDTO user = new UserDTO();
        user.setDateExpiration(null);
        assertFalse(user.isExpire());
    }

    @Test
    void testHasRequiredActions_true() {
        UserDTO user = new UserDTO();
        user.setRequiredActions(Arrays.asList("UPDATE_PASSWORD", "VERIFY_EMAIL"));
        assertTrue(user.hasRequiredActions());
    }

    @Test
    void testHasRequiredActions_empty() {
        UserDTO user = new UserDTO();
        user.setRequiredActions(Collections.emptyList());
        assertFalse(user.hasRequiredActions());
    }

    @Test
    void testHasRequiredActions_null() {
        UserDTO user = new UserDTO();
        user.setRequiredActions(null);
        assertFalse(user.hasRequiredActions());
    }

    @Test
    void testBuilderAndAllFields() {
        LocalDateTime now = LocalDateTime.now();
        Map<String, List<String>> clientRoles = new HashMap<>();
        clientRoles.put("app", Arrays.asList("user", "admin"));
        Map<String, List<String>> attributes = new HashMap<>();
        attributes.put("custom", Collections.singletonList("value"));

        List<UserDTO.FederatedIdentityDTO> fedIds = Collections.singletonList(
                UserDTO.FederatedIdentityDTO.builder()
                        .identityProvider("google")
                        .userId("google-123")
                        .userName("user@gmail.com")
                        .build());

        UserDTO user = UserDTO.builder()
                .id("uuid-123")
                .dateCreation(now)
                .dateModification(now)
                .creeParUsername("admin")
                .modifieParUsername("admin")
                .version(1L)
                .username("jdupont")
                .email("jean.dupont@lions.dev")
                .emailVerified(true)
                .prenom("Jean")
                .nom("Dupont")
                .statut(StatutUser.ACTIF)
                .enabled(true)
                .telephone("+225 07 12 34 56 78")
                .organisation("Lions Dev")
                .departement("IT")
                .fonction("Developer")
                .pays("Côte d'Ivoire")
                .ville("Abidjan")
                .langue("fr")
                .timezone("Africa/Abidjan")
                .realmName("btpxpress")
                .realmRoles(Arrays.asList("user", "admin"))
                .clientRoles(clientRoles)
                .groups(Arrays.asList("group1", "group2"))
                .derniereConnexion(now)
                .dateExpiration(now.plusYears(1))
                .dateVerrouillage(null)
                .attributes(attributes)
                .requiredActions(Collections.singletonList("UPDATE_PASSWORD"))
                .federatedIdentityProvider("google")
                .federatedIdentities(fedIds)
                .temporaryPassword("temp123")
                .temporaryPasswordFlag(true)
                .activeSessions(2)
                .failedLoginAttempts(0)
                .raisonModification("Update")
                .commentaires("Test user")
                .build();

        assertEquals("uuid-123", user.getId());
        assertNotNull(user.getDateCreation());
        assertNotNull(user.getDateModification());
        assertEquals("admin", user.getCreeParUsername());
        assertEquals("admin", user.getModifieParUsername());
        assertEquals(1L, user.getVersion());
        assertEquals("jdupont", user.getUsername());
        assertEquals("jean.dupont@lions.dev", user.getEmail());
        assertTrue(user.getEmailVerified());
        assertEquals("Jean", user.getPrenom());
        assertEquals("Dupont", user.getNom());
        assertEquals(StatutUser.ACTIF, user.getStatut());
        assertTrue(user.getEnabled());
        assertEquals("+225 07 12 34 56 78", user.getTelephone());
        assertEquals("Lions Dev", user.getOrganisation());
        assertEquals("IT", user.getDepartement());
        assertEquals("Developer", user.getFonction());
        assertEquals("Côte d'Ivoire", user.getPays());
        assertEquals("Abidjan", user.getVille());
        assertEquals("fr", user.getLangue());
        assertEquals("Africa/Abidjan", user.getTimezone());
        assertEquals("btpxpress", user.getRealmName());
        assertEquals(2, user.getRealmRoles().size());
        assertEquals(1, user.getClientRoles().size());
        assertEquals(2, user.getGroups().size());
        assertNotNull(user.getDerniereConnexion());
        assertNotNull(user.getDateExpiration());
        assertNull(user.getDateVerrouillage());
        assertEquals(1, user.getAttributes().size());
        assertEquals(1, user.getRequiredActions().size());
        assertEquals("google", user.getFederatedIdentityProvider());
        assertEquals(1, user.getFederatedIdentities().size());
        assertEquals("temp123", user.getTemporaryPassword());
        assertTrue(user.getTemporaryPasswordFlag());
        assertEquals(2, user.getActiveSessions());
        assertEquals(0, user.getFailedLoginAttempts());
        assertEquals("Update", user.getRaisonModification());
        assertEquals("Test user", user.getCommentaires());
    }

    @Test
    void testEqualsAndHashCode() {
        UserDTO user1 = UserDTO.builder().id("uuid-123").username("jdupont").build();
        UserDTO user2 = UserDTO.builder().id("uuid-123").username("jdupont").build();
        UserDTO user3 = UserDTO.builder().id("uuid-456").username("other").build();

        assertEquals(user1, user2);
        assertEquals(user1.hashCode(), user2.hashCode());
        assertNotEquals(user1, user3);
    }

    @Test
    void testToString() {
        UserDTO user = UserDTO.builder().username("jdupont").email("test@test.com").build();
        String str = user.toString();
        assertNotNull(str);
        assertTrue(str.contains("jdupont"));
        assertTrue(str.contains("test@test.com"));
    }

    @Test
    void testFederatedIdentityDTO() {
        UserDTO.FederatedIdentityDTO fed = new UserDTO.FederatedIdentityDTO();
        fed.setIdentityProvider("google");
        fed.setUserId("user-123");
        fed.setUserName("user@gmail.com");

        assertEquals("google", fed.getIdentityProvider());
        assertEquals("user-123", fed.getUserId());
        assertEquals("user@gmail.com", fed.getUserName());

        // Test equals/hashCode/toString
        UserDTO.FederatedIdentityDTO fed2 = UserDTO.FederatedIdentityDTO.builder()
                .identityProvider("google")
                .userId("user-123")
                .userName("user@gmail.com")
                .build();
        assertEquals(fed, fed2);
        assertEquals(fed.hashCode(), fed2.hashCode());
        assertNotNull(fed.toString());
    }

    @Test
    void testFederatedIdentityDTO_AllArgsConstructor() {
        UserDTO.FederatedIdentityDTO fed = new UserDTO.FederatedIdentityDTO("google", "user-123", "user@gmail.com");
        assertEquals("google", fed.getIdentityProvider());
        assertEquals("user-123", fed.getUserId());
        assertEquals("user@gmail.com", fed.getUserName());
    }

    @Test
    void testNoArgsConstructor() {
        UserDTO user = new UserDTO();
        assertNull(user.getUsername());
        assertNull(user.getEmail());
    }

    @Test
    void testAllArgsConstructor() {
        LocalDateTime now = LocalDateTime.now();
        Map<String, List<String>> clientRoles = new HashMap<>();
        Map<String, List<String>> attributes = new HashMap<>();
        List<UserDTO.FederatedIdentityDTO> fedIds = Collections.emptyList();
        List<String> roles = Collections.emptyList();
        List<String> groups = Collections.emptyList();
        List<String> actions = Collections.emptyList();

        UserDTO user = new UserDTO(
                "username", "email@test.com", true, "Jean", "Dupont",
                StatutUser.ACTIF, true, "phone", "org", "dept", "func",
                "pays", "ville", "fr", "UTC", "realm", roles, clientRoles,
                groups, now, now, now, attributes, actions, "google", fedIds,
                "temppass", true, 1, 0, "reason", "comments");

        assertEquals("username", user.getUsername());
        assertEquals("email@test.com", user.getEmail());
        assertTrue(user.getEmailVerified());
        assertEquals("Jean", user.getPrenom());
        assertEquals("Dupont", user.getNom());
        assertEquals(StatutUser.ACTIF, user.getStatut());
        assertTrue(user.getEnabled());
    }
}
