import { AFRelationship } from 'pdf-lib';

import { PdfUtilities } from './pdf.utilities';
import { XML, XmlUtilities } from './xml.utilities';
import { BaseCompanyInfo, BaseInvoice } from '../models';

/**
 * Provides functionality for handling the german X-Rechnung format.
 */
export abstract class XRechnungUtilities {

    /**
     * Creates and attaches a factur-x xml to the invoice pdf at the given path.
     * @param pdfFilePath - The path of the invoice pdf to attach to.
     * @param invoice - The invoice data to generate the xml from.
     * @param currency - The currency code, eg. 'USD'.
     * @param companyInfo - Info about the seller.
     * @param tradeContact - The trade contact. Defaults to companyInfo.ceo.
     */
    static async attachXRechnung<Invoice extends BaseInvoice>(
        pdfFilePath: string,
        invoice: Invoice,
        currency: string,
        companyInfo: BaseCompanyInfo,
        tradeContact: string | undefined = companyInfo.ceo
    ): Promise<void> {
        const xmlBytes: Uint8Array = this.createXRechnungBytes(invoice, currency, companyInfo, tradeContact);
        const now: Date = new Date();
        await PdfUtilities.attach(pdfFilePath, xmlBytes, 'xrechnung.xml', {
            mimeType: 'text/xml',
            afRelationship: AFRelationship.Alternative,
            creationDate: now,
            modificationDate: now
        });
    }

    private static createXRechnungBytes(
        invoice: BaseInvoice,
        currency: string,
        companyInfo: BaseCompanyInfo,
        tradeContact: string | undefined = companyInfo.ceo
    ): Uint8Array {
        const xml: XML = XmlUtilities.createCrossIndustryInvoiceXml(
            invoice,
            currency,
            companyInfo,
            tradeContact,
            'urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0'
        );
        const xmlString: string = xml.end({ prettyPrint: true });
        const xmlBytes: Uint8Array = new TextEncoder().encode(xmlString);
        return xmlBytes;
    }
}