• Aggregates skip data by artist

    Returns Promise<
        Record<
            string,
            {
                artistId?: string;
                artistName: string;
                totalSkips: number;
                uniqueTracksSkipped: string[];
                skipsByType: Record<string, number>;
                manualSkips: number;
                autoSkips: number;
                skipRatio: number;
                averagePlayPercentage: number;
                mostSkippedTrack?: { id: string; name: string; skipCount: number };
            },
        >,
    >

    Object with artist-level skip metrics

    export async function aggregateArtistSkipMetrics() {
    try {
    const skippedTracks = await getSkippedTracks();
    const statistics = await getStatistics();

    // Create a map to hold artist metrics
    const artistMetrics: Record<
    string,
    {
    artistId?: string;
    artistName: string;
    totalSkips: number;
    uniqueTracksSkipped: string[];
    skipsByType: Record<string, number>;
    manualSkips: number;
    autoSkips: number;
    skipRatio: number;
    averagePlayPercentage: number;
    mostSkippedTrack?: {
    id: string;
    name: string;
    skipCount: number;
    };
    }
    > = {};

    // Process each skipped track
    skippedTracks.forEach((track) => {
    // Use artist name as identifier since artist ID might not always be available
    const artistKey = track.artist.toLowerCase();

    // Initialize this artist's metrics if needed
    if (!artistMetrics[artistKey]) {
    artistMetrics[artistKey] = {
    artistName: track.artist,
    totalSkips: 0,
    uniqueTracksSkipped: [],
    skipsByType: {
    preview: 0,
    standard: 0,
    near_end: 0,
    manual: 0,
    auto: 0,
    },
    manualSkips: 0,
    autoSkips: 0,
    skipRatio: 0,
    averagePlayPercentage: 0,
    };
    }

    // Update metrics
    artistMetrics[artistKey].totalSkips += track.skipCount || 0;

    // Add to unique tracks if not already included
    if (!artistMetrics[artistKey].uniqueTracksSkipped.includes(track.id)) {
    artistMetrics[artistKey].uniqueTracksSkipped.push(track.id);
    }

    // Update artist ID if available in statistics
    if (statistics.artistMetrics && statistics.artistMetrics[track.id]) {
    const artistId = statistics.artistMetrics[track.id].id;
    if (artistId) {
    artistMetrics[artistKey].artistId = artistId;
    }
    }

    // Add skip type information if available
    if (track.skipTypes) {
    Object.entries(track.skipTypes).forEach(([type, count]) => {
    // Add the skip count to the existing count or initialize if not present
    artistMetrics[artistKey].skipsByType[type] =
    (artistMetrics[artistKey].skipsByType[type] || 0) + count;
    });
    }

    // Add manual/auto skip information if available
    if (track.manualSkipCount) {
    artistMetrics[artistKey].manualSkips += track.manualSkipCount;
    }

    if (track.autoSkipCount) {
    artistMetrics[artistKey].autoSkips += track.autoSkipCount;
    }

    // Track most skipped track for this artist
    if (
    !artistMetrics[artistKey].mostSkippedTrack ||
    (track.skipCount || 0) >
    artistMetrics[artistKey].mostSkippedTrack.skipCount
    ) {
    artistMetrics[artistKey].mostSkippedTrack = {
    id: track.id,
    name: track.name,
    skipCount: track.skipCount || 0,
    };
    }

    // Calculate average play percentage if we have events with progress data
    if (track.skipEvents && track.skipEvents.length > 0) {
    const totalProgress = track.skipEvents.reduce(
    (sum, event) => sum + event.progress,
    0,
    );
    const averageProgress = totalProgress / track.skipEvents.length;

    // Update running average for the artist
    const currentTotal =
    artistMetrics[artistKey].averagePlayPercentage *
    artistMetrics[artistKey].uniqueTracksSkipped.length;
    const newTotal = currentTotal + averageProgress;
    artistMetrics[artistKey].averagePlayPercentage =
    newTotal / artistMetrics[artistKey].uniqueTracksSkipped.length;
    }
    });

    // Calculate skip ratios using total track play counts from statistics
    for (const [, metrics] of Object.entries(artistMetrics)) {
    const artistName = metrics.artistName;

    // Find artist in statistics to get total plays
    let totalPlays = 0;

    // Look for matching artist in statistics
    for (const artistId in statistics.artistMetrics) {
    const artistStats = statistics.artistMetrics[artistId];

    if (artistStats.name.toLowerCase() === artistName.toLowerCase()) {
    totalPlays = artistStats.tracksPlayed || 0;
    // Update artist ID if we didn't have it before
    if (!metrics.artistId) {
    metrics.artistId = artistId;
    }
    break;
    }
    }

    // Calculate skip ratio
    if (totalPlays > 0) {
    metrics.skipRatio = metrics.totalSkips / totalPlays;
    }
    }

    // Store the artist metrics in a separate file
    const artistMetricsFilePath = join(
    ensureStatisticsDir(),
    "artist_skip_metrics.json",
    );
    writeJsonSync(artistMetricsFilePath, artistMetrics, { spaces: 2 });

    return artistMetrics;
    } catch (error) {
    console.error("Error aggregating artist skip metrics:", error);
    return {};
    }
    }