import { NextRequest, NextResponse } from 'next/server';

import { previewSetupCsvImport } from '@/features/setup/server/csv-preview.service';
import {
  BOOTSTRAP_OPTIONAL_TEMPLATE_FILES,
  BOOTSTRAP_REQUIRED_TEMPLATE_FILES,
  sanitizeCsvPreviewForResponse
} from '@/features/setup/server/setup-bootstrap.service';
import { readConfiguredSetupImportSource } from '@/features/setup/server/setup-import-source.service';
import { AuthError, requireSystemRole } from '@/lib/auth/session';
import type { CsvPreviewFileInput } from '@/features/setup/server/csv/types';

function isFile(value: FormDataEntryValue): value is File {
  return typeof value === 'object' && 'arrayBuffer' in value && 'name' in value;
}

async function readMultipartFiles(formData: FormData): Promise<CsvPreviewFileInput[]> {
  const uploadedFiles = Array.from(formData.values()).filter(isFile);

  return Promise.all(
    uploadedFiles.map(async (file) => ({
      fileName: file.name,
      bytes: new Uint8Array(await file.arrayBuffer())
    }))
  );
}

async function previewConfiguredDirectory(request: NextRequest) {
  const body = (await request.json().catch(() => ({}))) as { source?: string };

  if (body.source !== 'configured-directory') {
    return NextResponse.json({ message: 'Unsupported setup import preview source.' }, { status: 400 });
  }

  const source = await readConfiguredSetupImportSource({
    requiredFiles: BOOTSTRAP_REQUIRED_TEMPLATE_FILES,
    optionalFiles: BOOTSTRAP_OPTIONAL_TEMPLATE_FILES
  });

  if (source.report.errors.length > 0) {
    return NextResponse.json(
      { message: 'Configured setup import folder is not ready.', importSource: source.report },
      { status: 400 }
    );
  }

  const preview = await previewSetupCsvImport(source.files);
  return NextResponse.json({ ...sanitizeCsvPreviewForResponse(preview), importSource: source.report });
}

async function previewUploadedFiles(request: NextRequest) {
  const formData = await request.formData();
  const files = await readMultipartFiles(formData);

  if (files.length === 0) {
    return NextResponse.json(
      { message: 'Upload at least one setup CSV file using multipart/form-data.' },
      { status: 400 }
    );
  }

  const preview = await previewSetupCsvImport(files);
  return NextResponse.json(sanitizeCsvPreviewForResponse(preview));
}

export async function POST(request: NextRequest) {
  try {
    await requireSystemRole('super_admin');

    if (request.headers.get('content-type')?.includes('application/json')) {
      return await previewConfiguredDirectory(request);
    }

    return await previewUploadedFiles(request);
  } catch (error) {
    if (error instanceof AuthError) {
      return NextResponse.json({ message: error.message }, { status: error.status });
    }

    return NextResponse.json({ message: 'Unable to preview setup CSV import' }, { status: 500 });
  }
}
