package dev.lions.user.manager.mapper;

import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.enums.user.StatutUser;
import org.junit.jupiter.api.Test;
import org.keycloak.representations.idm.UserRepresentation;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;

class UserMapperTest {

    @Test
    void testToDTO() {
        UserRepresentation rep = new UserRepresentation();
        rep.setId("1");
        rep.setUsername("jdoe");
        rep.setEmail("jdoe@example.com");
        rep.setEmailVerified(true);
        rep.setFirstName("John");
        rep.setLastName("Doe");
        rep.setEnabled(true);
        rep.setCreatedTimestamp(System.currentTimeMillis());

        Map<String, List<String>> attrs = Map.of(
                "phone_number", List.of("123"),
                "organization", List.of("Lions"),
                "department", List.of("IT"),
                "job_title", List.of("Dev"),
                "country", List.of("CI"),
                "city", List.of("Abidjan"),
                "locale", List.of("fr"),
                "timezone", List.of("UTC"));
        rep.setAttributes(attrs);

        UserDTO dto = UserMapper.toDTO(rep, "realm");

        assertNotNull(dto);
        assertEquals("1", dto.getId());
        assertEquals("jdoe", dto.getUsername());
        assertEquals("jdoe@example.com", dto.getEmail());
        assertTrue(dto.getEmailVerified());
        assertEquals("John", dto.getPrenom());
        assertEquals("Doe", dto.getNom());
        assertEquals(StatutUser.ACTIF, dto.getStatut());
        assertEquals("realm", dto.getRealmName());
        assertEquals("123", dto.getTelephone());
        assertEquals("Lions", dto.getOrganisation());
        assertEquals("IT", dto.getDepartement());
        assertEquals("Dev", dto.getFonction());
        assertEquals("CI", dto.getPays());
        assertEquals("Abidjan", dto.getVille());
        assertEquals("fr", dto.getLangue());
        assertEquals("UTC", dto.getTimezone());
        assertNotNull(dto.getDateCreation());

        assertNull(UserMapper.toDTO(null, "realm"));
    }

    @Test
    void testToDTOWithNullAttributes() {
        UserRepresentation rep = new UserRepresentation();
        rep.setId("1");
        rep.setEnabled(true);
        UserDTO dto = UserMapper.toDTO(rep, "realm");
        assertNotNull(dto);
        assertNull(dto.getTelephone()); // Attribute missing
    }

    @Test
    void testToDTOWithEmptyAttributes() {
        UserRepresentation rep = new UserRepresentation();
        rep.setEnabled(true);
        rep.setAttributes(Collections.emptyMap());
        UserDTO dto = UserMapper.toDTO(rep, "realm");
        assertNotNull(dto);
        assertNull(dto.getTelephone());
    }

    @Test
    void testToRepresentation() {
        UserDTO dto = UserDTO.builder()
                .id("1")
                .username("jdoe")
                .email("jdoe@example.com")
                .emailVerified(true)
                .prenom("John")
                .nom("Doe")
                .enabled(true)
                .telephone("123")
                .organisation("Lions")
                .departement("IT")
                .fonction("Dev")
                .pays("CI")
                .ville("Abidjan")
                .langue("fr")
                .timezone("UTC")
                .requiredActions(Collections.singletonList("UPDATE_PASSWORD"))
                .attributes(Map.of("custom", List.of("value")))
                .build();

        UserRepresentation rep = UserMapper.toRepresentation(dto);

        assertNotNull(rep);
        assertEquals("1", rep.getId());
        assertEquals("jdoe", rep.getUsername());
        assertEquals("jdoe@example.com", rep.getEmail());
        assertTrue(rep.isEmailVerified());
        assertEquals("John", rep.getFirstName());
        assertEquals("Doe", rep.getLastName());
        assertTrue(rep.isEnabled());

        assertNotNull(rep.getAttributes());
        assertEquals(List.of("123"), rep.getAttributes().get("phone_number"));
        assertEquals(List.of("Lions"), rep.getAttributes().get("organization"));
        assertEquals(List.of("value"), rep.getAttributes().get("custom"));

        assertNotNull(rep.getRequiredActions());
        assertTrue(rep.getRequiredActions().contains("UPDATE_PASSWORD"));

        assertNull(UserMapper.toRepresentation(null));
    }

    @Test
    void testToRepresentationValuesNull() {
        UserDTO dto = UserDTO.builder().username("jdoe").enabled(null).build();
        UserRepresentation rep = UserMapper.toRepresentation(dto);
        assertTrue(rep.isEnabled()); // Defaults to true in mapper
    }

    @Test
    void testToDTOList() {
        UserRepresentation rep = new UserRepresentation();
        rep.setEnabled(true);
        List<UserRepresentation> reps = Collections.singletonList(rep);
        List<UserDTO> dtos = UserMapper.toDTOList(reps, "realm");
        assertEquals(1, dtos.size());

        assertTrue(UserMapper.toDTOList(null, "realm").isEmpty());
    }

    @Test
    void testPrivateConstructor() throws Exception {
        java.lang.reflect.Constructor<UserMapper> constructor = UserMapper.class.getDeclaredConstructor();
        assertTrue(java.lang.reflect.Modifier.isPrivate(constructor.getModifiers()));
        constructor.setAccessible(true);
        assertNotNull(constructor.newInstance());
    }
}
