import { tap, expect } from '@push.rocks/tapbundle';
import { XInvoice } from '../ts/classes.xinvoice.js';
import { ValidationLevel } from '../ts/interfaces/common.js';
import type { ExportFormat } from '../ts/interfaces/common.js';

// Basic XInvoice tests
tap.test('XInvoice should have the correct default properties', async () => {
  const xinvoice = new XInvoice();
  
  expect(xinvoice.type).toEqual('invoice');
  expect(xinvoice.invoiceType).toEqual('debitnote');
  expect(xinvoice.status).toEqual('invoice');
  expect(xinvoice.from).toBeTruthy();
  expect(xinvoice.to).toBeTruthy();
  expect(xinvoice.items).toBeArray();
  expect(xinvoice.currency).toEqual('EUR');
});

// Test XML export functionality
tap.test('XInvoice should export XML in the correct format', async () => {
  const xinvoice = new XInvoice();
  xinvoice.id = 'TEST-XML-EXPORT';
  xinvoice.invoiceId = 'TEST-XML-EXPORT';
  xinvoice.from.name = 'Test Seller';
  xinvoice.to.name = 'Test Buyer';
  
  // Add an item
  xinvoice.items.push({
    position: 1,
    name: 'Test Product',
    articleNumber: 'TP-001',
    unitType: 'EA',
    unitQuantity: 2,
    unitNetPrice: 100,
    vatPercentage: 19
  });
  
  // Export as Factur-X
  const xml = await xinvoice.exportXml('facturx');
  
  // Check that the XML contains the expected elements
  expect(xml).toInclude('CrossIndustryInvoice');
  expect(xml).toInclude('TEST-XML-EXPORT');
  expect(xml).toInclude('Test Seller');
  expect(xml).toInclude('Test Buyer');
  expect(xml).toInclude('Test Product');
});

// Test XML loading functionality
tap.test('XInvoice should load XML correctly', async () => {
  // Create a sample XML string
  const sampleXml = `<?xml version="1.0" encoding="UTF-8"?>
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
  xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
  xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
  <rsm:ExchangedDocumentContext>
    <ram:GuidelineSpecifiedDocumentContextParameter>
      <ram:ID>urn:cen.eu:en16931:2017</ram:ID>
    </ram:GuidelineSpecifiedDocumentContextParameter>
  </rsm:ExchangedDocumentContext>
  <rsm:ExchangedDocument>
    <ram:ID>TEST-XML-LOAD</ram:ID>
    <ram:TypeCode>380</ram:TypeCode>
    <ram:IssueDateTime>
      <udt:DateTimeString format="102">20230101</udt:DateTimeString>
    </ram:IssueDateTime>
  </rsm:ExchangedDocument>
  <rsm:SupplyChainTradeTransaction>
    <ram:ApplicableHeaderTradeAgreement>
      <ram:SellerTradeParty>
        <ram:Name>XML Seller</ram:Name>
        <ram:PostalTradeAddress>
          <ram:LineOne>Seller Street</ram:LineOne>
          <ram:LineTwo>123</ram:LineTwo>
          <ram:PostcodeCode>12345</ram:PostcodeCode>
          <ram:CityName>Seller City</ram:CityName>
          <ram:CountryID>DE</ram:CountryID>
        </ram:PostalTradeAddress>
      </ram:SellerTradeParty>
      <ram:BuyerTradeParty>
        <ram:Name>XML Buyer</ram:Name>
        <ram:PostalTradeAddress>
          <ram:LineOne>Buyer Street</ram:LineOne>
          <ram:LineTwo>456</ram:LineTwo>
          <ram:PostcodeCode>54321</ram:PostcodeCode>
          <ram:CityName>Buyer City</ram:CityName>
          <ram:CountryID>DE</ram:CountryID>
        </ram:PostalTradeAddress>
      </ram:BuyerTradeParty>
    </ram:ApplicableHeaderTradeAgreement>
    <ram:ApplicableHeaderTradeSettlement>
      <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
    </ram:ApplicableHeaderTradeSettlement>
  </rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>`;

  // Create XInvoice from XML
  const xinvoice = await XInvoice.fromXml(sampleXml);
  
  // Check that the XInvoice instance has the expected properties
  expect(xinvoice.id).toEqual('TEST-XML-LOAD');
  expect(xinvoice.from.name).toEqual('XML Seller');
  expect(xinvoice.to.name).toEqual('XML Buyer');
  expect(xinvoice.currency).toEqual('EUR');
});

// Test circular encoding/decoding
tap.test('XInvoice should maintain data integrity through export/import cycle', async () => {
  // Create a sample invoice
  const originalInvoice = new XInvoice();
  originalInvoice.id = 'TEST-CIRCULAR';
  originalInvoice.invoiceId = 'TEST-CIRCULAR';
  originalInvoice.from.name = 'Circular Seller';
  originalInvoice.to.name = 'Circular Buyer';
  
  // Add an item
  originalInvoice.items.push({
    position: 1,
    name: 'Circular Product',
    articleNumber: 'CP-001',
    unitType: 'EA',
    unitQuantity: 3,
    unitNetPrice: 150,
    vatPercentage: 19
  });
  
  // Export as Factur-X
  const xml = await originalInvoice.exportXml('facturx');
  
  // Create a new XInvoice from the XML
  const importedInvoice = await XInvoice.fromXml(xml);
  
  // Check that key properties match
  expect(importedInvoice.id).toEqual(originalInvoice.id);
  expect(importedInvoice.from.name).toEqual(originalInvoice.from.name);
  expect(importedInvoice.to.name).toEqual(originalInvoice.to.name);
  
  // Check that items match
  expect(importedInvoice.items).toHaveLength(1);
  expect(importedInvoice.items[0].name).toEqual('Circular Product');
  expect(importedInvoice.items[0].unitQuantity).toEqual(3);
  expect(importedInvoice.items[0].unitNetPrice).toEqual(150);
});

// Test validation
tap.test('XInvoice should validate XML correctly', async () => {
  const xinvoice = new XInvoice();
  xinvoice.id = 'TEST-VALIDATION';
  xinvoice.invoiceId = 'TEST-VALIDATION';
  xinvoice.from.name = 'Validation Seller';
  xinvoice.to.name = 'Validation Buyer';
  
  // Export as Factur-X
  const xml = await xinvoice.exportXml('facturx');
  
  // Set the XML string for validation
  xinvoice['xmlString'] = xml;
  
  // Validate the XML
  const result = await xinvoice.validate(ValidationLevel.SYNTAX);
  
  // Check that validation passed
  expect(result.valid).toBeTrue();
  expect(result.errors).toHaveLength(0);
});

// Run the tests
tap.start();
