import assert from 'node:assert/strict';
import test from 'node:test';
import { PDFDocument } from '@pdfme/pdf-lib';
import type { ResolvedAssemblySource } from '../types';
import {
  getPdfPageCount,
  mergePdfBuffers,
  normalizeAssemblyBrand,
  normalizeAssemblyProductType,
  validateAssemblySourceOrdering,
} from './helpers';

async function createPdf(pageCount: number) {
  const document = await PDFDocument.create();

  for (let index = 0; index < pageCount; index += 1) {
    document.addPage([595, 842]);
  }

  return Buffer.from(await document.save());
}

function createSource(input: {
  role: string;
  order: number;
  pageCount: number;
}): Promise<ResolvedAssemblySource> {
  return createPdf(input.pageCount).then((buffer) => ({
    role: input.role,
    sourceType: 'generated',
    required: true,
    order: input.order,
    fileName: `${input.role}.pdf`,
    contentType: 'application/pdf',
    checksum: input.role,
    pageCount: input.pageCount,
    fileSize: buffer.byteLength,
    metadata: {},
    buffer,
  }));
}

test('normalizeAssemblyProductType aligns legacy quotation codes', () => {
  assert.equal(normalizeAssemblyProductType('dockdoor'), 'dock_door');
  assert.equal(normalizeAssemblyProductType('solarcell'), 'solar');
  assert.equal(normalizeAssemblyProductType('crane'), 'crane');
  assert.equal(normalizeAssemblyProductType('unknown'), 'all');
});

test('normalizeAssemblyBrand falls back to generic', () => {
  assert.equal(normalizeAssemblyBrand('alla'), 'alla');
  assert.equal(normalizeAssemblyBrand('onvalla'), 'onvalla');
  assert.equal(normalizeAssemblyBrand('unknown'), 'generic');
});

test('validateAssemblySourceOrdering rejects duplicate orders', () => {
  assert.throws(
    () =>
      validateAssemblySourceOrdering([
        {
          sourceType: 'generated',
          role: 'main',
          required: true,
          order: 1,
        },
        {
          sourceType: 'document_library',
          role: 'sla',
          required: true,
          order: 1,
          documentType: 'sla',
        },
      ]),
    /Duplicate assembly source order/,
  );
});

test('mergePdfBuffers preserves page order and page count', async () => {
  const sources = await Promise.all([
    createSource({ role: 'main', order: 1, pageCount: 2 }),
    createSource({ role: 'sla', order: 2, pageCount: 1 }),
    createSource({ role: 'warranty', order: 3, pageCount: 3 }),
  ]);

  const merged = await mergePdfBuffers(sources);
  const pageCount = await getPdfPageCount(merged, 'merged-test');

  assert.equal(pageCount, 6);
});

test('getPdfPageCount fails for invalid pdf source', async () => {
  await assert.rejects(
    () => getPdfPageCount(Buffer.from('not-a-pdf'), 'invalid-source'),
    /not a readable PDF document/,
  );
});
