/**
 * PDF Generation Service
 *
 * Generiert PDFs aus HTML oder URLs mittels Playwright.
 * Unterstützt verschiedene Formate und Optionen.
 */

import { chromium, Browser, Page } from 'playwright'
import * as fs from 'fs/promises'
import * as path from 'path'

// Umgebungsvariablen
const PDF_OUTPUT_DIR = process.env.PDF_OUTPUT_DIR || '/tmp/payload-pdfs'
const PDF_GENERATION_DISABLED = process.env.PDF_GENERATION_DISABLED === 'true'

// Browser-Instanz (wird wiederverwendet)
let browserInstance: Browser | null = null

export interface PdfOptions {
  format?: 'A4' | 'A3' | 'Letter' | 'Legal'
  landscape?: boolean
  margin?: {
    top?: string
    right?: string
    bottom?: string
    left?: string
  }
  printBackground?: boolean
  scale?: number
  headerTemplate?: string
  footerTemplate?: string
  displayHeaderFooter?: boolean
}

export interface PdfResult {
  success: boolean
  buffer?: Buffer
  outputPath?: string
  filename?: string
  pageCount?: number
  fileSize?: number
  error?: string
  duration?: number
}

/**
 * Holt oder erstellt eine Browser-Instanz
 */
async function getBrowser(): Promise<Browser> {
  if (!browserInstance || !browserInstance.isConnected()) {
    console.log('[PDF] Launching browser...')
    browserInstance = await chromium.launch({
      headless: true,
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage',
        '--disable-gpu',
      ],
    })
  }
  return browserInstance
}

/**
 * Schließt die Browser-Instanz
 */
export async function closeBrowser(): Promise<void> {
  if (browserInstance) {
    await browserInstance.close()
    browserInstance = null
    console.log('[PDF] Browser closed')
  }
}

/**
 * Stellt sicher, dass das Output-Verzeichnis existiert
 */
async function ensureOutputDir(): Promise<void> {
  try {
    await fs.mkdir(PDF_OUTPUT_DIR, { recursive: true })
  } catch {
    // Verzeichnis existiert bereits
  }
}

/**
 * Generiert ein PDF aus HTML-Content
 */
export async function generatePdfFromHtml(
  html: string,
  options: PdfOptions = {},
  outputPath?: string,
): Promise<PdfResult> {
  const startTime = Date.now()

  // Check ob PDF-Generierung deaktiviert ist (Test-Modus)
  if (PDF_GENERATION_DISABLED) {
    console.log('[PDF] Generation disabled - returning mock result')
    return {
      success: true,
      buffer: Buffer.from('mock-pdf-content'),
      filename: 'mock.pdf',
      pageCount: 1,
      fileSize: 17,
      duration: Date.now() - startTime,
    }
  }

  let page: Page | null = null

  try {
    const browser = await getBrowser()
    page = await browser.newPage()

    // HTML laden
    await page.setContent(html, { waitUntil: 'networkidle' })

    // PDF-Optionen
    const pdfOptions = {
      format: options.format || 'A4',
      landscape: options.landscape || false,
      margin: options.margin || {
        top: '20mm',
        right: '15mm',
        bottom: '20mm',
        left: '15mm',
      },
      printBackground: options.printBackground !== false,
      scale: options.scale || 1,
      displayHeaderFooter: options.displayHeaderFooter || false,
      headerTemplate: options.headerTemplate || '',
      footerTemplate: options.footerTemplate || '',
    }

    // PDF generieren
    const pdfBuffer = await page.pdf(pdfOptions)

    // Seitenzahl ermitteln (geschätzt aus Dateigröße oder via PDF-Parser)
    // Für genauere Zählung würde man einen PDF-Parser brauchen
    const pageCount = Math.max(1, Math.ceil(pdfBuffer.length / 50000))

    const result: PdfResult = {
      success: true,
      buffer: pdfBuffer,
      pageCount,
      fileSize: pdfBuffer.length,
      duration: Date.now() - startTime,
    }

    // Optional: In Datei speichern
    if (outputPath) {
      await ensureOutputDir()
      const fullPath = path.isAbsolute(outputPath)
        ? outputPath
        : path.join(PDF_OUTPUT_DIR, outputPath)

      await fs.writeFile(fullPath, pdfBuffer)
      result.outputPath = fullPath
      result.filename = path.basename(fullPath)
      console.log(`[PDF] Saved to ${fullPath}`)
    }

    console.log(`[PDF] Generated successfully (${pdfBuffer.length} bytes, ~${pageCount} pages, ${result.duration}ms)`)

    return result
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : 'Unknown error'
    console.error('[PDF] Generation failed:', errorMessage)

    return {
      success: false,
      error: errorMessage,
      duration: Date.now() - startTime,
    }
  } finally {
    if (page) {
      await page.close()
    }
  }
}

/**
 * Generiert ein PDF von einer URL
 */
export async function generatePdfFromUrl(
  url: string,
  options: PdfOptions = {},
  outputPath?: string,
): Promise<PdfResult> {
  const startTime = Date.now()

  // Check ob PDF-Generierung deaktiviert ist (Test-Modus)
  if (PDF_GENERATION_DISABLED) {
    console.log('[PDF] Generation disabled - returning mock result')
    return {
      success: true,
      buffer: Buffer.from('mock-pdf-content'),
      filename: 'mock.pdf',
      pageCount: 1,
      fileSize: 17,
      duration: Date.now() - startTime,
    }
  }

  let page: Page | null = null

  try {
    const browser = await getBrowser()
    page = await browser.newPage()

    // URL laden
    await page.goto(url, { waitUntil: 'networkidle', timeout: 30000 })

    // PDF-Optionen
    const pdfOptions = {
      format: options.format || 'A4',
      landscape: options.landscape || false,
      margin: options.margin || {
        top: '20mm',
        right: '15mm',
        bottom: '20mm',
        left: '15mm',
      },
      printBackground: options.printBackground !== false,
      scale: options.scale || 1,
      displayHeaderFooter: options.displayHeaderFooter || false,
      headerTemplate: options.headerTemplate || '',
      footerTemplate: options.footerTemplate || '',
    }

    // PDF generieren
    const pdfBuffer = await page.pdf(pdfOptions)
    const pageCount = Math.max(1, Math.ceil(pdfBuffer.length / 50000))

    const result: PdfResult = {
      success: true,
      buffer: pdfBuffer,
      pageCount,
      fileSize: pdfBuffer.length,
      duration: Date.now() - startTime,
    }

    // Optional: In Datei speichern
    if (outputPath) {
      await ensureOutputDir()
      const fullPath = path.isAbsolute(outputPath)
        ? outputPath
        : path.join(PDF_OUTPUT_DIR, outputPath)

      await fs.writeFile(fullPath, pdfBuffer)
      result.outputPath = fullPath
      result.filename = path.basename(fullPath)
      console.log(`[PDF] Saved to ${fullPath}`)
    }

    console.log(`[PDF] Generated from URL successfully (${pdfBuffer.length} bytes, ~${pageCount} pages, ${result.duration}ms)`)

    return result
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : 'Unknown error'
    console.error('[PDF] Generation from URL failed:', errorMessage)

    return {
      success: false,
      error: errorMessage,
      duration: Date.now() - startTime,
    }
  } finally {
    if (page) {
      await page.close()
    }
  }
}

/**
 * Generiert einen eindeutigen Dateinamen für eine PDF
 */
export function generatePdfFilename(
  prefix: string = 'document',
  tenantId?: number,
  documentType?: string,
): string {
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
  const parts = [prefix]

  if (documentType) {
    parts.push(documentType)
  }
  if (tenantId) {
    parts.push(`tenant-${tenantId}`)
  }
  parts.push(timestamp)

  return `${parts.join('_')}.pdf`
}

/**
 * Löscht eine generierte PDF-Datei
 */
export async function deletePdfFile(filePath: string): Promise<boolean> {
  try {
    await fs.unlink(filePath)
    console.log(`[PDF] Deleted ${filePath}`)
    return true
  } catch {
    console.warn(`[PDF] Could not delete ${filePath}`)
    return false
  }
}

/**
 * Liest eine PDF-Datei als Buffer
 */
export async function readPdfFile(filePath: string): Promise<Buffer | null> {
  try {
    return await fs.readFile(filePath)
  } catch {
    console.warn(`[PDF] Could not read ${filePath}`)
    return null
  }
}
