import { promisify } from 'node:util'
import child_process from 'node:child_process'
import { existsSync, mkdirSync } from 'node:fs'
import { writeFile } from 'node:fs/promises'

// PDF page size thresholds in points
// A4: 595 x 842 points (210 x 297 mm)
// Letter: 612 x 792 points (8.5 x 11 inches)
// Labels are typically much smaller (e.g., 283 x 425 for 100x150mm)
const A4_MIN_WIDTH = 500 // Points - anything wider than this is A4/Letter

// Map shipping printer to Tisch number for A4 printer naming
const SHIPPING_PRINTER_TO_TISCH: Record<string, string> = {
  'labelprinter-1': '1', // Tisch 1
  'labelprinter-4': '2', // Tisch 2
  'labelprinter-5': '3'  // Tisch 3
}

export default defineEventHandler(async (event) => {
  let data: any = {}
  const body = await readBody(event)
  const exec = promisify(child_process.exec)
  const pathName = body.pathName
  const filePath = `/root/storage/${pathName}`
  const fileName = body.fileName
  const fileContent = Buffer.from(body.fileContent, 'base64')
  const shippingPrinter = body.shippingPrinter || 'labelprinter-1'

  // Prefer the A4 printer configured on the commissioning table
  // (CUST_CommissionTable.a4_printer, passed by the client). Fall back to the
  // legacy printer→Tisch map for callers that don't send it.
  const tischNumber = SHIPPING_PRINTER_TO_TISCH[shippingPrinter] || '1'
  const a4Printer = body.a4Printer || `commission-a4-${tischNumber}`

  try {
    if (!existsSync(filePath)) {
      mkdirSync(filePath, { recursive: true })
    }
    const fullFilePath = `${filePath}/${fileName}`
    await writeFile(fullFilePath, fileContent)

    // Analyze PDF dimensions using pdfinfo
    let pdfWidth = 0
    let pdfHeight = 0
    let isSmallLabel = false

    try {
      const { stdout } = await exec(`pdfinfo "${fullFilePath}" 2>/dev/null | grep -i "Page size"`)
      // Parse output like "Page size:      595.276 x 841.89 pts (A4)"
      const match = stdout.match(/Page size:\s+([\d.]+)\s*x\s*([\d.]+)/)
      if (match) {
        pdfWidth = parseFloat(match[1])
        pdfHeight = parseFloat(match[2])
        // If width is less than A4 minimum, it's a label
        isSmallLabel = pdfWidth < A4_MIN_WIDTH
      }
      console.log(`[Smart Print] PDF dimensions: ${pdfWidth} x ${pdfHeight} pts, isSmallLabel: ${isSmallLabel}`)
    } catch (pdfErr) {
      console.log('[Smart Print] pdfinfo failed, trying alternative method')

      // Fallback: try Ghostscript
      try {
        const { stdout } = await exec(`gs -q -dNODISPLAY -dBATCH -dNOPAUSE -c "(${fullFilePath}) (r) file runpdfbegin 1 pdfgetpage /MediaBox get == quit" 2>/dev/null`)
        // Parse MediaBox output like [0 0 595.276 841.89]
        const match = stdout.match(/\[\s*[\d.]+\s+[\d.]+\s+([\d.]+)\s+([\d.]+)\s*\]/)
        if (match) {
          pdfWidth = parseFloat(match[1])
          pdfHeight = parseFloat(match[2])
          isSmallLabel = pdfWidth < A4_MIN_WIDTH
        }
        console.log(`[Smart Print] GS dimensions: ${pdfWidth} x ${pdfHeight} pts, isSmallLabel: ${isSmallLabel}`)
      } catch (gsErr) {
        console.log('[Smart Print] Ghostscript also failed, defaulting to A4')
        // Default to A4 if we can't detect
        isSmallLabel = false
      }
    }

    // Choose printer based on PDF size
    // Small labels go to the shipping label printer, A4/large pages go to commission-a4-X
    const printerToUse = isSmallLabel ? shippingPrinter : a4Printer
    const printOptions = isSmallLabel ? '-o fit-to-page' : '-o sides=one-sided'

    console.log(`[Smart Print] Printing to: ${printerToUse} with options: ${printOptions}`)

    const { stdout, stderr } = await exec(`lp -d ${printerToUse} ${printOptions} "${fullFilePath}"`)

    data = {
      ...body,
      message: !stderr ? 'success' : 'failed',
      stdout: stdout,
      stderr: stderr,
      pdfAnalysis: {
        width: pdfWidth,
        height: pdfHeight,
        isSmallLabel: isSmallLabel,
        printerUsed: printerToUse
      }
    }
  } catch (err: any) {
    console.error('[Smart Print] Error:', err)
    data = {
      message: 'failed',
      error: err.message || err
    }
  }

  return data
})
