/**
 * File parsing for the importer — CSV (papaparse) and XLSX (ExcelJS) into a
 * uniform `{ headers, rows }` shape where every cell is a trimmed string.
 */
import ExcelJS from 'exceljs';
import Papa from 'papaparse';

import type { RawRow } from './types';

export interface ParsedFile {
  headers: string[];
  rows: RawRow[];
}

function cellToString(v: unknown): string {
  if (v === null || v === undefined) return '';
  if (typeof v === 'object') {
    // ExcelJS rich-text / hyperlink / formula cells.
    const o = v as { text?: unknown; result?: unknown; hyperlink?: unknown };
    if (typeof o.text === 'string') return o.text;
    if (o.result !== undefined) return String(o.result);
    if (typeof o.hyperlink === 'string') return o.hyperlink;
  }
  return String(v);
}

export function parseCsv(content: string): ParsedFile {
  const res = Papa.parse<Record<string, unknown>>(content, {
    header: true,
    skipEmptyLines: 'greedy',
    transformHeader: (h) => h.trim(),
  });
  const headers = (res.meta.fields ?? []).map((h) => h.trim()).filter(Boolean);
  const rows: RawRow[] = res.data.map((r) => {
    const out: RawRow = {};
    for (const h of headers) out[h] = cellToString(r[h]).trim();
    return out;
  });
  return { headers, rows };
}

export async function parseXlsx(buffer: Buffer): Promise<ParsedFile> {
  const wb = new ExcelJS.Workbook();
  await wb.xlsx.load(buffer as unknown as ArrayBuffer);
  const ws = wb.worksheets[0];
  if (!ws) return { headers: [], rows: [] };

  const headerRow = ws.getRow(1);
  const headers: string[] = [];
  const colIndex: number[] = [];
  headerRow.eachCell((cell, col) => {
    const h = cellToString(cell.value).trim();
    if (h) {
      headers.push(h);
      colIndex.push(col);
    }
  });

  const rows: RawRow[] = [];
  for (let r = 2; r <= ws.rowCount; r++) {
    const row = ws.getRow(r);
    const out: RawRow = {};
    let nonEmpty = false;
    headers.forEach((h, i) => {
      const v = cellToString(row.getCell(colIndex[i]!).value).trim();
      out[h] = v;
      if (v) nonEmpty = true;
    });
    if (nonEmpty) rows.push(out);
  }
  return { headers, rows };
}

export async function parseImportFile(filename: string, buffer: Buffer): Promise<ParsedFile> {
  if (/\.xlsx?$/i.test(filename)) return parseXlsx(buffer);
  return parseCsv(buffer.toString('utf8'));
}
