package com.wishurgift.service.dto.transformer;

import com.wishurgift.helper.UserMaker;
import com.wishurgift.persistence.entity.User;
import com.wishurgift.service.dto.UserDTO;
import com.wishurgift.service.dto.UserLightDTO;
import com.wishurgift.utils.StringUtils;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static org.junit.Assert.*;

public class UserTransformerTest {

    @Test
    public void entityToDtoTest() {
        User expected = UserMaker.makeUser();

        UserDTO actual = UserTransformer.entityToDto(expected);
        assertEquals(expected.getId(), actual.getId());
        assertEquals(StringUtils.capitalize(expected.getName()), actual.getName());
        assertEquals(expected.getEmail(), actual.getEmail());
        assertEquals(expected.isPublic(), actual.isPublic());
        assertEquals(convertTag(expected), actual.getTag());

        assertNull(UserTransformer.entityToDto((User) null));
    }

    @Test
    public void listEntityToDtoTest() {
        User user1 = UserMaker.makeUser();
        User user2 = UserMaker.makeUser();
        user2.setId(2);
        user2.setTag("59062");
        user2.setPublic(true);
        User user3 = UserMaker.makeUser();
        user3.setId(3);
        user3.setName("Autrenom");
        user3.setEmail("email@differ.ent");
        List<User> expected = new ArrayList<>();
        expected.add(user1);
        expected.add(user2);
        expected.add(user3);

        List<UserDTO> actual = UserTransformer.entityToDto(expected);
        assertEquals(expected.size(), actual.size());
        actual.forEach(dto -> {
            User entity = expected.get((int) dto.getId() - 1);
            assertEquals(entity.getId(), dto.getId());
            assertEquals(StringUtils.capitalize(entity.getName()), dto.getName());
            assertEquals(entity.getEmail(), dto.getEmail());
            assertEquals(entity.isPublic(), dto.isPublic());
            assertEquals(convertTag(entity), dto.getTag());
        });

        actual = UserTransformer.entityToDto(Collections.emptyList());
        assertTrue(actual.isEmpty());

        assertNull(UserTransformer.entityToDto((List<User>) null));
    }

    @Test
    public void dtoToEntityTest() {
        UserDTO expected = UserMaker.makeUserDTO();

        User actual = UserTransformer.dtoToEntity(expected);
        assertEquals(expected.getId(), actual.getId());
        assertEquals(StringUtils.lower(expected.getName()), actual.getName());
        assertEquals(expected.getEmail(), actual.getEmail());
        assertEquals(expected.isPublic(), actual.isPublic());
        assertEquals(convertTag(expected), actual.getTag());
        assertNull(actual.getPassword());

        assertNull(UserTransformer.dtoToEntity((UserDTO) null));
    }

    @Test
    public void listDtoToEntityTest() {
        UserDTO user1 = UserMaker.makeUserDTO();
        UserDTO user2 = UserMaker.makeUserDTO();
        user2.setId(2);
        user2.setTag("taggy#59062");
        user2.setPublic(true);
        UserDTO user3 = UserMaker.makeUserDTO();
        user3.setId(3);
        user3.setName("Autrenom");
        user3.setEmail("email@differ.ent");
        List<UserDTO> expected = new ArrayList<>();
        expected.add(user1);
        expected.add(user2);
        expected.add(user3);

        List<User> actual = UserTransformer.dtoToEntity(expected);
        assertEquals(expected.size(), actual.size());
        actual.forEach(entity -> {
            UserDTO dto = expected.get((int) entity.getId() - 1);
            assertEquals(dto.getId(), entity.getId());
            assertEquals(StringUtils.lower(dto.getName()), entity.getName());
            assertEquals(dto.getEmail(), entity.getEmail());
            assertEquals(dto.isPublic(), entity.isPublic());
            assertEquals(convertTag(dto), entity.getTag());
            assertNull(entity.getPassword());
        });

        actual = UserTransformer.dtoToEntity(Collections.emptyList());
        assertTrue(actual.isEmpty());

        assertNull(UserTransformer.dtoToEntity((List<UserDTO>) null));
    }

    @Test
    public void converTagEntityToDtoTest() {
        String name = "name #yolo";
        String tag = "12345";
        String expected = "name_yolo#12345";

        assertEquals(expected, UserTransformer.convertTag(name, tag));
        assertNull(UserTransformer.convertTag(null, null));
        assertNull(UserTransformer.convertTag(name, null));
        assertNull(UserTransformer.convertTag(null, tag));
    }

    @Test
    public void convertTagDtoToEntityTest() {
        String tag = "name_yolo#12345";
        String expected = "12345";

        assertEquals(expected, UserTransformer.convertTag(tag));
        assertNull(UserTransformer.convertTag(null));
    }

    @Test
    public void entityToLightDtoTest() {
        User user = UserMaker.makeUser();

        UserLightDTO actual = UserTransformer.entityToLightDto(user);
        assertEquals(user.getId(), actual.getId());
        assertEquals(StringUtils.capitalize(user.getName()), actual.getName());
        assertEquals(convertTag(user), actual.getTag());

        assertNull(UserTransformer.entityToDto((User) null));
    }

    @Test
    public void listEntityToLightDtoTest() {
        User user1 = UserMaker.makeUser();
        User user2 = UserMaker.makeUser();
        user2.setId(2);
        user2.setTag("59062");
        user2.setPublic(true);
        User user3 = UserMaker.makeUser();
        user3.setId(3);
        user3.setName("Autrenom");
        user3.setEmail("email@differ.ent");
        List<User> expected = new ArrayList<>();
        expected.add(user1);
        expected.add(user2);
        expected.add(user3);

        List<UserLightDTO> actual = UserTransformer.entityToLightDto(expected);
        assertEquals(expected.size(), actual.size());
        actual.forEach(dto -> {
            User entity = expected.get((int) dto.getId() - 1);
            assertEquals(entity.getId(), dto.getId());
            assertEquals(StringUtils.capitalize(entity.getName()), dto.getName());
            assertEquals(convertTag(entity), dto.getTag());
        });

        actual = UserTransformer.entityToLightDto(Collections.emptyList());
        assertTrue(actual.isEmpty());

        assertNull(UserTransformer.entityToLightDto((List<User>) null));
    }

    private String convertTag(User user) {
        return user.getName().toLowerCase().replaceAll(" ", "_").replaceAll("#", "") + "#" + user.getTag();
    }

    private String convertTag(UserDTO dto) {
        return dto.getTag().split("#")[1];
    }

}
