• Exports daily metrics to CSV

    Creates a time-series CSV export of listening and skip metrics aggregated by day, enabling temporal analysis of user behavior patterns. This export is particularly valuable for identifying trends and changes in listening habits over time.

    The export includes:

    • Date-based metrics (one row per day with active listening)
    • Daily skip counts and unique content metrics
    • Skip pattern analysis (sequential skips, peak hours)
    • Detailed skip type breakdown (preview, standard, near end)
    • Skip intention metrics (manual vs. automatic)

    The function handles the complete export workflow including data aggregation, format conversion, user interaction for save location, and file writing with comprehensive error handling.

    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 daily metrics for analysis
    try {
    const result = await exportDailyMetricsToCSV(mainWindow);
    if (result.success) {
    notifyUser("Export completed", `File saved to ${result.filePath}`);
    }
    } catch (err) {
    handleError("Failed to export daily metrics", err);
    }
    export async function exportDailyMetricsToCSV(
    mainWindow: BrowserWindow,
    targetPath?: string,
    ): Promise<{ success: boolean; message?: string; filePath?: string }> {
    try {
    // Get daily metrics
    const dailyMetrics = await aggregateDailySkipMetrics();

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

    // Define headers for CSV
    const headers = {
    date: "Date",
    totalSkips: "Total Skips",
    uniqueTracks: "Unique Tracks",
    sequentialSkips: "Sequential Skips",
    peakHour: "Peak Hour",
    previewSkips: "Preview Skips",
    standardSkips: "Standard Skips",
    nearEndSkips: "Near End Skips",
    manualSkips: "Manual Skips",
    autoSkips: "Auto Skips",
    };

    // Prepare data for CSV
    const csvData = Object.entries(dailyMetrics).map(([date, metrics]) => {
    const skipsByType = metrics.skipsByType || {
    preview: 0,
    standard: 0,
    near_end: 0,
    auto: 0,
    manual: 0,
    };

    return {
    date,
    totalSkips: metrics.tracksSkipped || 0,
    uniqueTracks: Array.isArray(metrics.uniqueTracks)
    ? metrics.uniqueTracks.length
    : metrics.uniqueTracks instanceof Set
    ? metrics.uniqueTracks.size
    : 0,
    sequentialSkips: metrics.sequentialSkips || 0,
    peakHour: metrics.peakHour || 0,
    previewSkips: skipsByType.preview || 0,
    standardSkips: skipsByType.standard || 0,
    nearEndSkips: skipsByType.near_end || 0,
    manualSkips: skipsByType.manual || 0,
    autoSkips: skipsByType.auto || 0,
    };
    });

    // 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 = `daily_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: "Daily metrics data exported successfully",
    filePath,
    };
    } catch (error) {
    console.error("Error exporting daily metrics to CSV:", error);
    return {
    success: false,
    message: `Error exporting data: ${error instanceof Error ? error.message : "Unknown error"}`,
    };
    }
    }