package io.wealthwizards.appsynctesting.utils;

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

import java.util.Map;

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

@DisplayName("$util.list")
public class ListTest {
    @Test
    @DisplayName(".copyAndRetainAll")
    public void shouldImplementCopyAndRetainAll() {
        var list = new List();

        var toCopy = java.util.List.of("abc", "def", "hij", Map.of("123", "987"));
        var toRetain = java.util.List.of("def", Map.of("123", "987"));

        var actual = list.copyAndRetainAll(toCopy, toRetain);

        assertNotSame(toRetain, actual);
        assertEquals(toRetain, actual);
    }

    @Test
    @DisplayName(".copyAndRemoveAll")
    public void shouldImplementCopyAndRemoveAll() {
        var list = new List();

        var toCopy = java.util.List.of("abc", "def", Map.of(), Map.of("123", "987"));
        var toRemove = java.util.List.of("def", Map.of("123", "987"));

        var expected = java.util.List.of("abc", Map.of());
        var actual = list.copyAndRemoveAll(toCopy, toRemove);

        assertEquals(expected, actual);
    }

    @Nested
    @DisplayName(".sortList")
    class SortList {
        @Test
        @DisplayName("should sort objects by property")
        public void shouldSortObjects() {
            var list = new List();

            var toSort = java.util.List.of(
                    Map.of(
                            "description", "youngest",
                            "age", 5
                    ),
                    Map.of(
                            "description", "middle",
                            "age", 45
                    ),
                    Map.of(
                            "description", "oldest",
                            "age", 85
                    )
            );

            // the AWS docs don't match the actual behaviour here, they typo'd the property for the results
            var expected = java.util.List.of(
                    Map.of(
                            "description", "middle",
                            "age", 45
                    ),
                    Map.of(
                            "description", "oldest",
                            "age", 85
                    ),
                    Map.of(
                            "description", "youngest",
                            "age", 5
                    )
            );

            var actual = list.sortList(toSort, false, "description");

            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("should sort objects by descending property")
        public void shouldSortObjectsDescending() {
            var list = new List();

            var toSort = java.util.List.of(
                    Map.of(
                            "description", "youngest",
                            "age", 5
                    ),
                    Map.of(
                            "description", "middle",
                            "age", 45
                    ),
                    Map.of(
                            "description", "oldest",
                            "age", 85
                    )
            );

            var expected = java.util.List.of(
                    Map.of(
                            "description", "oldest",
                            "age", 85
                    ),
                    Map.of(
                            "description", "middle",
                            "age", 45
                    ),
                    Map.of(
                            "description", "youngest",
                            "age", 5
                    )
            );

            var actual = list.sortList(toSort, true, "age");

            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("shouldn't attempt to sort mixed types")
        public void shouldBeLazyWithMixedTypes() {
            var list = new List();

            var toSort = java.util.List.of(
                    12,
                    14.4f,
                    11L,
                    100000000L,
                    -12
            );

            var actual = list.sortList(toSort, false, "meaningless");

            assertEquals(toSort, actual);
        }

        @Test
        @DisplayName("should sort primitives")
        public void shouldSortPrimitives() {
            var list = new List();

            var toSort = java.util.List.of(
                    12,
                    14,
                    11,
                    121,
                    -12
            );

            var expected = java.util.List.of(
                    -12,
                    11,
                    12,
                    14,
                    121
            );

            var actual = list.sortList(toSort, false, "meaningless");

            assertEquals(expected, actual);
        }

        @Test
        @DisplayName("should sort primitives reversed")
        public void shouldSortPrimitivesReversed() {
            var list = new List();

            var toSort = java.util.List.of(
                    12,
                    14,
                    11,
                    121,
                    -12
            );

            var expected = java.util.List.of(
                    121,
                    14,
                    12,
                    11,
                    -12
            );

            var actual = list.sortList(toSort, true, "meaningless");

            assertEquals(expected, actual);
        }
    }
}
