import { tap, expect } from '@push.rocks/tapbundle';
import { FacturXDecoder } from '../ts/formats/cii/facturx/facturx.decoder.js';
import { FacturXEncoder } from '../ts/formats/cii/facturx/facturx.encoder.js';
import { FacturXValidator } from '../ts/formats/cii/facturx/facturx.validator.js';
import type { TInvoice } from '../ts/interfaces/common.js';
import { ValidationLevel } from '../ts/interfaces/common.js';
import * as fs from 'fs/promises';
import * as path from 'path';

// Test for circular encoding/decoding of Factur-X
tap.test('Factur-X should maintain data integrity through encode/decode cycle', async () => {
  // Create a sample invoice
  const invoice = createSampleInvoice();
  
  // Create encoder
  const encoder = new FacturXEncoder();
  
  // Encode to XML
  const xml = await encoder.encode(invoice);
  
  // Save XML for inspection
  const testDir = path.join(process.cwd(), 'test', 'output');
  await fs.mkdir(testDir, { recursive: true });
  await fs.writeFile(path.join(testDir, 'facturx-circular-encoded.xml'), xml);
  
  // Create decoder
  const decoder = new FacturXDecoder(xml);
  
  // Decode XML
  const decodedInvoice = await decoder.decode();
  
  // Check that decoded invoice is not null
  expect(decodedInvoice).toBeTruthy();
  
  // Check that key properties match
  expect(decodedInvoice.id).toEqual(invoice.id);
  expect(decodedInvoice.from.name).toEqual(invoice.from.name);
  expect(decodedInvoice.to.name).toEqual(invoice.to.name);
  
  // Create validator
  const validator = new FacturXValidator(xml);
  
  // Validate XML
  const result = validator.validate(ValidationLevel.SYNTAX);
  
  // Check that validation passed
  expect(result.valid).toBeTrue();
  expect(result.errors).toHaveLength(0);
});

/**
 * Creates a sample invoice for testing
 * @returns Sample invoice
 */
function createSampleInvoice(): TInvoice {
  return {
    type: 'invoice',
    id: 'INV-2023-001',
    invoiceId: 'INV-2023-001',
    invoiceType: 'debitnote',
    date: new Date('2023-01-01').getTime(),
    status: 'invoice',
    versionInfo: {
      type: 'final',
      version: '1.0.0'
    },
    language: 'en',
    incidenceId: 'INV-2023-001',
    from: {
      type: 'company',
      name: 'Supplier Company',
      description: 'Supplier',
      address: {
        streetName: 'Supplier Street',
        houseNumber: '123',
        postalCode: '12345',
        city: 'Supplier City',
        country: 'DE',
        countryCode: 'DE'
      },
      status: 'active',
      foundedDate: {
        year: 2000,
        month: 1,
        day: 1
      },
      registrationDetails: {
        vatId: 'DE123456789',
        registrationId: 'HRB12345',
        registrationName: 'Supplier Company GmbH'
      }
    },
    to: {
      type: 'company',
      name: 'Customer Company',
      description: 'Customer',
      address: {
        streetName: 'Customer Street',
        houseNumber: '456',
        postalCode: '54321',
        city: 'Customer City',
        country: 'DE',
        countryCode: 'DE'
      },
      status: 'active',
      foundedDate: {
        year: 2005,
        month: 6,
        day: 15
      },
      registrationDetails: {
        vatId: 'DE987654321',
        registrationId: 'HRB54321',
        registrationName: 'Customer Company GmbH'
      }
    },
    subject: 'Invoice INV-2023-001',
    items: [
      {
        position: 1,
        name: 'Product A',
        articleNumber: 'PROD-A',
        unitType: 'EA',
        unitQuantity: 2,
        unitNetPrice: 100,
        vatPercentage: 19
      },
      {
        position: 2,
        name: 'Service B',
        articleNumber: 'SERV-B',
        unitType: 'HUR',
        unitQuantity: 5,
        unitNetPrice: 80,
        vatPercentage: 19
      }
    ],
    dueInDays: 30,
    reverseCharge: false,
    currency: 'EUR',
    notes: ['Thank you for your business'],
    objectActions: []
  } as TInvoice;
}

// Run the tests
tap.start();
