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

// PDF page size detection
// A4: 595 x 842 points (210 x 297 mm)
// Letter: 612 x 792 points (8.5 x 11 inches)
// Small labels are typically under 400 points in either dimension

const PAGE_SIZE_THRESHOLDS = {
  // A4/Letter size PDFs have width around 595-612 points
  A4_MIN_WIDTH: 500,
  // Small labels are typically under this width
  LABEL_MAX_WIDTH: 450,
  LABEL_MAX_HEIGHT: 450
}

// Function to detect PDF page size using pdfinfo command
const detectPdfPageSize = async (filePath: string): Promise<{ width: number; height: number; isSmall: boolean }> => {
  const exec = promisify(child_process.exec)
  
  try {
    // Use pdfinfo to get page dimensions
    const { stdout } = await exec(`pdfinfo "${filePath}" 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) {
      const width = parseFloat(match[1])
      const height = parseFloat(match[2])
      
      // Determine if it's a small label-size PDF
      const isSmall = width < PAGE_SIZE_THRESHOLDS.A4_MIN_WIDTH || 
                      (width < PAGE_SIZE_THRESHOLDS.LABEL_MAX_WIDTH && height < PAGE_SIZE_THRESHOLDS.LABEL_MAX_HEIGHT)
      
      return { width, height, isSmall }
    }
  } catch (err) {
    console.log('[PDF Size Detection] pdfinfo failed, trying alternative method')
  }
  
  // Fallback: Try using pdftk or gs if pdfinfo fails
  try {
    const { stdout } = await exec(`gs -q -dNODISPLAY -c "(${filePath}) (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(/\[[\d.\s]+\s+([\d.]+)\s+([\d.]+)\]/)
    if (match) {
      const width = parseFloat(match[1])
      const height = parseFloat(match[2])
      const isSmall = width < PAGE_SIZE_THRESHOLDS.A4_MIN_WIDTH
      return { width, height, isSmall }
    }
  } catch (err) {
    console.log('[PDF Size Detection] Ghostscript method failed')
  }
  
  // Default to A4 if detection fails
  return { width: 595, height: 842, isSmall: false }
}

export default defineEventHandler(async (event) => {
  let data: any = { printed: [], status: 200, message: '' }
  const body = await readBody(event)
  const exec = promisify(child_process.exec)
  const config = useRuntimeConfig()
  
  const orderId = body.orderId
  const labelPrinter = body.labelPrinter || 'labelprinter-1'
  const defaultPrinter = 'default' // CUPS printer name for A4/Letter PDFs
  
  if (!orderId) {
    return { printed: [], status: 400, message: 'Order ID is required' }
  }

  console.log(`[Order Attachment Print] Starting for order ID: ${orderId}, Label printer: ${labelPrinter}`)

  try {
    // Step 1: Get the Strapi attachment record for this order (AD_Table_ID 259 = C_Order)
    const attachmentRecordResponse: any = await strapiHelper(
      event,
      `ad-attachments?filters[AD_Table_ID][$eq]=259&filters[Record_ID][$eq]=${orderId}`,
      'GET',
      null
    )

    console.log(`[Order Attachment Print] Step 1 - Attachment record response for order ${orderId}:`, JSON.stringify(attachmentRecordResponse?.data?.[0] || 'No record'))

    if (!attachmentRecordResponse?.data?.[0]?.documentId) {
      console.log(`[Order Attachment Print] No attachment record found for order ${orderId}`)
      return { printed: [], status: 200, message: 'No attachments found for this order' }
    }

    const strapiDocumentId = attachmentRecordResponse.data[0].documentId

    // Step 2: Get the actual attachment files using the documentId
    const filesResponse: any = await strapiHelper(
      event,
      `ad-attachments/${strapiDocumentId}?populate=attachment`,
      'GET',
      null
    )

    console.log(`[Order Attachment Print] Step 2 - Files response for documentId ${strapiDocumentId}:`, JSON.stringify(filesResponse?.data?.attachment?.length || 0, null, 2))

    const files = filesResponse?.data?.attachment || []
    
    // Filter only PDF files
    const pdfFiles = files.filter((file: any) => file.mime === 'application/pdf')

    console.log(`[Order Attachment Print] Found ${files.length} total files, ${pdfFiles.length} PDF files for order ${orderId}`)

    if (pdfFiles.length === 0) {
      console.log(`[Order Attachment Print] No PDF attachments found for order ${orderId}`)
      return { printed: [], status: 200, message: 'No PDF attachments found' }
    }

    const pathName = `order-attachments/${new Date().getFullYear()}`
    const filePath = `/root/storage/${pathName}`
    
    // Ensure directory exists
    if (!existsSync(filePath)) {
      mkdirSync(filePath, { recursive: true })
    }

    for (const pdfFile of pdfFiles) {
      try {
        // Download the PDF file from Strapi
        // Try multiple URL patterns: direct url, files-api with hash, or strapiupload base
        let pdfUrl = ''

        // Log available file properties for debugging
        console.log(`[Order Attachment Print] File properties:`, JSON.stringify({
          name: pdfFile.name,
          hash: pdfFile.hash,
          ext: pdfFile.ext,
          url: pdfFile.url,
          mime: pdfFile.mime
        }))

        // Use strapiupload config (direct Strapi URL) with files-api endpoint
        const strapiBase = config.api.strapiupload || 'http://127.0.0.1:1337'
        pdfUrl = `${strapiBase}/files-api/${pdfFile.hash}${pdfFile.ext}`

        console.log(`[Order Attachment Print] Downloading file from: ${pdfUrl}`)

        const pdfResponse = await $fetch(pdfUrl, {
          responseType: 'arrayBuffer'
        })
        
        const pdfBuffer = Buffer.from(pdfResponse as ArrayBuffer)
        const fileName = `${Date.now()}-${pdfFile.name}`
        const fullFilePath = `${filePath}/${fileName}`
        
        // Save the PDF temporarily
        await writeFile(fullFilePath, pdfBuffer)
        
        // Detect PDF size
        const pageSize = await detectPdfPageSize(fullFilePath)
        
        // Determine which printer to use based on PDF size
        const printerToUse = pageSize.isSmall ? labelPrinter : defaultPrinter
        const printOptions = pageSize.isSmall ? '' : '-o sides=one-sided'
        
        console.log(`[Order Attachment Print] File: ${pdfFile.name}, Size: ${pageSize.width}x${pageSize.height}, Small: ${pageSize.isSmall}, Printer: ${printerToUse}`)

        // Print the PDF
        const printCommand = `lp -d ${printerToUse} ${printOptions} "${fullFilePath}"`
        console.log(`[Order Attachment Print] Executing: ${printCommand}`)

        const { stdout, stderr } = await exec(printCommand)

        console.log(`[Order Attachment Print] Print result - stdout: ${stdout}, stderr: ${stderr}`)

        // lp command returns success if stdout contains "request id"
        const printSuccess = stdout && stdout.includes('request id')

        data.printed.push({
          fileName: pdfFile.name,
          fileId: pdfFile.id,
          printer: printerToUse,
          pageSize: {
            width: pageSize.width,
            height: pageSize.height,
            isSmall: pageSize.isSmall
          },
          success: printSuccess,
          stdout: stdout,
          stderr: stderr
        })
      } catch (fileErr: any) {
        console.error(`[Order Attachment Print] Error printing file ${pdfFile.name}:`, fileErr)
        data.printed.push({
          fileName: pdfFile.name,
          fileId: pdfFile.id,
          success: false,
          error: fileErr.message || 'Unknown error'
        })
      }
    }

    data.message = `Processed ${data.printed.length} PDF attachment(s)`
    
  } catch (err: any) {
    console.error('[Order Attachment Print] Error:', err)
    data = {
      printed: [],
      status: err.status || err.statusCode || 500,
      message: err.detail || err.message || err.statusMessage || 'Error printing attachments'
    }
  }

  return data
})
