import PDFDocument from 'pdfkit';
import { SwissQRBill } from 'swissqrbill/pdf';
import type { Data, PDFOptions } from 'swissqrbill/types';
import type { QRInvoiceRequestOutput } from '../schemas/qr-invoice.schema.js';

export class QRBillService {
  /**
   * Generiert ein PDF mit Swiss QR-Bill
   */
  async generateQRBill(request: QRInvoiceRequestOutput): Promise<Buffer> {
    return new Promise((resolve, reject) => {
      const chunks: Buffer[] = [];

      // PDF Document erstellen (A4)
      const pdf = new PDFDocument({
        size: 'A4',
        margin: 0,
        autoFirstPage: true,
        bufferPages: true,
      });

      // Buffer sammeln
      pdf.on('data', (chunk: Buffer) => chunks.push(chunk));
      pdf.on('end', () => resolve(Buffer.concat(chunks)));
      pdf.on('error', reject);

      // Daten für swissqrbill aufbereiten
      const qrBillData = this.mapToSwissQRBillData(request);
      const options = this.mapToSwissQRBillOptions(request);

      // SwissQRBill erstellen und an PDF anhängen
      const qrBill = new SwissQRBill(qrBillData, options);
      qrBill.attachTo(pdf);

      // PDF finalisieren
      pdf.end();
    });
  }

  /**
   * Mappt Request-Daten auf swissqrbill Data Format
   */
  private mapToSwissQRBillData(request: QRInvoiceRequestOutput): Data {
    const data: Data = {
      creditor: {
        account: request.creditor.iban,
        name: request.creditor.address.name,
        address: request.creditor.address.street || '',
        buildingNumber: request.creditor.address.buildingNumber || undefined,
        zip: request.creditor.address.postalCode,
        city: request.creditor.address.city,
        country: request.creditor.address.country,
      },
      currency: request.currency,
    };

    // Betrag (optional)
    if (request.amount !== undefined) {
      data.amount = request.amount;
    }

    // Referenz
    if (request.reference && request.reference.type !== 'NON' && request.reference.value) {
      data.reference = request.reference.value.replace(/\s/g, '');
    }

    // Debitor (optional)
    if (request.debtor) {
      data.debtor = {
        name: request.debtor.address.name,
        address: request.debtor.address.street || '',
        buildingNumber: request.debtor.address.buildingNumber || undefined,
        zip: request.debtor.address.postalCode,
        city: request.debtor.address.city,
        country: request.debtor.address.country,
      };
    }

    // Nachricht
    if (request.additionalInformation?.message) {
      data.message = request.additionalInformation.message;
    }

    // Strukturierte Rechnungsinformationen
    if (request.additionalInformation?.billingInformation) {
      data.additionalInformation = request.additionalInformation.billingInformation;
    }

    return data;
  }

  /**
   * Mappt Request-Optionen auf swissqrbill PDFOptions
   */
  private mapToSwissQRBillOptions(request: QRInvoiceRequestOutput): PDFOptions {
    const languageMap: Record<string, 'DE' | 'EN' | 'FR' | 'IT'> = {
      de: 'DE',
      en: 'EN',
      fr: 'FR',
      it: 'IT',
    };

    return {
      language: languageMap[request.options?.language || 'de'] || 'DE',
      outlines: request.options?.separate !== false,
      scissors: request.options?.separate !== false,
    };
  }
}

export const qrBillService = new QRBillService();
