/**
 * PDF Generation Service
 * Uses tinypdf-plus for server-side PDF generation with custom font support
 */

// @ts-ignore - tinypdf-plus doesn't have types yet
import { pdf, loadFont } from 'tinypdf-plus'
import { randomUUID } from 'crypto'

export interface PDFOptions {
  title?: string
  author?: string
  subject?: string
  keywords?: string
  creator?: string
}

export interface TextOptions {
  font?: string
  color?: string
  size?: number
  align?: 'left' | 'center' | 'right'
  width?: number
}

export interface PDFDocumentConfig {
  width: number
  height: number
  margin: number
}

export interface FontConfig {
  name: string
  data: Uint8Array
}

class PDFService {
  private registeredFonts = new Map<string, FontConfig>()

  /**
   * Register a custom font for PDF generation
   */
  registerFont(name: string, fontData: Uint8Array): void {
    try {
      const font = loadFont(fontData, name)
      this.registeredFonts.set(name, { name, data: fontData })
    } catch (error) {
      console.error(`Failed to register font ${name}:`, error)
      throw new Error(`Font registration failed: ${error}`)
    }
  }

  /**
   * Get list of registered fonts
   */
  getRegisteredFonts(): string[] {
    return Array.from(this.registeredFonts.keys())
  }

  /**
   * Check if a font is registered
   */
  hasFont(name: string): boolean {
    return this.registeredFonts.has(name)
  }

  /**
   * Generate a simple text PDF
   */
  generateTextPDF(
    content: string,
    options: PDFDocumentConfig = { width: 612, height: 792, margin: 72 }
  ): Uint8Array {
    const doc = pdf()

    // Register any custom fonts
    for (const font of this.registeredFonts.values()) {
      try {
        const loadedFont = loadFont(font.data, font.name)
        doc.registerFont(font.name, loadedFont)
      } catch (error) {
        console.warn(`Failed to register font ${font.name}:`, error)
      }
    }

    doc.page((ctx: any) => {
      const { width, height, margin } = options
      const textWidth = width - margin * 2
      let y = height - margin
      const lineHeight = 14

      // Simple text wrapping
      const lines = this.wrapText(content, textWidth, 12)
      for (const line of lines) {
        ctx.text(line, margin, y, 12)
        y -= lineHeight
        if (y < margin) break
      }
    })

    return doc.build()
  }

  /**
   * Generate a certificate PDF
   */
  generateCertificate(
    data: {
      title: string
      recipientName: string
      description: string
      date: string
      certificateNumber: string
      authorizedBy?: string
    },
    options: PDFDocumentConfig = { width: 612, height: 792, margin: 72 }
  ): Uint8Array {
    const doc = pdf()

    // Register any custom fonts
    for (const font of this.registeredFonts.values()) {
      try {
        const loadedFont = loadFont(font.data, font.name)
        doc.registerFont(font.name, loadedFont)
      } catch (error) {
        console.warn(`Failed to register font ${font.name}:`, error)
      }
    }

    doc.page((ctx: any) => {
      const { width, height, margin } = options
      const centerX = width / 2
      let y = height - margin

      // Title
      ctx.text(data.title, centerX, y, 24, {
        font: this.registeredFonts.has('Title') ? 'Title' : undefined,
        align: 'center',
        width: width - margin * 2
      })
      y -= 50

      // Certificate number
      ctx.text(`Certificate No: ${data.certificateNumber}`, centerX, y, 10, {
        color: '#666',
        align: 'center',
        width: width - margin * 2
      })
      y -= 40

      // Separator line
      ctx.line(margin, y, width - margin, y, '#ccc', 1)
      y -= 60

      // Recipient name
      ctx.text(data.recipientName, centerX, y, 18, {
        font: this.registeredFonts.has('Body') ? 'Body' : undefined,
        align: 'center',
        width: width - margin * 2
      })
      y -= 30

      // Description
      const descriptionLines = this.wrapText(data.description, width - margin * 3, 12)
      for (const line of descriptionLines) {
        ctx.text(line, centerX, y, 12, {
          align: 'center',
          width: width - margin * 2
        })
        y -= 18
        if (y < margin + 100) break
      }

      y -= 40

      // Date
      ctx.text(`Date: ${data.date}`, centerX, y, 12, {
        color: '#666',
        align: 'center',
        width: width - margin * 2
      })

      // Authorized by (if provided)
      if (data.authorizedBy) {
        ctx.text(`Authorized by: ${data.authorizedBy}`, centerX, margin + 30, 10, {
          color: '#666',
          align: 'center',
          width: width - margin * 2
        })
      }
    })

    return doc.build()
  }

  /**
   * Generate a label PDF (for plants, batches, etc.)
   */
  generateLabel(
    data: {
      title: string
      subtitle?: string
      qrCode?: string
      details: { label: string; value: string }[]
    },
    options: PDFDocumentConfig = { width: 288, height: 144, margin: 18 }
  ): Uint8Array {
    const doc = pdf()

    // Register any custom fonts
    for (const font of this.registeredFonts.values()) {
      try {
        const loadedFont = loadFont(font.data, font.name)
        doc.registerFont(font.name, loadedFont)
      } catch (error) {
        console.warn(`Failed to register font ${font.name}:`, error)
      }
    }

    doc.page((ctx: any) => {
      const { width, height, margin } = options
      let y = height - margin

      // Title
      ctx.text(data.title, margin, y, 14, {
        font: this.registeredFonts.has('Label') ? 'Label' : undefined,
        color: '#333'
      })
      y -= 20

      // Subtitle (if provided)
      if (data.subtitle) {
        ctx.text(data.subtitle, margin, y, 10, { color: '#666' })
        y -= 15
      }

      y -= 10

      // Details
      for (const detail of data.details) {
        ctx.text(`${detail.label}: ${detail.value}`, margin, y, 9)
        y -= 12
        if (y < margin) break
      }

      // QR code placeholder (if provided)
      if (data.qrCode) {
        ctx.text(`QR: ${data.qrCode}`, margin, margin + 20, 8, { color: '#999' })
      }
    })

    return doc.build()
  }

  /**
   * Helper function to wrap text
   */
  private wrapText(text: string, maxWidth: number, fontSize: number): string[] {
    const lines: string[] = []
    const words = text.split(' ')
    let currentLine = ''

    // Approximate character width (default Helvetica)
    const avgCharWidth = fontSize * 0.5

    for (const word of words) {
      const testLine = currentLine ? `${currentLine} ${word}` : word
      const testWidth = testLine.length * avgCharWidth

      if (testWidth < maxWidth) {
        currentLine = testLine
      } else {
        if (currentLine) lines.push(currentLine)
        currentLine = word
      }
    }

    if (currentLine) lines.push(currentLine)
    return lines.length ? lines : ['']
  }
}

export const pdfService = new PDFService()
