import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Collectors;

/** Reportes sobre una lista de canciones, escritos con streams. */
public final class LibraryReports {

    private LibraryReports() {
    }

    /** Duración total (en segundos) de cada artista, por orden alfabético de artista. */
    public static Map<String, Integer> totalDurationByArtist(List<Song> songs) {
        return songs.stream()
                .collect(Collectors.groupingBy(Song::artist, TreeMap::new,
                        Collectors.summingInt(Song::seconds)));
    }

    /** Cuántas canciones tiene cada artista, por orden alfabético de artista. */
    public static Map<String, Long> songsPerArtist(List<Song> songs) {
        return songs.stream()
                .collect(Collectors.groupingBy(Song::artist, TreeMap::new, Collectors.counting()));
    }

    /** Los n artistas con más canciones; si empatan, por orden alfabético. */
    public static List<String> topArtists(List<Song> songs, int n) {
        return songsPerArtist(songs).entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue().reversed()
                        .thenComparing(Map.Entry.comparingByKey()))
                .limit(n)
                .map(Map.Entry::getKey)
                .toList();
    }

    /** La canción más larga, si la lista no está vacía. */
    public static Optional<Song> longest(List<Song> songs) {
        return songs.stream().max(Comparator.comparingInt(Song::seconds));
    }

    /** Los títulos de un artista, ordenados y separados por comas. */
    public static String titlesBy(List<Song> songs, String artist) {
        return songs.stream()
                .filter(s -> s.artist().equals(artist))
                .map(Song::title)
                .sorted()
                .collect(Collectors.joining(", "));
    }
}
