/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

import type { CellValue } from '@ifc-lite/lists';
import { displayCell, type ExportModel } from './model';

function esc(s: string, delim: string): string {
  return /["\r\n]/.test(s) || s.includes(delim) ? `"${s.replace(/"/g, '""')}"` : s;
}

/**
 * CSV faithful to the configured columns. When grouped, a leading "Group"
 * column preserves the grouping as data (so it stays re-importable), rows are
 * ordered by group, and a TOTAL row carries the grand count + sums.
 */
export function toCsv(model: ExportModel, delimiter = ','): string {
  const grouped = model.groups !== null;
  const header = [...(grouped ? ['Group'] : []), ...model.columns.map((c) => c.label)];
  const lines = [header.map((h) => esc(h, delimiter)).join(delimiter)];

  const line = (groupLabel: string | null, values: CellValue[]) => {
    const cells = grouped ? [esc(groupLabel ?? '', delimiter)] : [];
    for (let i = 0; i < model.columns.length; i++) cells.push(esc(displayCell(values[i]), delimiter));
    return cells.join(delimiter);
  };

  if (grouped && model.groups) {
    for (const g of model.groups) for (const r of g.rows) lines.push(line(g.label, r));
  } else {
    for (const r of model.rows) lines.push(line(null, r));
  }

  if (model.sumColumnIds.length > 0) {
    const totalLabel = `TOTAL (${model.totals.count})`;
    const cells = grouped ? [esc(totalLabel, delimiter)] : [];
    for (let i = 0; i < model.columns.length; i++) {
      const c = model.columns[i];
      if (c.summed) cells.push(esc(displayCell(model.totals.sums[c.id]), delimiter));
      else if (!grouped && i === 0) cells.push(esc(totalLabel, delimiter));
      else cells.push('');
    }
    lines.push(cells.join(delimiter));
  }

  return lines.join('\r\n');
}
