import 'server-only';

import path from 'node:path';
import { buildCsvPreviewBatchIndex } from './csv/dependency-resolver';
import { parseCsvFile } from './csv/parser';
import { buildFileResult, buildPreviewResult } from './csv/preview-builder';
import {
  findTemplateByFileName,
  getCsvTemplateRegistry,
  isUnsupportedTemplate
} from './csv/template-registry';
import type {
  CsvParsedFile,
  CsvPreviewError,
  CsvPreviewFileInput,
  CsvPreviewResult
} from './csv/types';
import { validateCsvPreviewFile } from './csv/validator';

function templateDetectionError(fileName: string, code: string, message: string, suggestedFix: string): CsvParsedFile {
  const file = path.basename(fileName);
  const error: CsvPreviewError = {
    file,
    row: 1,
    column: '__file__',
    code,
    message,
    suggestedFix
  };

  return {
    fileName: file,
    template: {
      file,
      template: 'unknown',
      seedType: 'unknown',
      importOrder: Number.MAX_SAFE_INTEGER,
      supported: false,
      requiredColumns: [],
      description: 'Unknown template',
      expectedHeaders: []
    },
    headers: [],
    rows: [],
    errors: [error],
    warnings: []
  };
}

export async function previewSetupCsvImport(files: CsvPreviewFileInput[]): Promise<CsvPreviewResult> {
  const registry = await getCsvTemplateRegistry();
  const parsedFiles: CsvParsedFile[] = [];

  for (const input of files) {
    const fileName = path.basename(input.fileName);
    const template = findTemplateByFileName(registry, fileName);

    if (!template) {
      parsedFiles.push(
        templateDetectionError(
          fileName,
          isUnsupportedTemplate(registry, fileName) ? 'UNSUPPORTED_TEMPLATE' : 'UNKNOWN_TEMPLATE',
          isUnsupportedTemplate(registry, fileName)
            ? 'CSV template is known but not supported by the setup import engine.'
            : 'CSV file does not match any registered setup template.',
          'Use one of the supported files from setup/templates/templates.json.'
        )
      );
      continue;
    }

    if (!template.supported) {
      parsedFiles.push(
        templateDetectionError(
          fileName,
          'UNSUPPORTED_TEMPLATE',
          'CSV template is registered but not supported.',
          'Remove this file from the preview upload.'
        )
      );
      continue;
    }

    parsedFiles.push(parseCsvFile({ fileName, bytes: input.bytes, template }));
  }

  const uploadCounts = new Map<string, number>();
  parsedFiles.forEach((file) => {
    uploadCounts.set(file.template.file, (uploadCounts.get(file.template.file) ?? 0) + 1);
  });
  parsedFiles.forEach((file) => {
    if (uploadCounts.get(file.template.file)! > 1 && file.template.supported) {
      file.errors.push({
        file: file.fileName,
        row: 1,
        column: '__file__',
        code: 'DUPLICATE_FILE',
        message: `Template ${file.template.file} was uploaded more than once.`,
        suggestedFix: 'Upload only one file for each setup template.'
      });
    }
  });

  const sortedFiles = parsedFiles.toSorted((left, right) => left.template.importOrder - right.template.importOrder);
  const batch = buildCsvPreviewBatchIndex(sortedFiles.filter((file) => file.template.supported));
  const fileResults = [];

  for (const file of sortedFiles) {
    const rows = await validateCsvPreviewFile(file, batch);
    fileResults.push(
      buildFileResult({
        fileName: file.fileName,
        template: file.template.template,
        importOrder: file.template.importOrder,
        rows
      })
    );
  }

  return buildPreviewResult(fileResults);
}
