package com.wishurgift.service.dto.transformer;

import com.wishurgift.helper.WishlistMaker;
import com.wishurgift.persistence.entity.Wishlist;
import com.wishurgift.service.dto.WishlistDTO;
import com.wishurgift.service.dto.WishlistHeaderDTO;
import com.wishurgift.service.dto.WishlistSizeDTO;
import com.wishurgift.utils.Constant;
import org.junit.Test;

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

import static org.junit.Assert.*;

public class WishlistTransformerTest {

    @Test
    public void entityToDtoTest() {
        Wishlist expected = WishlistMaker.makeWishlist();

        WishlistDTO actual = WishlistTransformer.entityToDto(expected);
        assertEquals(expected.getId(), actual.getId());
        assertEquals(expected.getName(), actual.getName());
        assertEquals(ElementTransformer.entityToDto(expected.getElements()), actual.getElement());
        assertNull(actual.getUser());
        testSize(expected, actual.getSize());

        assertNull(WishlistTransformer.entityToDto((Wishlist) null));
    }

    @Test
    public void listEntityToDtoTest() {
        List<Wishlist> expected = new ArrayList<>();
        expected.add(WishlistMaker.makeWishlist());
        Wishlist wishlist = WishlistMaker.makeWishlist();
        wishlist.setId(2);
        wishlist.setPublic(true);
        expected.add(wishlist);
        wishlist = WishlistMaker.makeWishlist();
        wishlist.setId(3);
        wishlist.getElements().remove(0);
        expected.add(wishlist);

        List<WishlistDTO> actual = WishlistTransformer.entityToDto(expected);
        assertEquals(expected.size(), actual.size());
        actual.forEach(dto -> {
            Wishlist entity = expected.get((int) dto.getId() - 1);
            assertEquals(entity.getId(), dto.getId());
            assertEquals(entity.getName(), dto.getName());
            assertEquals(ElementTransformer.entityToDto(entity.getElements()), dto.getElement());
            assertNull(dto.getUser());
            testSize(entity, dto.getSize());
        });

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

        assertNull(WishlistTransformer.entityToDto((List<Wishlist>) null));
    }

    @Test
    public void entityToHeaderDtoTest() {
        Wishlist expected = WishlistMaker.makeWishlist();

        WishlistHeaderDTO actual = WishlistTransformer.entityToHeaderDto(expected);
        assertEquals(expected.getId(), actual.getId());
        assertEquals(expected.getName(), actual.getName());
        assertNull(actual.getUser());
        testSize(expected, actual.getSize());

        actual = WishlistTransformer.entityToHeaderDto(expected, true);
        assertEquals(expected.getId(), actual.getId());
        assertEquals(expected.getName(), actual.getName());
        assertNotNull(actual.getUser());
        testSize(expected, actual.getSize());

        assertNull(WishlistTransformer.entityToHeaderDto((Wishlist) null));
    }

    @Test
    public void listEntityToHeaderDtoTest() {
        List<Wishlist> expected = new ArrayList<>();
        expected.add(WishlistMaker.makeWishlist());
        Wishlist wishlist = WishlistMaker.makeWishlist();
        wishlist.setId(2);
        wishlist.setPublic(true);
        expected.add(wishlist);
        wishlist = WishlistMaker.makeWishlist();
        wishlist.setId(3);
        wishlist.getElements().remove(0);
        expected.add(wishlist);

        List<WishlistHeaderDTO> actual = WishlistTransformer.entityToHeaderDto(expected);
        assertEquals(expected.size(), actual.size());
        actual.forEach(dto -> {
            Wishlist entity = expected.get((int) dto.getId() - 1);
            assertEquals(entity.getId(), dto.getId());
            assertEquals(entity.getName(), dto.getName());
            assertNull(dto.getUser());
            testSize(entity, dto.getSize());
        });

        actual = WishlistTransformer.entityToHeaderDto(expected, true);
        assertEquals(expected.size(), actual.size());
        actual.forEach(dto -> {
            Wishlist entity = expected.get((int) dto.getId() - 1);
            assertEquals(entity.getId(), dto.getId());
            assertEquals(entity.getName(), dto.getName());
            assertNotNull(dto.getUser());
            testSize(entity, dto.getSize());
        });

        actual = WishlistTransformer.entityToHeaderDto(Collections.emptyList());
        assertTrue(actual.isEmpty());

        assertNull(WishlistTransformer.entityToHeaderDto((List<Wishlist>) null));
    }

    private void testSize(Wishlist entity, WishlistSizeDTO size) {
        assertEquals(entity.getElements().size(), size.getTotal());
        assertTrue(size.getTotal() >= size.getUnbuy());
        long unbuy = entity.getElements().stream()
                .map(elt -> Constant.Status.fromName(elt.getStatus()))
                .filter(elt -> elt != Constant.Status.PURCHASED)
                .count();
        assertEquals(unbuy, size.getUnbuy());
    }

}
