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 ProductRecord {
  name: string
  sku: string
  ean: string
  qtyOnHand: number
  locatorX?: string
  locatorY?: string
  locatorZ?: string
  locatorPriority?: number
  locatorTypeName?: string
}

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'
  })
}

// Format a 'YYYY-MM-DD' string to a DD.MM.YYYY label (empty string passes through)
const formatAsOf = (ymd: string) => {
  if (!ymd) return ''
  const [y, m, d] = ymd.split('-')
  return `${d}.${m}.${y}`
}

const generatePdfReport = async (records: ProductRecord[], organizationName: string, lang: string, showByLocator: boolean = false, asOfDate: 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)

  // Use landscape for locator view to fit more columns
  const pageWidth = showByLocator ? 841.89 : 595.28 // A4 landscape or portrait
  const pageHeight = showByLocator ? 595.28 : 841.89
  const margin = 40
  const lineHeight = 16
  const headerHeight = 22

  // Column widths based on view mode
  const colWidths = showByLocator
    ? { name: 150, sku: 80, ean: 100, qty: 50, x: 50, y: 50, z: 50, priority: 55, type: 90 }
    : { name: 200, sku: 100, ean: 120, qty: 75 }

  const addNewPage = () => {
    const page = pdfDoc.addPage([pageWidth, pageHeight])
    return page
  }

  const drawHeader = (page: any, yPos: number) => {
    const headers = showByLocator
      ? (isGerman
          ? ['Produktname', 'SKU', 'EAN', 'Menge', 'X', 'Y', 'Z', 'Prioritaet', 'Lagertyp']
          : ['Product Name', 'SKU', 'EAN', 'Qty', 'X', 'Y', 'Z', 'Priority', 'Locator Type'])
      : (isGerman
          ? ['Produktname', 'SKU', 'EAN', 'Bestand']
          : ['Product Name', 'SKU', 'EAN', 'Qty On Hand'])

    let xPos = margin

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

    // Header text
    const fontSize = showByLocator ? 8 : 10
    page.drawText(headers[0], { x: xPos, y: yPos, size: fontSize, font: fontBold })
    xPos += colWidths.name
    page.drawText(headers[1], { x: xPos, y: yPos, size: fontSize, font: fontBold })
    xPos += colWidths.sku
    page.drawText(headers[2], { x: xPos, y: yPos, size: fontSize, font: fontBold })
    xPos += colWidths.ean
    page.drawText(headers[3], { x: xPos, y: yPos, size: fontSize, font: fontBold })

    if (showByLocator) {
      xPos += colWidths.qty
      page.drawText(headers[4], { x: xPos, y: yPos, size: fontSize, font: fontBold })
      xPos += colWidths.x
      page.drawText(headers[5], { x: xPos, y: yPos, size: fontSize, font: fontBold })
      xPos += colWidths.y
      page.drawText(headers[6], { x: xPos, y: yPos, size: fontSize, font: fontBold })
      xPos += colWidths.z
      page.drawText(headers[7], { x: xPos, y: yPos, size: fontSize, font: fontBold })
      xPos += colWidths.priority
      page.drawText(headers[8], { x: xPos, y: yPos, size: fontSize, font: fontBold })
    }

    return yPos - headerHeight - 5
  }

  const drawRow = (page: any, record: ProductRecord, yPos: number) => {
    let xPos = margin
    const fontSize = showByLocator ? 7 : 9
    const maxNameLength = showByLocator ? 25 : 35

    // Truncate name if too long
    let displayName = record.name || ''
    if (displayName.length > maxNameLength) {
      displayName = displayName.substring(0, maxNameLength - 3) + '...'
    }

    page.drawText(displayName, { x: xPos, y: yPos, size: fontSize, font })
    xPos += colWidths.name
    page.drawText(record.sku || '', { x: xPos, y: yPos, size: fontSize, font })
    xPos += colWidths.sku
    page.drawText(record.ean || '', { x: xPos, y: yPos, size: fontSize, font })
    xPos += colWidths.ean
    page.drawText(String(record.qtyOnHand || 0), { x: xPos, y: yPos, size: fontSize, font })

    if (showByLocator) {
      xPos += colWidths.qty
      page.drawText(record.locatorX || '', { x: xPos, y: yPos, size: fontSize, font })
      xPos += colWidths.x
      page.drawText(record.locatorY || '', { x: xPos, y: yPos, size: fontSize, font })
      xPos += colWidths.y
      page.drawText(record.locatorZ || '', { x: xPos, y: yPos, size: fontSize, font })
      xPos += colWidths.z
      page.drawText(String(record.locatorPriority ?? ''), { x: xPos, y: yPos, size: fontSize, font })
      xPos += colWidths.priority

      let locatorType = record.locatorTypeName || ''
      if (locatorType.length > 15) {
        locatorType = locatorType.substring(0, 12) + '...'
      }
      page.drawText(locatorType, { x: xPos, y: yPos, size: fontSize, font })
    }

    return yPos - lineHeight
  }

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

  const asOf = formatAsOf(asOfDate)

  // Title
  const title = isGerman
    ? `Bestandsbericht${asOf ? ` (Stichtag ${asOf})` : ''} - ${organizationName}`
    : `Stock Report${asOf ? ` (as of ${asOf})` : ''} - ${organizationName}`
  page.drawText(title, { x: margin, y: yPos, size: 16, font: fontBold })
  yPos -= 25

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

  // Point-in-time stichtag line
  if (asOf) {
    const asOfLabel = isGerman ? 'Bestand zum Stichtag: ' : 'Stock as of: '
    page.drawText(asOfLabel + asOf, { x: margin, y: yPos, size: 10, font: fontBold })
    yPos -= 15
  }

  // Record count
  const countLabel = isGerman ? 'Anzahl Eintraege: ' : 'Total Records: '
  page.drawText(countLabel + records.length, { x: margin, y: yPos, size: 10, font })

  // View mode indicator
  if (showByLocator) {
    const viewLabel = isGerman ? 'Ansicht: Nach Lagerplatz' : 'View: By Locator'
    page.drawText(viewLabel, { x: margin + 150, y: yPos, size: 10, font })
  }
  yPos -= 30

  // Draw table header
  yPos = drawHeader(page, yPos)

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

  // Summary at the bottom
  yPos -= 20
  if (yPos < margin + 60) {
    page = addNewPage()
    yPos = pageHeight - margin
  }

  const totalQty = records.reduce((sum, r) => sum + (r.qtyOnHand || 0), 0)
  const summaryLabel = isGerman ? 'Gesamtbestand: ' : 'Total Stock: '
  page.drawText(summaryLabel + totalQty, { x: margin, y: yPos, size: 12, font: fontBold })

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

const generateHtmlEmailDE = (organizationName: string, recordCount: number, totalQty: number, asOfDate: string = '') => {
  const asOf = formatAsOf(asOfDate)
  const asOfRow = asOf
    ? `<tr style="background-color: #fff8e1;">
                  <td style="padding: 12px 16px; border-bottom: 1px solid #e0e0e0; font-weight: 600;">Stichtag</td>
                  <td style="padding: 12px 16px; border-bottom: 1px solid #e0e0e0;">${asOf}</td>
                </tr>`
    : ''
  const intro = asOf
    ? `anbei finden Sie den Bestandsbericht zum Stichtag <strong>${asOf}</strong> als PDF-Anhang.`
    : 'anbei finden Sie den aktuellen Bestandsbericht als PDF-Anhang.'
  return `
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Bestandsbericht - ${organizationName}</title>
</head>
<body style="margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; font-size: 14px; line-height: 1.6; color: #333333; 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-color: #ffffff; 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: #ffffff; font-size: 24px; font-weight: 600;">Bestandsbericht</h1>
              <p style="margin: 10px 0 0 0; color: #ffffff; font-size: 16px;">${organizationName}</p>
            </td>
          </tr>
          <tr>
            <td style="padding: 40px;">
              <p style="margin: 0 0 20px 0;">Sehr geehrte Damen und Herren,</p>
              <p style="margin: 0 0 20px 0;">${intro}</p>
              <table role="presentation" cellspacing="0" cellpadding="0" style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #e0e0e0; border-radius: 6px;">
                ${asOfRow}
                <tr style="background-color: #f8f9fa;">
                  <td style="padding: 12px 16px; border-bottom: 1px solid #e0e0e0; font-weight: 600;">Anzahl Produkte</td>
                  <td style="padding: 12px 16px; border-bottom: 1px solid #e0e0e0;">${recordCount}</td>
                </tr>
                <tr>
                  <td style="padding: 12px 16px; font-weight: 600;">Gesamtbestand</td>
                  <td style="padding: 12px 16px;">${totalQty}</td>
                </tr>
              </table>
              <p style="margin: 20px 0 0 0;">Mit freundlichen Gruessen</p>
            </td>
          </tr>
          <tr>
            <td style="background-color: #f8f9fa; padding: 20px 40px; text-align: center; border-top: 1px solid #eeeeee;">
              <p style="margin: 0; font-size: 12px; color: #888888;">
                Diese E-Mail wurde automatisch versendet.
              </p>
            </td>
          </tr>
        </table>
      </td>
    </tr>
  </table>
</body>
</html>
`
}

const generateHtmlEmailEN = (organizationName: string, recordCount: number, totalQty: number, asOfDate: string = '') => {
  const asOf = formatAsOf(asOfDate)
  const asOfRow = asOf
    ? `<tr style="background-color: #fff8e1;">
                  <td style="padding: 12px 16px; border-bottom: 1px solid #e0e0e0; font-weight: 600;">As of date</td>
                  <td style="padding: 12px 16px; border-bottom: 1px solid #e0e0e0;">${asOf}</td>
                </tr>`
    : ''
  const intro = asOf
    ? `Please find attached the stock report as of <strong>${asOf}</strong> as a PDF.`
    : 'Please find attached the current stock report as a PDF.'
  return `
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Stock Report - ${organizationName}</title>
</head>
<body style="margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; font-size: 14px; line-height: 1.6; color: #333333; 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-color: #ffffff; 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: #ffffff; font-size: 24px; font-weight: 600;">Stock Report</h1>
              <p style="margin: 10px 0 0 0; color: #ffffff; font-size: 16px;">${organizationName}</p>
            </td>
          </tr>
          <tr>
            <td style="padding: 40px;">
              <p style="margin: 0 0 20px 0;">Dear Sir or Madam,</p>
              <p style="margin: 0 0 20px 0;">${intro}</p>
              <table role="presentation" cellspacing="0" cellpadding="0" style="width: 100%; border-collapse: collapse; margin: 20px 0; border: 1px solid #e0e0e0; border-radius: 6px;">
                ${asOfRow}
                <tr style="background-color: #f8f9fa;">
                  <td style="padding: 12px 16px; border-bottom: 1px solid #e0e0e0; font-weight: 600;">Total Products</td>
                  <td style="padding: 12px 16px; border-bottom: 1px solid #e0e0e0;">${recordCount}</td>
                </tr>
                <tr>
                  <td style="padding: 12px 16px; font-weight: 600;">Total Stock</td>
                  <td style="padding: 12px 16px;">${totalQty}</td>
                </tr>
              </table>
              <p style="margin: 20px 0 0 0;">Best regards</p>
            </td>
          </tr>
          <tr>
            <td style="background-color: #f8f9fa; padding: 20px 40px; text-align: center; border-top: 1px solid #eeeeee;">
              <p style="margin: 0; font-size: 12px; color: #888888;">
                This email was sent automatically.
              </p>
            </td>
          </tr>
        </table>
      </td>
    </tr>
  </table>
</body>
</html>
`
}

const generateCsvReport = (records: ProductRecord[], organizationName: string, lang: string, showByLocator: boolean = false, asOfDate: string = '') => {
  const isGerman = lang.startsWith('de')
  const asOf = formatAsOf(asOfDate)

  const headers = showByLocator
    ? (isGerman
        ? ['Nr.', 'Produktname', 'SKU', 'EAN', 'Menge', 'X', 'Y', 'Z', 'Prioritaet', 'Lagertyp']
        : ['No.', 'Product Name', 'SKU', 'EAN', 'Qty', 'X', 'Y', 'Z', 'Priority', 'Locator Type'])
    : (isGerman
        ? ['Nr.', 'Produktname', 'SKU', 'EAN', 'Bestand']
        : ['No.', 'Product Name', 'SKU', 'EAN', 'Qty On Hand'])

  const rows = records.map((r, index) => {
    if (showByLocator) {
      return [
        index + 1,
        r.name || '',
        r.sku || '',
        r.ean || '',
        r.qtyOnHand || 0,
        r.locatorX || '',
        r.locatorY || '',
        r.locatorZ || '',
        r.locatorPriority ?? '',
        r.locatorTypeName || ''
      ]
    }
    return [
      index + 1,
      r.name || '',
      r.sku || '',
      r.ean || '',
      r.qtyOnHand || 0
    ]
  })

  const lines = []
  if (asOf) {
    const asOfLabel = isGerman ? 'Bestand zum Stichtag' : 'Stock as of'
    lines.push(`"${asOfLabel}: ${asOf}"`)
  }
  lines.push(headers.join(';'))
  lines.push(...rows.map(row => row.map(cell => `"${String(cell).replace(/"/g, '""')}"`).join(';')))
  const csvContent = lines.join('\n')

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

const handleFunc = async (event: any, authToken: any = null) => {
  let data: any = { status: 200, message: 'Stock report sent successfully' }
  const token = authToken ?? await getTokenHelper(event)
  const body = await readBody(event)

  const {
    toEmail,
    ccEmail,
    subject,
    records,
    organizationName,
    language = 'de_DE',
    showByLocator = false,
    asOfDate = '',
    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' }
  }

  if (!organizationName) {
    return { status: 400, message: 'Organization name is required' }
  }

  const isGerman = language.startsWith('de')
  const totalQty = records.reduce((sum: number, r: ProductRecord) => sum + (r.qtyOnHand || 0), 0)

  // Generate attachment based on format
  let attachmentBuffer: Buffer
  let attachmentFilename: string
  let attachmentContentType: string

  // Filename segment for point-in-time reports
  const asOfSeg = asOfDate ? `_asof_${asOfDate}` : ''

  if (format === 'csv') {
    attachmentBuffer = generateCsvReport(records, organizationName, language, showByLocator, asOfDate)
    attachmentFilename = isGerman
      ? `Bestandsbericht_${organizationName.replace(/[^a-zA-Z0-9]/g, '_')}${asOfSeg}_${new Date().toISOString().split('T')[0]}.csv`
      : `Stock_Report_${organizationName.replace(/[^a-zA-Z0-9]/g, '_')}${asOfSeg}_${new Date().toISOString().split('T')[0]}.csv`
    attachmentContentType = 'text/csv; charset=utf-8'
  } else {
    attachmentBuffer = await generatePdfReport(records, organizationName, language, showByLocator, asOfDate)
    attachmentFilename = isGerman
      ? `Bestandsbericht_${organizationName.replace(/[^a-zA-Z0-9]/g, '_')}${asOfSeg}_${new Date().toISOString().split('T')[0]}.pdf`
      : `Stock_Report_${organizationName.replace(/[^a-zA-Z0-9]/g, '_')}${asOfSeg}_${new Date().toISOString().split('T')[0]}.pdf`
    attachmentContentType = 'application/pdf'
  }

  // Generate HTML email
  const htmlContent = isGerman
    ? generateHtmlEmailDE(organizationName, records.length, totalQty, asOfDate)
    : generateHtmlEmailEN(organizationName, records.length, totalQty, asOfDate)

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

  // Build email options
  const emailOptions: any = {
    from: 'no-reply@logyou.de',
    to: toEmail,
    subject: subject || (isGerman ? `Bestandsbericht - ${organizationName}` : `Stock Report - ${organizationName}`),
    html: htmlContent,
    attachments: [
      {
        filename: attachmentFilename,
        content: attachmentBuffer,
        contentType: attachmentContentType
      }
    ]
  }

  if (ccEmail) {
    emailOptions.cc = ccEmail
  }

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

  return data
}

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
})