import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;

class LibraryReportsTest {

    private final List<Song> library = Songs.library();

    @Test
    void totalDurationByArtistAddsEverySong() {
        Map<String, Integer> totals = LibraryReports.totalDurationByArtist(Songs.sample());
        assertEquals(Map.of("Costa Verde", 410, "Duna", 395, "Los Andinos", 435), totals);
    }

    @Test
    void topArtistsBreaksTiesAlphabetically() {
        // Costa Verde tiene 4; Duna y Los Andinos, 3 cada uno.
        assertEquals(List.of("Costa Verde", "Duna", "Los Andinos"), LibraryReports.topArtists(library, 3));
        assertEquals(List.of("Costa Verde"), LibraryReports.topArtists(library, 1));
    }

    @Test
    void longestOfEmptyListIsEmpty() {
        assertTrue(LibraryReports.longest(List.of()).isEmpty());
        assertEquals("Quebrada", LibraryReports.longest(library).orElseThrow().title());
    }

    @Test
    void titlesByUnknownArtistIsEmptyText() {
        assertEquals("Arena, Brisa, Oasis", LibraryReports.titlesBy(library, "Duna"));
        assertEquals("", LibraryReports.titlesBy(library, "Nadie"));
    }

    @Test
    void theArrowOfAssertThrowsIsALambda() {
        // La receta de siempre, con la lambda guardada en una variable de tipo Executable.
        Executable getFromEmpty = () -> LibraryReports.longest(List.of()).orElseThrow();
        assertThrows(NoSuchElementException.class, getFromEmpty);
    }
}
