• Exports weekly metrics to CSV

    Creates a CSV export of listening statistics aggregated by calendar week, providing a medium-term view of listening patterns between daily and monthly aggregations. This export is particularly useful for analyzing weekly rhythms and patterns in listening behavior.

    The export includes:

    • Week identifiers in ISO format (YYYY-Wnn)
    • Total skip metrics for each week
    • Unique content exposure (tracks, artists)
    • Listening duration totals
    • Average skip rates per week
    • Day-of-week patterns (most skipped day)

    The function handles data retrieval, formatting, user prompts for save location, and file writing with comprehensive error handling throughout the process.

    Parameters

    • mainWindow: BrowserWindow

      The Electron BrowserWindow to attach dialogs to

    • OptionaltargetPath: string

      Optional pre-defined export path (bypasses user prompt)

    Returns Promise<{ success: boolean; message?: string; filePath?: string }>

    Promise resolving to object containing success status, message, and path

    // Export weekly metrics with user-selected location
    const result = await exportWeeklyMetricsToCSV(mainWindow);

    if (result.success) {
    console.log(`Weekly metrics saved to ${result.filePath}`);
    } else {
    console.error(`Export failed: ${result.message}`);
    }
    export async function exportWeeklyMetricsToCSV(
    mainWindow: BrowserWindow,
    targetPath?: string,
    ): Promise<{ success: boolean; message?: string; filePath?: string }> {
    try {
    // Get weekly metrics - this is a placeholder
    // Create a function to get weekly metrics similar to how we get daily metrics
    const weeklyMetricsFile = join(
    app.getPath("userData"),
    "statistics",
    "weekly_metrics.json",
    );

    let weeklyMetrics: Record<string, Record<string, unknown>> = {};
    if (existsSync(weeklyMetricsFile)) {
    weeklyMetrics = JSON.parse(readFileSync(weeklyMetricsFile, "utf-8"));
    }

    if (!weeklyMetrics || Object.keys(weeklyMetrics).length === 0) {
    return {
    success: false,
    message: "No weekly metrics data available to export",
    };
    }

    // Define headers for CSV
    const headers = {
    week: "Week",
    totalSkips: "Total Skips",
    uniqueTracks: "Unique Tracks",
    totalListeningTime: "Total Listening Time (ms)",
    avgSkipRate: "Average Skip Rate",
    mostSkippedDay: "Most Skipped Day",
    };

    // Prepare data for CSV
    const csvData = Object.entries(weeklyMetrics).map(([week, metrics]) => {
    return {
    week,
    totalSkips: metrics.totalSkips || 0,
    uniqueTracks: Array.isArray(metrics.uniqueTracks)
    ? metrics.uniqueTracks.length
    : metrics.uniqueTracks instanceof Set
    ? metrics.uniqueTracks.size
    : 0,
    totalListeningTime: metrics.totalListeningTimeMs || 0,
    avgSkipRate: metrics.avgSkipRate || 0,
    mostSkippedDay: metrics.mostSkippedDay || "",
    };
    });

    // Convert to CSV
    const csv = objectToCSV(csvData, headers);

    // Determine file path
    let filePath = targetPath;
    if (!filePath) {
    const timestamp = new Date()
    .toISOString()
    .replace(/:/g, "-")
    .split(".")[0];
    const defaultFileName = `weekly_metrics_${timestamp}.csv`;

    filePath = await promptForExportLocation(
    mainWindow,
    join(ensureExportDir(), defaultFileName),
    [{ name: "CSV Files", extensions: ["csv"] }],
    );

    if (!filePath) {
    return { success: false, message: "Export was canceled" };
    }
    }

    // Write the CSV file
    writeFileSync(filePath, csv);

    return {
    success: true,
    message: "Weekly metrics data exported successfully",
    filePath,
    };
    } catch (error) {
    console.error("Error exporting weekly metrics to CSV:", error);
    return {
    success: false,
    message: `Error exporting data: ${error instanceof Error ? error.message : "Unknown error"}`,
    };
    }
    }