Parse a Kenmei CSV export file.

export const parseKenmeiCsvExport = (
csvString: string,
options: Partial<KenmeiParseOptions> = {},
): KenmeiExport => {
const parseOptions = { ...DEFAULT_PARSE_OPTIONS, ...options };

try {
// Replace Windows line breaks with Unix style
const normalizedCsv = csvString.replace(/\r\n/g, "\n");

// Parse CSV rows properly, respecting quoted fields
const rows = parseCSVRows(normalizedCsv);

// Validate CSV structure and get headers
const headers = validateCsvStructure(rows);

// Parse manga entries
const manga: KenmeiManga[] = [];

// Skip the header row
for (let i = 1; i < rows.length; i++) {
const values = rows[i];

// Skip invalid rows
if (shouldSkipRow(values, headers, i)) {
continue;
}

// Create entry mapping from headers and values
const entry = createEntryMapping(headers, values);

// Extract all field values
const fieldValues = extractFieldValues(entry);

// Create manga entry
const mangaEntry = createMangaEntry(entry, fieldValues);
manga.push(mangaEntry);
}

// Process validation if enabled
processValidationResults(manga, parseOptions);

// Create the export object
const kenmeiExport: KenmeiExport = {
export_date: new Date().toISOString(),
user: {
username: "CSV Import User",
id: 0,
},
manga,
};

console.log(`Successfully parsed ${manga.length} manga entries from CSV`);
return kenmeiExport;
} catch (error) {
if (error instanceof Error) {
console.error("CSV parsing error:", error.message);
throw new Error(`Failed to parse CSV: ${error.message}`);
}
console.error("Unknown CSV parsing error");
throw new Error("Failed to parse CSV: Unknown error");
}
};