import nodemailer from 'nodemailer'
import { PDFDocument, StandardFonts, rgb } from 'pdf-lib'
import refreshTokenHelper from "../../utils/refreshTokenHelper"
import forceLogoutHelper from "../../utils/forceLogoutHelper"
import errorHandlingHelper from "../../utils/errorHandlingHelper"

interface InOutLineRecord {
  organization: string
  shipment: string
  productName: string
  productValue: string
  productSku: string
  productMpn: string
  uom: string
  qtyEntered: number
  movementQty: number
  locator: string
  orderLine: string
  line: number
}

const formatDate = (date: Date, lang: string) => {
  const isGerman = lang.startsWith('de')
  return date.toLocaleDateString(isGerman ? 'de-DE' : 'en-US', {
    day: '2-digit',
    month: '2-digit',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit'
  })
}

const generatePdfReport = async (records: InOutLineRecord[], lang: string) => {
  const isGerman = lang.startsWith('de')
  const pdfDoc = await PDFDocument.create()
  const font = await pdfDoc.embedFont(StandardFonts.Helvetica)
  const fontBold = await pdfDoc.embedFont(StandardFonts.HelveticaBold)

  const pageWidth = 841.89 // A4 landscape
  const pageHeight = 595.28
  const margin = 30
  const lineHeight = 14
  const headerHeight = 20

  const colWidths = { org: 70, shipment: 90, prodName: 140, sku: 70, qty: 45, movQty: 50, locator: 70, orderLine: 80 }

  const addNewPage = () => pdfDoc.addPage([pageWidth, pageHeight])

  const drawHeader = (page: any, yPos: number) => {
    const headers = isGerman
      ? ['Organisation', 'Lieferung', 'Produktname', 'SKU', 'Menge', 'Bew.Menge', 'Lagerplatz', 'Auftragspos.']
      : ['Organization', 'Shipment', 'Product Name', 'SKU', 'Qty', 'Mov Qty', 'Locator', 'Order Line']

    let xPos = margin
    page.drawRectangle({
      x: margin - 5, y: yPos - 5,
      width: pageWidth - (margin * 2) + 10, height: headerHeight,
      color: rgb(0.9, 0.9, 0.9)
    })

    const fontSize = 7
    const widths = Object.values(colWidths)
    for (let i = 0; i < headers.length; i++) {
      page.drawText(headers[i], { x: xPos, y: yPos, size: fontSize, font: fontBold })
      xPos += widths[i]
    }
    return yPos - headerHeight - 5
  }

  const truncate = (str: string, max: number) => {
    if (!str) return ''
    return str.length > max ? str.substring(0, max - 3) + '...' : str
  }

  const drawRow = (page: any, record: InOutLineRecord, yPos: number) => {
    let xPos = margin
    const fontSize = 6
    const widths = Object.values(colWidths)
    const values = [
      truncate(record.organization, 16),
      truncate(record.shipment, 20),
      truncate(record.productName, 30),
      truncate(record.productSku, 14),
      String(record.qtyEntered || 0),
      String(record.movementQty || 0),
      truncate(record.locator, 14),
      truncate(record.orderLine, 16)
    ]
    for (let i = 0; i < values.length; i++) {
      page.drawText(values[i], { x: xPos, y: yPos, size: fontSize, font })
      xPos += widths[i]
    }
    return yPos - lineHeight
  }

  let page = addNewPage()
  let yPos = pageHeight - margin

  const title = isGerman ? 'Warenausgangszeilen Bericht' : 'Shipment Line Report'
  page.drawText(title, { x: margin, y: yPos, size: 16, font: fontBold })
  yPos -= 25

  page.drawText((isGerman ? 'Erstellt am: ' : 'Generated on: ') + formatDate(new Date(), lang), { x: margin, y: yPos, size: 10, font })
  yPos -= 15

  page.drawText((isGerman ? 'Anzahl Eintraege: ' : 'Total Records: ') + records.length, { x: margin, y: yPos, size: 10, font })
  yPos -= 15

  const totalMovQty = records.reduce((sum, r) => sum + (r.movementQty || 0), 0)
  page.drawText((isGerman ? 'Gesamtbewegungsmenge: ' : 'Total Movement Qty: ') + totalMovQty, { x: margin, y: yPos, size: 10, font })
  yPos -= 25

  yPos = drawHeader(page, yPos)

  for (const record of records) {
    if (yPos < margin + 40) {
      page = addNewPage()
      yPos = pageHeight - margin
      yPos = drawHeader(page, yPos)
    }
    yPos = drawRow(page, record, yPos)
  }

  yPos -= 20
  if (yPos < margin + 60) {
    page = addNewPage()
    yPos = pageHeight - margin
  }
  page.drawText((isGerman ? 'Gesamtbewegungsmenge: ' : 'Total Movement Qty: ') + totalMovQty, { x: margin, y: yPos, size: 12, font: fontBold })

  const pdfBytes = await pdfDoc.save()
  return Buffer.from(pdfBytes)
}

const generateCsvReport = (records: InOutLineRecord[], lang: string) => {
  const isGerman = lang.startsWith('de')
  const headers = isGerman
    ? ['Nr.', 'Organisation', 'Lieferung', 'Produktname', 'Produktwert', 'SKU', 'MPN', 'ME', 'Menge Eingabe', 'Bewegungsmenge', 'Lagerplatz', 'Auftragsposition', 'Zeile']
    : ['No.', 'Organization', 'Shipment', 'Product Name', 'Product Value', 'SKU', 'MPN', 'UOM', 'Qty Entered', 'Movement Qty', 'Locator', 'Order Line', 'Line']

  const rows = records.map((r, i) => [
    i + 1, r.organization || '', r.shipment || '', r.productName || '',
    r.productValue || '', r.productSku || '', r.productMpn || '',
    r.uom || '', r.qtyEntered || 0, r.movementQty || 0,
    r.locator || '', r.orderLine || '', r.line || 0
  ])

  const csvContent = [
    headers.join(';'),
    ...rows.map(row => row.map(cell => `"${String(cell).replace(/"/g, '""')}"`).join(';'))
  ].join('\n')

  return Buffer.from('\uFEFF' + csvContent, 'utf-8')
}

const generateHtmlEmail = (lang: string, recordCount: number, totalMovQty: number) => {
  const isGerman = lang.startsWith('de')
  const title = isGerman ? 'Warenausgangszeilen Bericht' : 'Shipment Line Report'
  const greeting = isGerman ? 'Sehr geehrte Damen und Herren,' : 'Dear Sir or Madam,'
  const body = isGerman
    ? 'anbei finden Sie den Warenausgangszeilen-Bericht als Anhang.'
    : 'Please find attached the shipment line report.'
  const linesLabel = isGerman ? 'Anzahl Zeilen' : 'Total Lines'
  const totalLabel = isGerman ? 'Gesamtbewegungsmenge' : 'Total Movement Qty'
  const closing = isGerman ? 'Mit freundlichen Gruessen' : 'Best regards'
  const footer = isGerman ? 'Diese E-Mail wurde automatisch versendet.' : 'This email was sent automatically.'

  return `<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>${title}</title></head>
<body style="margin:0;padding:0;font-family:Arial,Helvetica,sans-serif;font-size:14px;line-height:1.6;color:#333;background-color:#f4f4f4;">
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="background-color:#f4f4f4;"><tr><td style="padding:20px 0;">
<table role="presentation" width="600" cellspacing="0" cellpadding="0" style="margin:0 auto;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 2px 4px rgba(0,0,0,0.1);">
<tr><td style="background-color:#2c3e50;padding:30px 40px;text-align:center;"><h1 style="margin:0;color:#fff;font-size:24px;font-weight:600;">${title}</h1></td></tr>
<tr><td style="padding:40px;">
<p style="margin:0 0 20px 0;">${greeting}</p>
<p style="margin:0 0 20px 0;">${body}</p>
<table role="presentation" cellspacing="0" cellpadding="0" style="width:100%;border-collapse:collapse;margin:20px 0;border:1px solid #e0e0e0;border-radius:6px;">
<tr style="background-color:#f8f9fa;"><td style="padding:12px 16px;border-bottom:1px solid #e0e0e0;font-weight:600;">${linesLabel}</td><td style="padding:12px 16px;border-bottom:1px solid #e0e0e0;">${recordCount}</td></tr>
<tr><td style="padding:12px 16px;font-weight:600;">${totalLabel}</td><td style="padding:12px 16px;">${totalMovQty}</td></tr>
</table>
<p style="margin:20px 0 0 0;">${closing}</p>
</td></tr>
<tr><td style="background-color:#f8f9fa;padding:20px 40px;text-align:center;border-top:1px solid #eee;"><p style="margin:0;font-size:12px;color:#888;">${footer}</p></td></tr>
</table></td></tr></table></body></html>`
}

const handleFunc = async (event: any, authToken: any = null) => {
  const body = await readBody(event)
  const { toEmail, ccEmail, subject, records, language = 'de_DE', format = 'pdf' } = body

  if (!toEmail) return { status: 400, message: 'Recipient email is required' }
  if (!records || !Array.isArray(records) || records.length === 0) return { status: 400, message: 'No records to send' }

  const isGerman = language.startsWith('de')
  const totalMovQty = records.reduce((sum: number, r: InOutLineRecord) => sum + (r.movementQty || 0), 0)

  let attachmentBuffer: Buffer
  let attachmentFilename: string
  let attachmentContentType: string

  if (format === 'csv') {
    attachmentBuffer = generateCsvReport(records, language)
    attachmentFilename = `${isGerman ? 'Warenausgangszeilen_Bericht' : 'Shipment_Line_Report'}_${new Date().toISOString().split('T')[0]}.csv`
    attachmentContentType = 'text/csv; charset=utf-8'
  } else {
    attachmentBuffer = await generatePdfReport(records, language)
    attachmentFilename = `${isGerman ? 'Warenausgangszeilen_Bericht' : 'Shipment_Line_Report'}_${new Date().toISOString().split('T')[0]}.pdf`
    attachmentContentType = 'application/pdf'
  }

  const htmlContent = generateHtmlEmail(language, records.length, totalMovQty)

  const transporter = nodemailer.createTransport({
    host: 'localhost', port: 25, secure: false,
    tls: { rejectUnauthorized: false }
  })

  const emailOptions: any = {
    from: 'no-reply@logyou.de',
    to: toEmail,
    subject: subject || (isGerman ? 'Warenausgangszeilen Bericht' : 'Shipment Line Report'),
    html: htmlContent,
    attachments: [{ filename: attachmentFilename, content: attachmentBuffer, contentType: attachmentContentType }]
  }
  if (ccEmail) emailOptions.cc = ccEmail

  try {
    await transporter.sendMail(emailOptions)
  } catch (err: any) {
    console.error('Email send error:', err)
    return { status: 500, message: `Failed to send shipment line report: ${err.message}` }
  }

  return { status: 200, message: 'Shipment line report sent successfully' }
}

export default defineEventHandler(async (event) => {
  let data: any = {}
  try {
    data = await handleFunc(event)
  } catch (err: any) {
    try {
      let authToken: any = await refreshTokenHelper(event)
      data = await handleFunc(event, authToken)
    } catch (error: any) {
      data = errorHandlingHelper(err?.data ?? err, error?.data ?? error)
      forceLogoutHelper(event, data)
    }
  }
  return data
})
