/* eslint-disable stylistic/max-len */
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 factur-x conformance.
 */
export abstract class FacturXUtilities {
    /**
     * 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 attachFacturX<Invoice extends BaseInvoice>(
        pdfFilePath: string,
        invoice: Invoice,
        currency: string,
        companyInfo: BaseCompanyInfo,
        tradeContact: string | undefined = companyInfo.ceo
    ): Promise<void> {
        const xmlBytes: Uint8Array = this.createFacturXBytes(invoice, currency, companyInfo, tradeContact);
        const now: Date = new Date();
        await PdfUtilities.attach(pdfFilePath, xmlBytes, 'factur-x.xml', {
            mimeType: 'text/xml',
            afRelationship: AFRelationship.Alternative,
            creationDate: now,
            modificationDate: now
        });
    }

    /**
     * Adds the required factur-x metadata to the pdf file at the provided path.
     * @param pdfFilePath - The path of the invoice pdf.
     * @param author - The author that should be set.
     * @param id - The id to use in the metadata.
     * @param producer - The producer that should be set. Defaults to `lbx-invoice`.
     */
    static async addFacturXMetadata(pdfFilePath: string, author: string, id: string, producer: string = 'lbx-invoice'): Promise<void> {
        const invoiceNumber: string = pdfFilePath.split('/')[pdfFilePath.split('/').length];
        const now: Date = new Date();
        const whitespacePadding: string = '';

        // <dc:subject>
        //     <rdf:Bag>
        //         ${options.keywords.map(keyword => `<rdf:li>${keyword}</rdf:li>`).join('\n')}
        //     </rdf:Bag>
        // </dc:subject>

        // <xmp:CreatorTool>${options.creatorTool}</xmp:CreatorTool>

        const metadataXML: string = `
            <?xpacket begin="" id="${id}"?>
                <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.2-c001 63.139439, 2010/09/27-13:37:26        ">
                    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

                        <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">
                            <dc:format>application/pdf</dc:format>
                            <dc:creator>
                                <rdf:Seq>
                                    <rdf:li>${author}</rdf:li>
                                </rdf:Seq>
                            </dc:creator>
                            <dc:title>
                                <rdf:Alt>
                                    <rdf:li xml:lang="x-default">${invoiceNumber}</rdf:li>
                                </rdf:Alt>
                            </dc:title>
                            <!--Keywords-->
                        </rdf:Description>

                        <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
                            <!--Creator Tool-->
                            <xmp:CreateDate>${now.toISOString()}</xmp:CreateDate>
                            <xmp:ModifyDate>${now.toISOString()}</xmp:ModifyDate>
                            <xmp:MetadataDate>${now.toISOString()}</xmp:MetadataDate>
                        </rdf:Description>

                        <rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
                            <pdf:Producer>${producer}</pdf:Producer>
                        </rdf:Description>

                        <!-- The actual Factur-X properties; adjust if required -->
                        <rdf:Description rdf:about="" xmlns:fx="urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#">
                            <fx:ConformanceLevel>BASIC</fx:ConformanceLevel>
                            <fx:DocumentFileName>factur-x.xml</fx:DocumentFileName>
                            <fx:DocumentType>INVOICE</fx:DocumentType>
                            <fx:Version>1.0</fx:Version>
                        </rdf:Description>

                        <!-- PDF/A extension schema description for the Factur-X schema. It is crucial for PDF/A-3 conformance. Don't touch! -->
                        <rdf:Description rdf:about="" xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/" xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#" xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">
                            <pdfaExtension:schemas>
                                <rdf:Bag>
                                    <rdf:li rdf:parseType="Resource">
                                        <pdfaSchema:schema>Factur-X PDFA Extension Schema</pdfaSchema:schema>
                                        <pdfaSchema:namespaceURI>urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#</pdfaSchema:namespaceURI>
                                        <pdfaSchema:prefix>fx</pdfaSchema:prefix>
                                        <pdfaSchema:property>
                                            <rdf:Seq>
                                                <rdf:li rdf:parseType="Resource">
                                                    <pdfaProperty:name>DocumentFileName</pdfaProperty:name>
                                                    <pdfaProperty:valueType>Text</pdfaProperty:valueType>
                                                    <pdfaProperty:category>external</pdfaProperty:category>
                                                    <pdfaProperty:description>name of the embedded XML invoice file</pdfaProperty:description>
                                                </rdf:li>
                                                <rdf:li rdf:parseType="Resource">
                                                    <pdfaProperty:name>DocumentType</pdfaProperty:name>
                                                    <pdfaProperty:valueType>Text</pdfaProperty:valueType>
                                                    <pdfaProperty:category>external</pdfaProperty:category>
                                                    <pdfaProperty:description>INVOICE</pdfaProperty:description>
                                                </rdf:li>
                                                <rdf:li rdf:parseType="Resource">
                                                    <pdfaProperty:name>Version</pdfaProperty:name>
                                                    <pdfaProperty:valueType>Text</pdfaProperty:valueType>
                                                    <pdfaProperty:category>external</pdfaProperty:category>
                                                    <pdfaProperty:description>The actual version of the Factur-X XML schema</pdfaProperty:description>
                                                </rdf:li>
                                                <rdf:li rdf:parseType="Resource">
                                                    <pdfaProperty:name>ConformanceLevel</pdfaProperty:name>
                                                    <pdfaProperty:valueType>Text</pdfaProperty:valueType>
                                                    <pdfaProperty:category>external</pdfaProperty:category>
                                                    <pdfaProperty:description>The conformance level of the embedded Factur-X data</pdfaProperty:description>
                                                </rdf:li>
                                            </rdf:Seq>
                                        </pdfaSchema:property>
                                    </rdf:li>
                                </rdf:Bag>
                            </pdfaExtension:schemas>
                        </rdf:Description>

                    </rdf:RDF>
                </x:xmpmeta>
                ${whitespacePadding}
            <?xpacket end="w"?>
        `.trim();
        // TODO: enable
        await PdfUtilities['setXmpMetadata'](metadataXML, pdfFilePath);
    }

    private static createFacturXBytes(
        invoice: BaseInvoice,
        currency: string,
        companyInfo: BaseCompanyInfo,
        tradeContact: string | undefined = companyInfo.ceo
    ): Uint8Array {
        const xml: XML = XmlUtilities.createCrossIndustryInvoiceXml(invoice, currency, companyInfo, tradeContact);
        const xmlString: string = xml.end({ prettyPrint: true });
        const xmlBytes: Uint8Array = new TextEncoder().encode(xmlString);
        return xmlBytes;
    }
}