import { PDFDocument, rgb, StandardFonts } from 'pdf-lib'; import { readFile } from 'fs/promises'; import path from 'path'; import { formatDate } from './date-utils'; export async function generateContractFromTemplate( booking: any, location: any, photobox: any, signatureData?: string ) { try { // Load the template PDF const templatePath = path.join(process.cwd(), 'mietvertrag-vorlage.pdf'); const templateBytes = await readFile(templatePath); // Load PDF const pdfDoc = await PDFDocument.load(templateBytes); const pages = pdfDoc.getPages(); const firstPage = pages[0]; // Embed font const font = await pdfDoc.embedFont(StandardFonts.Helvetica); const fontBold = await pdfDoc.embedFont(StandardFonts.HelveticaBold); const { width, height } = firstPage.getSize(); // PDF coordinate system: (0,0) is bottom-left, Y increases upwards // A4 page height is ~842 points // Page 1: Customer Info & Table // Customer name (under "und") - around middle of page if (booking.customerName) { firstPage.drawText(booking.customerName, { x: 250, y: 465, size: 10, font: font, color: rgb(0, 0, 0), }); } // Customer address (next line) if (booking.customerAddress) { firstPage.drawText( `${booking.customerAddress}, ${booking.customerZip} ${booking.customerCity}`, { x: 250, y: 450, size: 10, font: font, color: rgb(0, 0, 0), } ); } // Distance (in "Lieferung inkl. Aufbau" row) if (booking.distance) { const distance = booking.distance || 0; const totalKm = distance * 2; // Fill in the km field firstPage.drawText(`${distance.toFixed(1)}`, { x: 735, y: 95, size: 9, font: font, color: rgb(0, 0, 0), }); firstPage.drawText(`${totalKm.toFixed(1)}`, { x: 895, y: 95, size: 9, font: font, color: rgb(0, 0, 0), }); } // Event location and date (Section 2 - MIETZWECK) - bottom of page 1 if (booking.eventLocation && booking.eventDate) { firstPage.drawText( `${booking.eventLocation} am ${formatDate(booking.eventDate)}`, { x: 100, y: 35, size: 10, font: font, color: rgb(0, 0, 0), } ); } // Page 2: Mietzeit & Mietpreis const secondPage = pages[1]; // Event date (Section 3 - MIETZEIT) if (booking.eventDate) { secondPage.drawText(formatDate(booking.eventDate), { x: 210, y: height - 85, size: 10, font: font, color: rgb(0, 0, 0), }); } // Price (Section 4 - MIETPREIS) if (booking.calculatedPrice) { const price = booking.calculatedPrice.toFixed(2); secondPage.drawText(`${price}`, { x: 475, y: height - 165, size: 10, font: font, color: rgb(0, 0, 0), }); } // Signature on last page if provided if (signatureData && pages.length >= 4) { const lastPage = pages[pages.length - 1]; // Convert base64 signature to image try { const signatureImage = await pdfDoc.embedPng(signatureData); const signatureDims = signatureImage.scale(0.25); // Right side signature box lastPage.drawImage(signatureImage, { x: 420, y: 120, width: signatureDims.width, height: signatureDims.height, }); // Signature name below if (booking.customerName) { lastPage.drawText(booking.customerName, { x: 420, y: 100, size: 10, font: font, color: rgb(0, 0, 0), }); } // Signature date and info const sigDate = new Date(); lastPage.drawText(`Digital signiert am ${formatDate(sigDate)}`, { x: 420, y: 85, size: 8, font: font, color: rgb(0.4, 0.4, 0.4), }); } catch (err) { console.error('Signature embedding error:', err); } } // Serialize the PDF const pdfBytes = await pdfDoc.save(); return Buffer.from(pdfBytes); } catch (error) { console.error('PDF generation from template error:', error); throw error; } }