import { describe, expect, it } from "vitest";
import {
  MAX_BROWSER_SPREADSHEET_BYTES,
  assertSpreadsheetFile,
  parseSpreadsheet,
} from "./excel.js";

async function createWorkbookFile(
  rows: unknown[][],
  fileName = "spreadsheet.xlsx",
): Promise<File> {
  const ExcelJS = await import("exceljs");
  const workbook = new ExcelJS.Workbook();
  const worksheet = workbook.addWorksheet("Sheet1");

  for (const row of rows) {
    worksheet.addRow(row);
  }

  const buffer = await workbook.xlsx.writeBuffer();
  return new File([buffer], fileName, {
    type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  });
}

describe("excel import helpers", () => {
  it("parses csv files with quoted values and skips blank rows", async () => {
    const file = new File(
      ['name,role\n"Alice, A.",Engineer\n\nBob,Producer\n'],
      "people.csv",
      { type: "text/csv" },
    );

    await expect(parseSpreadsheet(file)).resolves.toEqual([
      { name: "Alice, A.", role: "Engineer" },
      { name: "Bob", role: "Producer" },
    ]);
  });

  it("parses xlsx files and normalizes date cells to ISO strings", async () => {
    const file = await createWorkbookFile([
      ["name", "startDate", "active"],
      ["Alice", new Date("2026-03-30T09:15:00.000Z"), true],
    ]);

    await expect(parseSpreadsheet(file)).resolves.toEqual([
      {
        name: "Alice",
        startDate: "2026-03-30T09:15:00.000Z",
        active: "true",
      },
    ]);
  });

  it("rejects duplicate headers in xlsx imports", async () => {
    const file = await createWorkbookFile([
      ["Name", "name"],
      ["Alice", "Producer"],
    ]);

    await expect(parseSpreadsheet(file)).rejects.toThrow('duplicate header "name"');
  });

  it("rejects legacy .xls uploads before parsing", () => {
    const file = new File(["legacy"], "legacy.xls", {
      type: "application/vnd.ms-excel",
    });

    expect(() => assertSpreadsheetFile(file)).toThrow(
      "Legacy .xls files are not supported.",
    );
  });

  it("rejects oversized spreadsheet uploads before parsing", () => {
    const file = new File([Buffer.alloc(MAX_BROWSER_SPREADSHEET_BYTES + 1)], "oversized.xlsx", {
      type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    });

    expect(() => assertSpreadsheetFile(file)).toThrow(
      `The selected file exceeds the ${MAX_BROWSER_SPREADSHEET_BYTES} byte limit`,
    );
  });
});
