/**
 * Branded partner report (Partner-Report) PDF builder — pdfmake, server-side.
 * Internal one-pager for meetings: master data, addresses, contacts and the
 * partner's fulfillment pricing, in the LogYou quote/contract look.
 * Reuses BRAND + header/footer from the offer generator.
 */
import { BRAND, buildBrandHeader, buildBrandFooter, getQuoteLogos } from '../offers/quotePdf'

export const REPORT_TEXTS: any = {
  de: {
    docTitle: 'Partner-Report',
    dateWord: 'Stand',
    date: 'Datum',
    partnerNo: 'Partner-Nr.',
    status: 'Status',
    active: 'Aktiv',
    inactive: 'Inaktiv',
    type: 'Typ',
    customer: 'Kunde',
    vendor: 'Lieferant',
    fulfillmentCustomer: 'Fulfillment-Kunde',
    prospect: 'Interessent',
    masterData: 'Stammdaten',
    taxId: 'USt-IdNr.',
    hrgNumber: 'Handelsregister-Nr.',
    url: 'Webseite',
    language: 'Sprache',
    email: 'E-Mail',
    emailInvoice: 'Rechnungs-E-Mail',
    emailReturn: 'Retouren-E-Mail',
    partnerGroup: 'Partnergruppe',
    paymentTerm: 'Zahlungsbedingung',
    priceList: 'Preisliste',
    salesRep: 'Vertriebsmitarbeiter',
    contractSigned: 'Vertrag unterschrieben',
    description: 'Beschreibung',
    addresses: 'Adressen',
    addressName: 'Bezeichnung',
    address: 'Anschrift',
    phone: 'Telefon',
    addressType: 'Typ',
    billTo: 'Rechnung',
    shipTo: 'Lieferung',
    contacts: 'Ansprechpartner',
    contactName: 'Name',
    position: 'Position',
    mobile: 'Telefon 2',
    noRecords: 'Keine Einträge',
    pricingTitle: 'Fulfillment & Retoure — Preise',
    service: 'Leistung',
    dimension: 'Dimension',
    price: 'Preis',
    piece: '1 St.',
    hour: '1 Std.',
    perMonth: 'pro Monat',
    perM3: 'pro m³',
    orderBaseprice: 'Basispreis pro Auftrag',
    orderBasepriceTier: 'Basispreis pro Auftrag (Volumenstufe {n})',
    pickPrice: 'Preis pro Pick',
    pickPriceFrom: 'Preis pro Pick (ab dem {n}. Artikel)',
    returnBase: 'Retoure Basispreis',
    returnPerItem: 'Retoure pro Artikel',
    hourlyRate: 'Stundensatz (Arbeiten nach Aufwand)',
    storageTitle: 'Lagerung',
    storageType: 'Lagertyp',
    monthlyCost: 'Monatspreis',
    rentedQty: 'Gemietet',
    shelfSmall: 'Fachbodenregal M',
    shelfLarge: 'Fachbodenregal L',
    palletSpace: 'Palettenstellplatz',
    volumeStorage: 'Volumenlagerung',
    feesTitle: 'Monatliche Gebühren & Sonstiges',
    serviceFee: 'Servicepauschale',
    kpPriceLimit: 'Kleinpaket-Preislimit',
    kpExtraWeight: 'Kleinpaket-Zusatzgewicht',
    packagingTitle: 'Verpackung — Kartonpreise',
    cartonSize: 'Kartongröße',
    cartonPrice: 'Preis pro Karton',
    notSet: '—',
    page: 'Seite',
    of: 'von'
  },
  en: {
    docTitle: 'Partner Report',
    dateWord: 'As of',
    date: 'Date',
    partnerNo: 'Partner no.',
    status: 'Status',
    active: 'Active',
    inactive: 'Inactive',
    type: 'Type',
    customer: 'Customer',
    vendor: 'Vendor',
    fulfillmentCustomer: 'Fulfillment customer',
    prospect: 'Prospect',
    masterData: 'Master data',
    taxId: 'VAT ID',
    hrgNumber: 'Trade register no.',
    url: 'Website',
    language: 'Language',
    email: 'Email',
    emailInvoice: 'Invoice email',
    emailReturn: 'Return email',
    partnerGroup: 'Partner group',
    paymentTerm: 'Payment term',
    priceList: 'Price list',
    salesRep: 'Sales representative',
    contractSigned: 'Contract signed',
    description: 'Description',
    addresses: 'Addresses',
    addressName: 'Name',
    address: 'Address',
    phone: 'Phone',
    addressType: 'Type',
    billTo: 'Invoice',
    shipTo: 'Delivery',
    contacts: 'Contacts',
    contactName: 'Name',
    position: 'Position',
    mobile: 'Phone 2',
    noRecords: 'No records',
    pricingTitle: 'Fulfillment & Returns — Prices',
    service: 'Service',
    dimension: 'Dimension',
    price: 'Price',
    piece: '1 pc.',
    hour: '1 hr.',
    perMonth: 'per month',
    perM3: 'per m³',
    orderBaseprice: 'Base price per order',
    orderBasepriceTier: 'Base price per order (volume tier {n})',
    pickPrice: 'Price per pick',
    pickPriceFrom: 'Price per pick (from item no. {n})',
    returnBase: 'Return base price',
    returnPerItem: 'Return per item',
    hourlyRate: 'Hourly rate (work by effort)',
    storageTitle: 'Storage',
    storageType: 'Storage type',
    monthlyCost: 'Monthly price',
    rentedQty: 'Rented',
    shelfSmall: 'Shelf rack M',
    shelfLarge: 'Shelf rack L',
    palletSpace: 'Pallet space',
    volumeStorage: 'Volume storage',
    feesTitle: 'Monthly fees & other',
    serviceFee: 'Service fee',
    kpPriceLimit: 'Small parcel price limit',
    kpExtraWeight: 'Small parcel extra weight',
    packagingTitle: 'Packaging — carton prices',
    cartonSize: 'Carton size',
    cartonPrice: 'Price per carton',
    notSet: '—',
    page: 'Page',
    of: 'of'
  }
}

const fmt = (template: string, vars: Record<string, any>): string =>
  template.replace(/\{(\w+)\}/g, (_, k) => String(vars[k] ?? ''))

const formatDateLocal = (iso: string, language: string): string => {
  if (!iso) return '—'
  const d = new Date(iso)
  if (isNaN(d.getTime())) return 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()}`
}

// Authoritative filename — never trust the client's.
export const sanitizeReportFilename = (name: string, date?: string): string => {
  const safe = String(name || 'Partner')
    .replace(/ä/g, 'ae').replace(/ö/g, 'oe').replace(/ü/g, 'ue')
    .replace(/Ä/g, 'Ae').replace(/Ö/g, 'Oe').replace(/Ü/g, 'Ue')
    .replace(/ß/g, 'ss')
    .replace(/[^A-Za-z0-9-_ ]/g, '')
    .trim()
    .replace(/\s+/g, '-') || 'Partner'
  const d = date || new Date().toISOString().slice(0, 10)
  return `Partner-Report_${safe}_${d}.pdf`
}

export const buildPartnerReportDocDefinition = (data: any, logos: { light: string | null; dark: string | null }) => {
  const language = data?.language === 'en' ? 'en' : 'de'
  const T = REPORT_TEXTS[language]
  const p = data.partner || {}
  const pr = data.pricing || {}
  const locations: any[] = Array.isArray(data.locations) ? data.locations : []
  const contacts: any[] = Array.isArray(data.contacts) ? data.contacts : []
  const dateIso = new Date().toISOString().slice(0, 10)

  const euro = (amount: any) =>
    new Intl.NumberFormat(language === 'en' ? 'en-IE' : 'de-DE', { style: 'currency', currency: 'EUR' }).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: () => 8,
    paddingRight: () => 8,
    paddingTop: () => 5,
    paddingBottom: () => 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 tdPrice = (value: any) =>
    Number(value) > 0
      ? td(euro(value), { alignment: 'right', bold: true })
      : td(T.notSet, { alignment: 'right', color: BRAND.grayText })

  const kv = (label: string, value: any) => [
    td(label, { color: BRAND.grayText }),
    td(value || '—', { bold: true })
  ]

  // ---- Type / status chips
  const types: string[] = []
  if (p.isCustomer) types.push(T.customer)
  if (p.isVendor) types.push(T.vendor)
  if (p.isFulfillmentCustomer) types.push(T.fulfillmentCustomer)
  if (p.isProspect && !p.isCustomer) types.push(T.prospect)

  // ---- Master data grid (skip empty pairs where both sides are blank)
  const masterRows: any[][] = [
    [...kv(T.taxId, p.taxId), ...kv(T.hrgNumber, p.hrgNumber)],
    [...kv(T.email, p.email), ...kv(T.emailInvoice, p.emailInvoice)],
    [...kv(T.emailReturn, p.returnEmail), ...kv(T.url, p.url)],
    [...kv(T.partnerGroup, p.partnerGroup), ...kv(T.paymentTerm, p.paymentTerm)],
    [...kv(T.priceList, p.priceList), ...kv(T.salesRep, p.salesRep)],
    [...kv(T.language, p.language), ...kv(T.contractSigned, p.contractSigned ? formatDateLocal(p.contractSigned, language) : '')]
  ]

  // ---- Address rows
  const addressRows: any[][] = locations.map((loc: any) => {
    const lines = [loc.address1, loc.address2, [loc.postal, loc.city].filter(Boolean).join(' '), loc.country]
      .filter((l: any) => String(l || '').trim() !== '')
    const typeParts: string[] = []
    if (loc.isBillTo) typeParts.push(T.billTo)
    if (loc.isShipTo) typeParts.push(T.shipTo)
    return [
      td(loc.name || '—'),
      { stack: lines.length ? lines.map((l: string, i: number) => td(l, { margin: [0, i === 0 ? 0 : 1, 0, 0] })) : [td('—')] },
      td(loc.phone || '—'),
      td(typeParts.join(' + ') || '—', { alignment: 'center' })
    ]
  })

  // ---- Contact rows
  const contactRows: any[][] = contacts.map((u: any) => [
    td(u.name || '—', { bold: true }),
    td(u.title || '—'),
    td(u.phone || '—'),
    td(u.phone2 || '—'),
    td(u.email || '—')
  ])

  const emptyRow = (cols: number) => [[
    { text: T.noRecords, fontSize: 9, italics: true, color: BRAND.grayText, colSpan: cols, alignment: 'center' },
    ...Array(cols - 1).fill({})
  ]]

  const content: any[] = [
    // Partner name + meta card
    {
      columns: [
        {
          width: '*',
          stack: [
            { text: p.name || '', bold: true, fontSize: 15, color: BRAND.navy },
            ...(p.name2 ? [{ text: p.name2, fontSize: 10, color: BRAND.grayText, margin: [0, 2, 0, 0] }] : []),
            ...(types.length ? [{ text: types.join('  ·  '), fontSize: 9, bold: true, color: BRAND.orange, margin: [0, 6, 0, 0] }] : []),
            ...(p.description ? [{ text: p.description, fontSize: 8.5, color: BRAND.grayText, margin: [0, 6, 0, 0] }] : [])
          ]
        },
        {
          width: 210,
          table: {
            widths: [86, '*'],
            body: [
              kv(T.date, formatDateLocal(dateIso, language)),
              kv(T.partnerNo, p.value),
              kv(T.status, p.isActive ? T.active : T.inactive)
            ]
          },
          layout: {
            hLineWidth: () => 0,
            vLineWidth: () => 0,
            fillColor: () => BRAND.zebra,
            paddingLeft: () => 8,
            paddingRight: () => 8,
            paddingTop: () => 4,
            paddingBottom: () => 4
          }
        }
      ],
      columnGap: 24,
      margin: [0, 4, 0, 0]
    },

    // STAMMDATEN
    {
      unbreakable: true,
      stack: [
        sectionTitle(T.masterData),
        {
          table: { widths: [110, '*', 110, '*'], body: masterRows },
          layout: {
            hLineWidth: (i: number) => (i > 0 && i < masterRows.length ? 0.5 : 0),
            vLineWidth: () => 0,
            hLineColor: () => BRAND.grayLine,
            paddingLeft: () => 4,
            paddingRight: () => 8,
            paddingTop: () => 4,
            paddingBottom: () => 4
          }
        }
      ]
    },

    // ADRESSEN
    {
      unbreakable: addressRows.length <= 6,
      stack: [
        sectionTitle(T.addresses),
        {
          table: {
            headerRows: 1,
            widths: [110, '*', 100, 90],
            body: [
              [th(T.addressName), th(T.address), th(T.phone), th(T.addressType, 'center')],
              ...(addressRows.length ? addressRows : emptyRow(4))
            ]
          },
          layout: zebraLayout
        }
      ]
    },

    // ANSPRECHPARTNER
    {
      unbreakable: contactRows.length <= 8,
      stack: [
        sectionTitle(T.contacts),
        {
          table: {
            headerRows: 1,
            widths: [130, 80, 85, 85, '*'],
            body: [
              [th(T.contactName), th(T.position), th(T.phone), th(T.mobile), th(T.email)],
              ...(contactRows.length ? contactRows : emptyRow(5))
            ]
          },
          layout: zebraLayout
        }
      ]
    }
  ]

  // ---- Fulfillment pricing (only when it carries any signal)
  if (pr.show) {
    const pickfree = Number(pr.qtyPickfree) || 0
    const pickLabel = pickfree > 0 ? fmt(T.pickPriceFrom, { n: pickfree + 1 }) : T.pickPrice

    const fulfillmentRows: any[][] = [
      [td(T.orderBaseprice), td(T.piece, { alignment: 'center' }), tdPrice(pr.orderBaseprice)]
    ]
    if (Number(pr.orderBaseprice2) > 0) fulfillmentRows.push([td(fmt(T.orderBasepriceTier, { n: 2 })), td(T.piece, { alignment: 'center' }), tdPrice(pr.orderBaseprice2)])
    if (Number(pr.orderBaseprice3) > 0) fulfillmentRows.push([td(fmt(T.orderBasepriceTier, { n: 3 })), td(T.piece, { alignment: 'center' }), tdPrice(pr.orderBaseprice3)])
    fulfillmentRows.push(
      [td(pickLabel), td(T.piece, { alignment: 'center' }), tdPrice(pr.orderPickprice)],
      [td(T.returnBase), td(T.piece, { alignment: 'center' }), tdPrice(pr.returnBaseprice)],
      [td(T.returnPerItem), td(T.piece, { alignment: 'center' }), tdPrice(pr.returnPickprice)],
      [td(T.hourlyRate), td(T.hour, { alignment: 'center' }), tdPrice(pr.hourlyRate)]
    )

    const qtyCell = (qty: any) =>
      Number(qty) > 0 ? td(String(Number(qty)), { alignment: 'center', bold: true }) : td(T.notSet, { alignment: 'center', color: BRAND.grayText })
    const storageRows: any[][] = [
      [td(T.shelfSmall), qtyCell(pr.shelfSmallQty), tdPrice(pr.shelfSmallPrice)],
      [td(T.shelfLarge), qtyCell(pr.shelfLargeQty), tdPrice(pr.shelfLargePrice)],
      [td(T.palletSpace), qtyCell(pr.palletQty), tdPrice(pr.palletPrice)]
    ]
    if (Number(pr.volumeM3Price) > 0) {
      storageRows.push([td(T.volumeStorage), td(T.perM3, { alignment: 'center' }), tdPrice(pr.volumeM3Price)])
    }

    const feeRows: any[][] = [
      [td(T.serviceFee), td(T.perMonth, { alignment: 'center' }), tdPrice(pr.monthlyFee)]
    ]
    if (Number(pr.kleinPaketPriceLimit) > 0) feeRows.push([td(T.kpPriceLimit), td('', { alignment: 'center' }), tdPrice(pr.kleinPaketPriceLimit)])
    if (Number(pr.kpExtraWeight) > 0) feeRows.push([td(T.kpExtraWeight), td('', { alignment: 'center' }), td(`${pr.kpExtraWeight} kg`, { alignment: 'right', bold: true })])

    const packagingRows: any[][] = [
      [td('KP'), tdPrice(pr.cartons?.kp)],
      [td('S'), tdPrice(pr.cartons?.s)],
      [td('M'), tdPrice(pr.cartons?.m)],
      [td('L'), tdPrice(pr.cartons?.l)],
      [td('XL'), tdPrice(pr.cartons?.xl)]
    ]

    content.push(
      {
        unbreakable: true,
        stack: [
          sectionTitle(T.pricingTitle),
          {
            table: { headerRows: 1, widths: ['*', 70, 110], body: [[th(T.service), th(T.dimension, 'center'), th(T.price, 'right')], ...fulfillmentRows] },
            layout: zebraLayout
          }
        ]
      },
      {
        unbreakable: true,
        stack: [
          sectionTitle(T.storageTitle),
          {
            table: { headerRows: 1, widths: ['*', 80, 110], body: [[th(T.storageType), th(T.rentedQty, 'center'), th(T.monthlyCost, 'right')], ...storageRows] },
            layout: zebraLayout
          }
        ]
      },
      {
        unbreakable: true,
        stack: [
          sectionTitle(T.feesTitle),
          {
            table: { headerRows: 1, widths: ['*', 80, 110], body: [[th(T.service), th('', 'center'), th(T.price, 'right')], ...feeRows] },
            layout: zebraLayout
          }
        ]
      },
      {
        unbreakable: true,
        stack: [
          sectionTitle(T.packagingTitle),
          {
            table: { headerRows: 1, widths: ['*', 110], body: [[th(T.cartonSize), th(T.cartonPrice, 'right')], ...packagingRows] },
            layout: zebraLayout
          }
        ]
      }
    )
  }

  return {
    pageSize: 'A4',
    pageMargins: [40, 106, 40, 86],
    info: {
      title: `${T.docTitle} – ${p.name || ''}`,
      author: 'LogYou GmbH',
      subject: T.docTitle
    },
    header: buildBrandHeader(T.docTitle, `${p.name || ''}  ·  ${T.dateWord} ${formatDateLocal(dateIso, language)}`, logos.dark),
    footer: buildBrandFooter(T.page, T.of),
    content,
    styles: {
      tableHeader: { fontSize: 8.5, bold: true, color: BRAND.white }
    },
    defaultStyle: {
      font: 'Roboto',
      fontSize: 9.5,
      color: BRAND.text,
      lineHeight: 1.25
    }
  }
}

/** Build the final PDF buffer + authoritative filename. */
export const generatePartnerReportPdf = async (data: any): Promise<{ buffer: Buffer; filename: string }> => {
  // Import pdfmake with virtual file system for server-side use
  // (defensive vfs extraction — the export shape varies by pdfmake
  // version/bundler, do not simplify; same block as quotePdf/contractPdf).
  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 = buildPartnerReportDocDefinition(data, logos)
  const filename = sanitizeReportFilename(data?.partner?.name)

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