/**
 * PDF Generator Service - Main service for PDF generation
 * Clean Code: Facade Pattern, Single Responsibility
 */

import { PDFDocument } from 'pdf-lib'
import fs from 'fs/promises'
import path from 'path'
import { fillPdfForm } from './pdf-form-filler.js'

/**
 * PDF Generation Result
 */
export class PDFGenerationResult {
  constructor(success, pdfBuffer, filename, error = null) {
    this.success = success
    this.pdfBuffer = pdfBuffer
    this.filename = filename
    this.error = error
  }
}

/**
 * PDF Generator Service
 */
export class PDFGeneratorService {
  constructor() {
    this.templatePath = path.join(process.cwd(), 'server', 'templates', 'mitgliedschaft-fillable.pdf')
    this.fallbackTemplatePath = path.join(process.cwd(), 'server', 'templates', 'Aufnahmeantrag 2025.pdf')
  }

  /**
   * Generates PDF from template with form data
   * @param {Object} data - Form data
   * @returns {Promise<PDFGenerationResult>} Generation result
   */
  async generateFromTemplate(data) {
    try {
      const templatePath = await this.getTemplatePath()
      const templateBytes = await fs.readFile(templatePath)
      const pdfDoc = await PDFDocument.load(templateBytes)
      const form = pdfDoc.getForm()
      
      // Fill form fields
      await fillPdfForm(pdfDoc, form, data)
      
      // Don't flatten form to keep fields editable
      // form.flatten() makes fields non-editable
      
      // Generate filename
      const filename = this.generateFilename(data)
      
      // Save PDF
      const pdfBytes = await pdfDoc.save()
      
      return new PDFGenerationResult(true, Buffer.from(pdfBytes), filename)
    } catch (_error) {
      console.error('Template PDF generation failed:', error.message)
      return new PDFGenerationResult(false, null, null, error.message)
    }
  }


  /**
   * Gets the appropriate template path
   * @returns {Promise<string>} Template path
   */
  async getTemplatePath() {
    try {
      await fs.access(this.templatePath)
      return this.templatePath
    } catch (_error) {
      try {
        await fs.access(this.fallbackTemplatePath)
        return this.fallbackTemplatePath
      } catch (_fallbackError) {
        throw new Error('No PDF template found')
      }
    }
  }

  /**
   * Generates filename for PDF
   * @param {Object} data - Form data
   * @returns {string} Filename
   */
  generateFilename(data) {
    const timestamp = Date.now()
    return `beitrittserklärung_${timestamp}.pdf`
  }

  /**
   * Saves PDF to file system
   * @param {Buffer} pdfBuffer - PDF buffer
   * @param {string} filename - Filename
   * @param {string} uploadDir - Upload directory
   * @returns {Promise<string>} File path
   */
  async savePDF(pdfBuffer, filename, uploadDir) {
    // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
    const filePath = path.join(uploadDir, filename)
    await fs.writeFile(filePath, pdfBuffer)
    return filePath
  }
}
