• Analyzes time-based skip patterns from the collected data

    Returns Promise<
        | null
        | {
            hourlyDistribution: any[];
            peakSkipHours: number[];
            dayOfWeekDistribution: any[];
            timeOfDayDistribution: {
                morning: number;
                afternoon: number;
                evening: number;
                night: number;
            };
            patternsByArtist: Record<
                string,
                { hourlyDistribution: number[]; peakHours: number[] },
            >;
            lastUpdated: string;
        },
    >

    Object with time-based skip pattern analysis

    export async function analyzeTimeBasedPatterns() {
    try {
    const skippedTracks = await getSkippedTracks();

    // Object to hold time patterns
    const timePatterns = {
    hourlyDistribution: Array(24).fill(0),
    peakSkipHours: [] as number[],
    dayOfWeekDistribution: Array(7).fill(0), // Sunday is 0, Saturday is 6
    timeOfDayDistribution: {
    morning: 0, // 5:00 - 11:59
    afternoon: 0, // 12:00 - 16:59
    evening: 0, // 17:00 - 20:59
    night: 0, // 21:00 - 4:59
    },
    patternsByArtist: {} as Record<
    string,
    {
    hourlyDistribution: number[];
    peakHours: number[];
    }
    >,
    lastUpdated: new Date().toISOString(),
    };

    // Process each skipped track's skip events
    skippedTracks.forEach((track) => {
    if (!track.skipEvents || track.skipEvents.length === 0) return;

    // Initialize this artist in our patterns if not already present
    if (track.artist && !timePatterns.patternsByArtist[track.artist]) {
    timePatterns.patternsByArtist[track.artist] = {
    hourlyDistribution: Array(24).fill(0),
    peakHours: [],
    };
    }

    // Process each skip event
    track.skipEvents.forEach((event) => {
    // Skip if no timestamp
    if (!event.timestamp) return;

    // Create a safe date from the timestamp
    const skipDate = createSafeDate(event.timestamp);

    // Skip invalid dates
    if (!skipDate) {
    return;
    }

    const hour = skipDate.getHours();
    const dayOfWeek = skipDate.getDay();

    // Update hourly distribution
    timePatterns.hourlyDistribution[hour]++;

    // Update day of week distribution
    timePatterns.dayOfWeekDistribution[dayOfWeek]++;

    // Update time of day distribution
    if (hour >= 5 && hour < 12) {
    timePatterns.timeOfDayDistribution.morning++;
    } else if (hour >= 12 && hour < 17) {
    timePatterns.timeOfDayDistribution.afternoon++;
    } else if (hour >= 17 && hour < 21) {
    timePatterns.timeOfDayDistribution.evening++;
    } else {
    timePatterns.timeOfDayDistribution.night++;
    }

    // Update artist-specific pattern
    if (track.artist) {
    timePatterns.patternsByArtist[track.artist].hourlyDistribution[
    hour
    ]++;
    }
    });
    });

    // Find peak hours (hours with skip counts above average)
    const hourlyAverage =
    timePatterns.hourlyDistribution.reduce((sum, count) => sum + count, 0) /
    24;
    timePatterns.peakSkipHours = timePatterns.hourlyDistribution
    .map((count, hour) => ({ hour, count }))
    .filter((entry) => entry.count > hourlyAverage * 1.5) // 50% above average
    .sort((a, b) => b.count - a.count)
    .map((entry) => entry.hour);

    // Calculate peak hours for each artist
    Object.keys(timePatterns.patternsByArtist).forEach((artist) => {
    const artistHourly =
    timePatterns.patternsByArtist[artist].hourlyDistribution;
    const artistAverage =
    artistHourly.reduce((sum, count) => sum + count, 0) / 24;

    timePatterns.patternsByArtist[artist].peakHours = artistHourly
    .map((count, hour) => ({ hour, count }))
    .filter(
    (entry) => entry.count > artistAverage * 1.5 && entry.count >= 3,
    ) // Significant pattern
    .sort((a, b) => b.count - a.count)
    .map((entry) => entry.hour);
    });

    // Store the time patterns in a separate file
    const timePatternsFilePath = join(
    ensureStatisticsDir(),
    "time_based_patterns.json",
    );
    writeJsonSync(timePatternsFilePath, timePatterns, { spaces: 2 });

    return timePatterns;
    } catch (error) {
    console.error("Error analyzing time-based patterns:", error);
    return null;
    }
    }