/**
 * Branded "Anlage zur Rechnung – Nachbelastung DHL-Versandkosten" PDF (pdfmake,
 * A4 landscape). Customer-facing breakdown of the Nachbelastung positions of a
 * fulfillment fee invoice: one row per shipment with the DHL invoice number and
 * the DHL cost components as printed on the DHL invoice.
 * Reuses BRAND + header/footer from the offer generator (same look as the
 * partner report / price sheet).
 */
import { BRAND, buildBrandHeader, buildBrandFooter, getQuoteLogos } from '../offers/quotePdf'
import type { DhlSurchargeReportData, DhlSurchargeRow } from './dhlSurchargeReportData'

const A4_LANDSCAPE_WIDTH = 841.89

export const SURCHARGE_REPORT_TEXTS: any = {
  de: {
    docTitle: 'Anlage zur Rechnung',
    subtitle: 'Nachbelastung DHL-Versandkosten',
    dateWord: 'Stand',
    page: 'Seite',
    of: 'von',
    invoiceNo: 'Rechnungsnummer',
    invoiceDate: 'Rechnungsdatum',
    period: 'Leistungszeitraum',
    shipRange: 'Versanddaten der Sendungen',
    customer: 'Kunde',
    shipments: 'Sendungen',
    intro: 'Diese Anlage schlüsselt die Rechnungsposition(en) „Nachbelastung DHL Paket (Zuschläge lt. DHL-Rechnung)“ je Sendung auf. ' +
      'Die Versandkosten werden zum Versandzeitpunkt auf Basis der Vertragspreise berechnet. Die DHL-Rechnung geht erst ein bis zwei Wochen später ein ' +
      'und enthält zusätzliche Entgelte, die bei der Berechnung noch nicht bekannt waren – z. B. Maut- und CO2-Zuschlag, Energiezuschlag, Codierentgelt, ' +
      'Transportversicherung, Rücksendeentgelt oder Premium-Zuschläge im internationalen Versand. Nachbelastet wird je Sendung ausschließlich die Differenz ' +
      'zwischen dem von DHL in Rechnung gestellten Gesamtbetrag und dem bereits berechneten Betrag. Erfasst werden alle Sendungen, für die seit der ' +
      'ursprünglichen Versandkostenberechnung weitere DHL-Entgelte eingegangen sind – daher können auch Sendungen aus zurückliegenden Monaten enthalten sein. ' +
      'Negative Beträge sind Gutschriften.',
    sumTitle: 'Rechnungspositionen',
    position: 'Rechnungsposition',
    count: 'Sendungen',
    amount: 'Betrag (netto)',
    total: 'Gesamt',
    breakdownTitle: 'Zusammensetzung der DHL-Entgelte',
    breakdownHint: 'Summe der von DHL berechneten Entgelte über alle hier aufgeführten Sendungen, gegliedert nach Entgeltart.',
    component: 'Entgeltart lt. DHL-Rechnung',
    dhlTotal: 'DHL-Entgelte gesamt',
    booked: 'bereits berechnet',
    difference: 'Nachbelastung',
    dhlInvoices: 'Referenzierte DHL-Rechnungen',
    detailTitle: 'Einzelnachweis je Sendung',
    shipment: 'Sendung',
    shipDate: 'Versand',
    order: 'Auftrag / Referenz',
    country: 'Land',
    tracking: 'Sendungsnummer',
    dhlInvoice: 'DHL-Rechnung',
    positions: 'DHL-Positionen lt. Rechnung',
    dhlSum: 'DHL gesamt',
    subtotal: 'Zwischensumme',
    calcSource: 'lt. Frachtkalkulation',
    noPositions: '–',
    noteTitle: 'Hinweis',
    note: 'Alle Beträge in EUR netto. Die Entgeltbezeichnungen entsprechen den Positionen der DHL-Rechnung. Rückfragen bitte unter Angabe der Sendungsnummer an info@logyou.de.'
  },
  en: {
    docTitle: 'Invoice attachment',
    subtitle: 'DHL shipping cost surcharges',
    dateWord: 'As of',
    page: 'Page',
    of: 'of',
    invoiceNo: 'Invoice no.',
    invoiceDate: 'Invoice date',
    period: 'Period of performance',
    shipRange: 'Ship dates of the shipments',
    customer: 'Customer',
    shipments: 'shipments',
    intro: 'This attachment breaks down the invoice position(s) "Nachbelastung DHL Paket (surcharges per DHL invoice)" per shipment. ' +
      'Shipping costs are charged at dispatch based on the contract rates. The DHL invoice arrives one to two weeks later and contains additional ' +
      'charges that were not known at that time – e.g. toll and CO2 surcharge, energy surcharge, coding fee, transport insurance, return fee or ' +
      'premium surcharges for international parcels. Only the difference between the total DHL charged and the amount already invoiced is ' +
      'passed on per shipment. All shipments for which further DHL charges have been received since the original shipping cost calculation are ' +
      'included – shipments from previous months may therefore appear as well. Negative amounts are credits.',
    sumTitle: 'Invoice positions',
    position: 'Invoice position',
    count: 'Shipments',
    amount: 'Amount (net)',
    total: 'Total',
    breakdownTitle: 'Composition of the DHL charges',
    breakdownHint: 'Sum of the charges invoiced by DHL across all shipments listed here, by type of charge.',
    component: 'Charge type per DHL invoice',
    dhlTotal: 'DHL charges total',
    booked: 'already invoiced',
    difference: 'Surcharge',
    dhlInvoices: 'Referenced DHL invoices',
    detailTitle: 'Detail per shipment',
    shipment: 'Shipment',
    shipDate: 'Shipped',
    order: 'Order / reference',
    country: 'Country',
    tracking: 'Tracking no.',
    dhlInvoice: 'DHL invoice',
    positions: 'DHL positions per invoice',
    dhlSum: 'DHL total',
    subtotal: 'Subtotal',
    calcSource: 'per freight calculation',
    noPositions: '–',
    noteTitle: 'Note',
    note: 'All amounts in EUR net. The charge names correspond to the positions on the DHL invoice. For questions please quote the tracking number and contact info@logyou.de.'
  }
}

const formatDateLocal = (iso: string | null | undefined, language: string): string => {
  if (!iso) return '—'
  const d = new Date(iso)
  if (isNaN(d.getTime())) return String(iso)
  const dd = String(d.getDate()).padStart(2, '0')
  const mm = String(d.getMonth() + 1).padStart(2, '0')
  return language === 'en' ? `${d.getFullYear()}-${mm}-${dd}` : `${dd}.${mm}.${d.getFullYear()}`
}

// period_of_performance is free text ("Oktober 2026") on fee invoices; only ISO dates are reformatted.
const formatPeriod = (value: string | null | undefined, language: string): string => {
  if (!value) return '—'
  const txt = String(value).trim()
  if (!/^\d{4}-\d{2}(-\d{2})?/.test(txt)) return txt
  const d = new Date(txt)
  if (isNaN(d.getTime())) return txt
  return d.toLocaleDateString(language === 'en' ? 'en-GB' : 'de-DE', { month: 'long', year: 'numeric' })
}

export const sanitizeSurchargeReportFilename = (documentNo: string): string => {
  const safe = String(documentNo || 'Rechnung').replace(/[^A-Za-z0-9-_]/g, '') || 'Rechnung'
  return `Nachbelastung-DHL_${safe}.pdf`
}

export const buildDhlSurchargeReportDocDefinition = (data: DhlSurchargeReportData, logos: { light: string | null; dark: string | null }) => {
  const inv = data.invoice!
  const language = inv.language === 'en' ? 'en' : 'de'
  const T = SURCHARGE_REPORT_TEXTS[language]
  const rows = data.rows || []
  const nowIso = new Date().toISOString()
  const shipDates = rows.map(r => r.shipDate).filter(Boolean).map(d => new Date(d as string).getTime()).filter(n => Number.isFinite(n))
  const shipRange = shipDates.length
    ? `${formatDateLocal(new Date(Math.min(...shipDates)).toISOString(), language)} – ${formatDateLocal(new Date(Math.max(...shipDates)).toISOString(), language)}`
    : '—'

  const euro = (amount: any) =>
    new Intl.NumberFormat(language === 'en' ? 'en-IE' : 'de-DE', { style: 'currency', currency: 'EUR' }).format(Number(amount) || 0)
  const num = (amount: any) =>
    new Intl.NumberFormat(language === 'en' ? 'en-IE' : 'de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(Number(amount) || 0)

  const sectionTitle = (text: string) => ({
    stack: [
      { canvas: [{ type: 'rect', x: 0, y: 0, w: 26, h: 3, color: BRAND.orange }] },
      { text: String(text).toUpperCase(), fontSize: 11, bold: true, color: BRAND.navy, characterSpacing: 0.4, margin: [0, 5, 0, 0] }
    ],
    margin: [0, 16, 0, 8]
  })

  const zebraLayout = {
    hLineWidth: (i: number) => (i === 1 ? 0.75 : 0),
    vLineWidth: () => 0,
    hLineColor: () => BRAND.grayLine,
    fillColor: (rowIndex: number) => (rowIndex === 0 ? BRAND.navy : rowIndex % 2 === 0 ? BRAND.zebra : null),
    paddingLeft: () => 6,
    paddingRight: () => 6,
    paddingTop: () => 4,
    paddingBottom: () => 4
  }
  const detailLayout = {
    ...zebraLayout,
    paddingLeft: () => 4,
    paddingRight: () => 4,
    paddingTop: () => 2.5,
    paddingBottom: () => 2.5
  }

  const th = (text: string, alignment: string = 'left') => ({ text, style: 'tableHeader', alignment })
  const td = (text: any, opts: any = {}) => ({ text: String(text ?? ''), fontSize: 9, ...opts })
  const tdS = (text: any, opts: any = {}) => ({ text: String(text ?? ''), fontSize: 7.2, ...opts })

  // ---- Meta block
  const kv = (label: string, value: any) => ({
    columns: [
      { width: 120, text: label, fontSize: 9, color: BRAND.grayText },
      { width: '*', text: String(value || '—'), fontSize: 9, bold: true }
    ],
    margin: [0, 0, 0, 2]
  })

  const content: any[] = [
    {
      columns: [
        {
          width: '*',
          stack: [
            { text: `${T.docTitle} ${inv.documentNo}`, fontSize: 16, bold: true, color: BRAND.navy },
            { text: T.subtitle, fontSize: 11, color: BRAND.orange, bold: true, margin: [0, 2, 0, 10] },
            kv(T.customer, inv.partnerName),
            kv(T.invoiceNo, inv.documentNo),
            kv(T.invoiceDate, formatDateLocal(inv.dateInvoiced, language)),
            kv(T.period, formatPeriod(inv.periodOfPerformance, language)),
            kv(T.shipRange, shipRange)
          ]
        },
        {
          width: 260,
          stack: [
            {
              table: {
                widths: ['*'],
                body: [[{
                  border: [false, false, false, false],
                  fillColor: BRAND.navy,
                  margin: [12, 10, 12, 10],
                  stack: [
                    { text: T.difference, color: BRAND.headerSub, fontSize: 8 },
                    { text: euro(data.totals?.difference), color: BRAND.white, fontSize: 20, bold: true, margin: [0, 2, 0, 4] },
                    { text: `${data.totals?.count || 0} ${T.shipments}`, color: BRAND.white, fontSize: 9 }
                  ]
                }]]
              },
              layout: 'noBorders'
            }
          ]
        }
      ],
      columnGap: 20
    },
    { text: T.intro, fontSize: 9, lineHeight: 1.3, margin: [0, 12, 0, 0], alignment: 'justify' }
  ]

  // ---- Summary per invoice position
  const sumRows: any[][] = (data.byProduct || []).map(bp => [
    td(bp.productName || `#${bp.productId}`),
    td(bp.count, { alignment: 'right' }),
    td(euro(bp.total), { alignment: 'right', bold: true })
  ])
  sumRows.push([
    td(T.total, { bold: true }),
    td(data.totals?.count, { alignment: 'right', bold: true }),
    td(euro(data.totals?.difference), { alignment: 'right', bold: true, color: BRAND.orange })
  ])
  content.push({
    unbreakable: true,
    stack: [
      sectionTitle(T.sumTitle),
      {
        table: { headerRows: 1, widths: ['*', 90, 120], body: [[th(T.position), th(T.count, 'right'), th(T.amount, 'right')], ...sumRows] },
        layout: zebraLayout
      }
    ]
  })

  // ---- Breakdown by DHL charge type
  const brRows: any[][] = (data.bySurcharge || []).map(s => [
    td(s.label),
    td(s.count, { alignment: 'right' }),
    td(euro(s.total), { alignment: 'right' })
  ])
  brRows.push(
    [td(T.dhlTotal, { bold: true }), td('', {}), td(euro(data.totals?.dhlTotal), { alignment: 'right', bold: true })],
    [td(T.booked, { color: BRAND.grayText }), td('', {}), td('- ' + euro(data.totals?.booked), { alignment: 'right', color: BRAND.grayText })],
    [td(T.difference, { bold: true }), td('', {}), td(euro(data.totals?.difference), { alignment: 'right', bold: true, color: BRAND.orange })]
  )
  content.push({
    unbreakable: true,
    stack: [
      sectionTitle(T.breakdownTitle),
      { text: T.breakdownHint, fontSize: 8.5, color: BRAND.grayText, margin: [0, 0, 0, 6] },
      {
        table: { headerRows: 1, widths: ['*', 90, 120], body: [[th(T.component), th(T.count, 'right'), th(T.amount, 'right')], ...brRows] },
        layout: zebraLayout
      }
    ]
  })

  if ((data.dhlInvoiceNos || []).length) {
    content.push({
      margin: [0, 10, 0, 0],
      columns: [
        { width: 160, text: T.dhlInvoices, fontSize: 9, color: BRAND.grayText },
        { width: '*', text: data.dhlInvoiceNos!.join(', '), fontSize: 9 }
      ]
    })
  }

  // ---- Detail per invoice position
  const positionsText = (row: DhlSurchargeRow): string => {
    if (row.source === 'calc') return `${T.calcSource} ${num(row.dhlTotal)}`
    if (!row.positions.length) return T.noPositions
    return row.positions.map(p => `${p.label} ${num(p.amount)}`).join(' · ')
  }

  const header = [
    th(T.shipment), th(T.shipDate), th(T.order), th(T.country), th(T.tracking), th(T.dhlInvoice),
    th(T.positions), th(T.dhlSum, 'right'), th(T.booked, 'right'), th(T.difference, 'right')
  ]
  const widths = [40, 46, 78, 26, 92, 54, '*', 46, 50, 52]

  content.push({ text: '', pageBreak: 'before' })
  content.push(sectionTitle(T.detailTitle))

  for (const bp of data.byProduct || []) {
    const group = rows.filter(r => r.productId === bp.productId)
    const body: any[][] = [header]
    for (const r of group) {
      body.push([
        tdS(r.shipmentNo, { bold: true }),
        tdS(formatDateLocal(r.shipDate, language)),
        tdS([r.orderNo, r.orderReference].filter(Boolean).join(' / ')),
        tdS(r.countryCode || ''),
        tdS(r.trackingNo || ''),
        tdS(r.dhlInvoiceNos.join(', ')),
        tdS(positionsText(r)),
        tdS(r.dhlTotal != null ? num(r.dhlTotal) : '', { alignment: 'right' }),
        tdS(r.booked != null ? num(r.booked) : '', { alignment: 'right' }),
        tdS(num(r.amount), { alignment: 'right', bold: true, color: r.amount < 0 ? '#1f7a3d' : BRAND.text })
      ])
    }
    body.push([
      tdS(`${T.subtotal} – ${bp.productName}`, { bold: true, colSpan: 7 }), {}, {}, {}, {}, {}, {},
      tdS('', {}),
      tdS(`${group.length} ${T.shipments}`, { alignment: 'right', color: BRAND.grayText }),
      tdS(num(bp.total), { alignment: 'right', bold: true, color: BRAND.orange })
    ])
    content.push({ text: `${bp.productName} — ${group.length} ${T.shipments}`, fontSize: 10, bold: true, color: BRAND.navy, margin: [0, 6, 0, 4] })
    content.push({
      table: { headerRows: 1, dontBreakRows: true, widths, body },
      layout: detailLayout,
      margin: [0, 0, 0, 8]
    })
  }

  content.push({
    margin: [0, 10, 0, 0],
    stack: [
      { text: T.noteTitle, fontSize: 8.5, bold: true, color: BRAND.navy },
      { text: T.note, fontSize: 8.5, color: BRAND.grayText, margin: [0, 2, 0, 0] }
    ]
  })

  return {
    pageSize: 'A4',
    pageOrientation: 'landscape',
    pageMargins: [40, 100, 40, 86],
    info: {
      title: `${T.docTitle} ${inv.documentNo} – ${T.subtitle}`,
      author: 'LogYou GmbH',
      subject: T.subtitle
    },
    header: buildBrandHeader(`${T.docTitle} ${inv.documentNo}`, `${inv.partnerName}  ·  ${T.subtitle}  ·  ${T.dateWord} ${formatDateLocal(nowIso, language)}`, logos.dark, A4_LANDSCAPE_WIDTH),
    footer: buildBrandFooter(T.page, T.of, A4_LANDSCAPE_WIDTH),
    content,
    styles: {
      tableHeader: { fontSize: 7.6, bold: true, color: BRAND.white }
    },
    defaultStyle: {
      font: 'Roboto',
      fontSize: 9,
      color: BRAND.text,
      lineHeight: 1.2
    }
  }
}

/** Build the final PDF buffer + authoritative filename. */
export const generateDhlSurchargeReportPdf = async (data: DhlSurchargeReportData): Promise<{ buffer: Buffer; filename: string }> => {
  // (defensive vfs extraction — the export shape varies by pdfmake
  // version/bundler, do not simplify; same block as quotePdf/partnerReportPdf).
  const pdfMake = await import('pdfmake/build/pdfmake.js')
  const pdfFonts = await import('pdfmake/build/vfs_fonts.js')

  // @ts-ignore - Set up virtual file system
  const pdfMakeInstance = pdfMake.default || pdfMake

  let vfs = null
  if ((pdfFonts as any).pdfMake?.vfs) {
    vfs = (pdfFonts as any).pdfMake.vfs
  } else if ((pdfFonts as any).default?.pdfMake?.vfs) {
    vfs = (pdfFonts as any).default.pdfMake.vfs
  } else if ((pdfFonts as any).default?.vfs) {
    vfs = (pdfFonts as any).default.vfs
  } else if ((pdfFonts as any).vfs) {
    vfs = (pdfFonts as any).vfs
  } else if ((pdfFonts as any).default) {
    const defaultKeys = Object.keys((pdfFonts as any).default)
    if (defaultKeys.some((key: string) => key.endsWith('.ttf'))) {
      vfs = (pdfFonts as any).default
    }
  }
  if (!vfs) {
    throw new Error('Could not find vfs fonts in pdfmake fonts module')
  }
  pdfMakeInstance.vfs = vfs

  const logos = await getQuoteLogos()
  const docDefinition = buildDhlSurchargeReportDocDefinition(data, logos)
  const filename = sanitizeSurchargeReportFilename(data.invoice?.documentNo || '')

  const buffer = await new Promise<Buffer>((resolve, reject) => {
    try {
      pdfMakeInstance.createPdf(docDefinition).getBuffer((buf: Buffer) => resolve(buf))
    } catch (error) {
      reject(error)
    }
  })
  return { buffer, filename }
}
