import { createHash } from 'node:crypto';
import type { CsvPreviewFileResult, CsvPreviewResult, CsvPreviewRow } from './types';

export interface CsvCommitPlanRow {
  fileName: string;
  template: string;
  importOrder: number;
  row: CsvPreviewRow;
}

export interface CsvCommitPlanFile {
  fileName: string;
  template: string;
  importOrder: number;
  rows: CsvCommitPlanRow[];
}

export interface CsvCommitPlan {
  preview: CsvPreviewResult;
  files: CsvCommitPlanFile[];
  rows: CsvCommitPlanRow[];
  committedHash: string;
}

function stableRowPayload(file: CsvPreviewFileResult, row: CsvPreviewRow) {
  return {
    fileName: file.fileName,
    importOrder: file.importOrder,
    row: row.row,
    key: row.key,
    action: row.action,
    values: row.values
  };
}

export function buildCsvCommitPlan(preview: CsvPreviewResult): CsvCommitPlan {
  const files = preview.files
    .toSorted((left, right) => left.importOrder - right.importOrder || left.fileName.localeCompare(right.fileName))
    .map((file) => ({
      fileName: file.fileName,
      template: file.template,
      importOrder: file.importOrder,
      rows: file.rows
        .filter((row) => row.action !== 'error')
        .toSorted((left, right) => left.row - right.row)
        .map((row) => ({
          fileName: file.fileName,
          template: file.template,
          importOrder: file.importOrder,
          row
        }))
    }));

  const rows = files.flatMap((file) => file.rows);
  const committedHash = createHash('sha256')
    .update(
      JSON.stringify({
        previewHash: preview.previewHash,
        rows: preview.files.flatMap((file) => file.rows.map((row) => stableRowPayload(file, row)))
      })
    )
    .digest('hex');

  return { preview, files, rows, committedHash };
}
