• Exports match results in specified format with optional filtering; triggers browser download.

    Parameters

    Returns Promise<string>

    Promise resolving to filename of exported file.

    If export fails or document.body unavailable.

    export async function exportMatchResults(
    matches: MangaMatchResult[],
    format: ExportFormat,
    filters?: ExportFilterOptions,
    ): Promise<string> {
    console.info(
    `[Export] 📤 Exporting ${matches.length} match results as ${format}`,
    );

    // Apply filters if provided
    const filteredMatches = filters
    ? filterMatchResults(matches, filters)
    : matches;

    console.info(`[Export] 🔍 Filtered to ${filteredMatches.length} matches`);

    const metadata = buildExportMetadata(format, filteredMatches.length, filters);

    let filename: string;

    switch (format) {
    case "json": {
    let payload: unknown;

    // Apply field projection if fields are provided
    if (filters?.fields && filters.fields.length > 0) {
    const fields = filters.fields;
    const projectedMatches = filteredMatches.map((match) => {
    const flattened = flattenMatchResult(match);
    const projected: Record<string, unknown> = {};
    for (const fieldId of fields) {
    projected[fieldId] = flattened[fieldId];
    }
    return projected;
    });
    payload = {
    metadata,
    matches: projectedMatches,
    };
    } else {
    // Full payload
    payload = {
    metadata,
    matches: filteredMatches,
    };
    }

    filename = await exportToJson(
    payload as Record<string, unknown>,
    "match-results",
    );
    break;
    }
    case "csv": {
    const flattened = filteredMatches.map(flattenMatchResult);

    // Project to selected fields if provided
    let projectedData: Record<string, unknown>[];
    if (filters?.fields && filters.fields.length > 0) {
    const fields = filters.fields;
    projectedData = flattened.map((row) => {
    const projected: Record<string, unknown> = {};
    for (const fieldId of fields) {
    projected[fieldId] = row[fieldId];
    }
    return projected;
    });
    } else {
    projectedData = flattened as unknown as Record<string, unknown>[];
    }

    // Add metadata as comment rows at top of CSV
    const withMetadata = [
    { comment: `Exported: ${metadata.exportedAt}` },
    { comment: `App Version: v${metadata.appVersion}` },
    { comment: `Total Entries: ${metadata.totalEntries}` },
    { comment: "" }, // Empty row separator
    ...projectedData,
    ];
    filename = await exportToCSV(
    withMetadata as unknown as Record<string, unknown>[],
    "match-results",
    );
    break;
    }
    case "markdown": {
    const flattened = filteredMatches.map(flattenMatchResult);

    // Project to selected fields if provided
    let projectedData: Record<string, unknown>[];
    if (filters?.fields && filters.fields.length > 0) {
    const fields = filters.fields;
    projectedData = flattened.map((row) => {
    const projected: Record<string, unknown> = {};
    for (const fieldId of fields) {
    projected[fieldId] = row[fieldId];
    }
    return projected;
    });
    } else {
    projectedData = flattened as unknown as Record<string, unknown>[];
    }

    filename = exportToMarkdown(
    projectedData as unknown as Record<string, unknown>[],
    "match-results",
    metadata,
    );
    break;
    }
    default:
    throw new Error(`Unsupported export format: ${format}`);
    }
    console.info(`[Export] ✅ Successfully exported to ${filename}`);
    return filename;
    }