/**
 * Marketing flyer "LogYou × LogShip" — 16:9 landscape PDF (720×405 pt, the
 * format of the Hive reference deck) built with pdfmake from FLYER_TEXTS and the
 * assets under server/assets/offers/flyer/ (photos + app screenshots rendered
 * from /flyer-demo/* with dummy data + integration logos).
 *
 * Opt-in attachment (default OFF) for quote and contract sends — see
 * contractPackage.ts ('flyer' key) and quote/send.post.ts. Cached per language.
 */
import { BRAND } from './quotePdf'
import { renderPdfmake } from './agbPdf'
import { FLYER_TEXTS } from './flyerTexts'

const W = 720
const H = 405
const NAVY = BRAND.navy || '#1c324b'
const ORANGE = BRAND.orange || '#f15924'
const LIGHT = '#f3f5f8'
const TEXT = '#1f2a37'
const MUTED = '#6b7a8c'
const GREEN = '#1f9d55'
const LINE = '#e3e7ec'

// ---------- assets ----------
const assetCache: Record<string, string | null> = {}
const loadAsset = async (file: string): Promise<string | null> => {
  if (file in assetCache) return assetCache[file]
  try {
    const storage = useStorage('assets:server')
    const raw: any = await storage.getItemRaw(`offers/flyer/${file}`)
    if (!raw) { assetCache[file] = null; return null }
    const buf = Buffer.isBuffer(raw) ? raw : Buffer.from(raw)
    if (file.endsWith('.svg')) { assetCache[file] = buf.toString('utf8'); return assetCache[file] }
    const mime = file.endsWith('.png') ? 'image/png' : 'image/jpeg'
    assetCache[file] = `data:${mime};base64,${buf.toString('base64')}`
  } catch {
    assetCache[file] = null
  }
  return assetCache[file]
}

const LOGO_FILES: Record<string, string> = {
  shopify: 'logos/shopify.png', amazon: 'logos/amazon_icon.png', ebay: 'logos/ebay.svg', shopware: 'logos/shopware.png',
  jtl: 'logos/jtl.png', plentyone: 'logos/plentyone_logo.png', xentral: 'logos/xentral_logo.png', temu: 'logos/temu.png',
  dhl: 'logos/dhl_logo_small.png', dhlexpress: 'logos/dhlexpress.png', dpd: 'logos/dpd_logo_small.png', gls: 'logos/gls_logo_small.svg', ups: 'logos/one_logo_small.png'
}
const LOGO_LABELS: Record<string, string> = {
  shopify: 'Shopify', amazon: 'Amazon', ebay: 'eBay', shopware: 'Shopware', jtl: 'JTL', plentyone: 'PlentyOne', xentral: 'Xentral', temu: 'Temu',
  dhl: 'DHL', dhlexpress: 'DHL Express', dpd: 'DPD', gls: 'GLS', ups: 'UPS'
}

// ---------- layout helpers ----------
const abs = (x: number, y: number, node: any) => ({ ...node, absolutePosition: { x, y } })
// pdfkit has no rgba() colours — translucency goes through fillOpacity.
const rect = (x: number, y: number, w: number, h: number, color: string, r = 0, opacity = 1) =>
  abs(0, 0, { canvas: [{ type: 'rect', x, y, w, h, r, color, ...(opacity < 1 ? { fillOpacity: opacity } : {}) }] })
const line = (x1: number, y1: number, x2: number, y2: number, color = LINE, lw = 0.75) =>
  abs(0, 0, { canvas: [{ type: 'line', x1, y1, x2, y2, lineWidth: lw, lineColor: color }] })
const circle = (x: number, y: number, r: number, color: string) =>
  abs(0, 0, { canvas: [{ type: 'ellipse', x, y, r1: r, r2: r, color }] })
// A bare absolutely-positioned text wraps against the page edge, so the width
// is enforced through a single-column container.
const txt = (x: number, y: number, w: number, text: any, opts: any = {}) =>
  abs(x, y, { columns: [{ width: w, text, ...opts }] })
const img = (data: string | null, x: number, y: number, w?: number, h?: number, fit?: [number, number]) =>
  data ? abs(x, y, fit ? { image: data, fit } : { image: data, ...(w ? { width: w } : {}), ...(h ? { height: h } : {}) }) : { text: '' }
const svg = (data: string | null, x: number, y: number, w: number, h: number) =>
  data ? abs(x, y, { svg: data, fit: [w, h] }) : { text: '' }

/** pdfmake nodes with absolutePosition never advance the flow, so every page is
 *  explicitly opened with a break marker. */
const pageBreak = () => ({ text: '', pageBreak: 'before' as const })

export const buildFlyerDocDefinition = async (language: string) => {
  const lang = language === 'en' ? 'en' : 'de'
  const T = FLYER_TEXTS[lang]
  const A = async (f: string) => loadAsset(f)
  const logoLogyou = await A('logyou-logo.png')
  const logoLogyouDark = await A('logyou-logo-dark.png')
  const logoLogship = await A('logship-logo-dark.png')
  const logoLogshipLight = await A('logship-logo-light.png')
  const markLogship = await A('logship-mark.png')

  let pageNo = 0
  const pages: any[][] = []

  // Footer strip: section tag left, LogYou mark + page right
  const footer = (tag: string, dark = false) => [
    txt(28, H - 22, 300, tag, { fontSize: 7, bold: true, characterSpacing: 0.8, color: dark ? '#9fb0c2' : MUTED }),
    txt(W - 120, H - 22, 92, `${T.footer.page} ${pageNo}`, { fontSize: 7, color: dark ? '#9fb0c2' : MUTED, alignment: 'right' }),
    ...(logoLogyouDark && logoLogyou ? [img(dark ? logoLogyouDark : logoLogyou, W - 26 - 44, H - 26, 44)] : [])
  ]
  const bullet = (x: number, y: number, w: number, b: { h: string; t: string }, dark = false) => [
    circle(x + 7, y + 7, 7, ORANGE),
    txt(x + 4.2, y + 2.6, 8, '✓', { fontSize: 7.5, bold: true, color: '#fff' }),
    txt(x + 22, y, w - 22, [{ text: b.h + ' ', bold: true, color: dark ? '#fff' : NAVY }, { text: b.t, color: dark ? '#dbe3ec' : TEXT }], { fontSize: 9, lineHeight: 1.3 })
  ]
  const headline = (x: number, y: number, w: number, title: string, sub: string, dark = false) => [
    txt(x, y, w, title, { fontSize: 21, bold: true, color: dark ? '#fff' : NAVY, lineHeight: 1.12 }),
    txt(x, y + 62, w, sub, { fontSize: 9.5, color: dark ? '#c9d3df' : MUTED, lineHeight: 1.35 })
  ]
  /** Standard feature slide: text left, image right (portrait crop), bullets. */
  const featureSlide = (S: any, image: string | null, extra: any[] = [], opts: { screenshot?: boolean; phone?: string | null } = {}) => {
    pageNo += 1
    const nodes: any[] = [rect(0, 0, W, H, '#fff')]
    if (opts.screenshot && image) {
      // screenshot in a navy "device" frame on the right
      const iw = 306, ih = Math.round(iw * 652 / 1207)
      nodes.push(rect(384, 70, iw + 12, ih + 12, NAVY, 8))
      nodes.push(img(image, 390, 76, iw))
      nodes.push(rect(384, 70 + ih + 20, iw + 12, 3, ORANGE))
    } else if (image) {
      nodes.push(img(image, 400, 0, 320, H))
    }
    if (opts.phone) {
      nodes.push(rect(556, 60, 132, 258, '#111', 16))
      nodes.push(img(opts.phone, 561, 65, 122))
    }
    nodes.push(...headline(30, 42, 340, S.title, S.sub))
    let y = 148
    for (const b of S.bullets) { nodes.push(...bullet(30, y, 340, b)); y += 62 }
    nodes.push(...extra)
    nodes.push(...footer(S.tag))
    pages.push(nodes)
  }

  // ---------- 1 · Cover ----------
  pageNo += 1
  const dash = await A('screen-dashboard.png')
  pages.push([
    rect(0, 0, W, H, NAVY),
    rect(0, H - 6, W, 6, ORANGE),
    img(logoLogyouDark, 30, 26, 96),
    txt(30, 76, 330, T.cover.kicker, { fontSize: 8, color: '#9fb0c2', characterSpacing: 0.5 }),
    txt(30, 96, 330, T.cover.title, { fontSize: 30, bold: true, color: '#fff', lineHeight: 1.08 }),
    txt(30, 222, 320, T.cover.sub, { fontSize: 9.5, color: '#dbe3ec', lineHeight: 1.4 }),
    line(30, 306, 330, 306, '#4a6280'),
    txt(30, 318, 330, T.cover.trust, { fontSize: 11, bold: true, color: ORANGE }),
    txt(30, 338, 330, T.cover.channels, { fontSize: 7.5, color: '#9fb0c2', lineHeight: 1.3 }),
    // laptop-ish frame with the dashboard
    rect(376, 58, 334, 226, '#0e1a29', 10),
    rect(382, 64, 322, 214, '#fff', 4),
    img(dash, 383, 65, 320),
    rect(356, 284, 374, 12, '#243b55', 5),
    rect(516, 290, 54, 4, '#0e1a29', 2),
    img(logoLogshipLight, 590, 336, 110),
    txt(W - 120, H - 24, 92, 'logyou.de', { fontSize: 7, color: '#9fb0c2', alignment: 'right' })
  ])

  // ---------- 2 · Why ----------
  pageNo += 1
  {
    const nodes: any[] = [rect(0, 0, W, H, '#fff'), ...headline(30, 40, 560, T.why.title, T.why.sub)]
    const cardW = 206
    T.why.items.forEach((it: any, i: number) => {
      const x = 30 + i * (cardW + 21)
      nodes.push(rect(x, 150, cardW, 190, LIGHT, 10))
      nodes.push(rect(x, 150, cardW, 5, i === 1 ? NAVY : ORANGE, 2))
      nodes.push(circle(x + 30, 194, 17, NAVY))
      nodes.push(txt(x + 22, 185, 16, String(i + 1), { fontSize: 13, bold: true, color: '#fff', alignment: 'center' }))
      nodes.push(txt(x + 18, 226, cardW - 36, it.h, { fontSize: 12, bold: true, color: NAVY, lineHeight: 1.2 }))
      nodes.push(txt(x + 18, 266, cardW - 36, it.t, { fontSize: 8.8, color: TEXT, lineHeight: 1.35 }))
    })
    nodes.push(...footer('WARUM LOGYOU'))
    pages.push(nodes)
  }

  // ---------- 3 · Stats ----------
  pageNo += 1
  {
    const photo = await A('warehouse_scanning_p.jpg')
    const nodes: any[] = [rect(0, 0, W, H, '#fff'), img(photo, 0, 0, 300, H), rect(0, 0, 300, 30, NAVY, 0, 0.85),
      txt(14, 10, 272, T.combine.photoCaption, { fontSize: 7.5, color: '#fff' }),
      ...headline(330, 40, 360, T.combine.title, T.combine.sub)]
    T.combine.stats.forEach((s: any, i: number) => {
      const x = 330 + (i % 2) * 185
      const y = 168 + Math.floor(i / 2) * 96
      nodes.push(rect(x, y, 172, 82, LIGHT, 10))
      nodes.push(rect(x, y, 4, 82, i % 3 === 0 ? ORANGE : i === 1 ? NAVY : GREEN, 2))
      nodes.push(txt(x + 16, y + 12, 150, s.v, { fontSize: 22, bold: true, color: i % 3 === 0 ? ORANGE : i === 1 ? NAVY : GREEN }))
      nodes.push(txt(x + 16, y + 44, 150, s.l, { fontSize: 9.5, bold: true, color: NAVY }))
      nodes.push(txt(x + 16, y + 58, 150, s.s, { fontSize: 7.5, color: MUTED }))
    })
    nodes.push(...footer('LOGYOU × LOGSHIP'))
    pages.push(nodes)
  }

  // ---------- 4 · Services overview ----------
  pageNo += 1
  {
    const nodes: any[] = [rect(0, 0, W, H, LIGHT), txt(30, 40, 660, T.services.title, { fontSize: 21, bold: true, color: NAVY })]
    const colW = 124
    const photos = ['forklift_aisle_t.jpg', 'warehouse_shelves_t.jpg', 'barcode_scanner_t.jpg', 'delivery_truck_t.jpg', 'cardboard_boxes_t.jpg']
    for (let i = 0; i < T.services.items.length; i++) {
      const it = T.services.items[i]
      const x = 30 + i * (colW + 10)
      const p = await A(photos[i])
      nodes.push(rect(x, 96, colW, 280, '#fff', 10))
      nodes.push(img(p, x, 96, colW, 96))
      nodes.push(rect(x, 96, colW, 96, NAVY, 0, 0.22))
      nodes.push(circle(x + 22, 206, 15, ORANGE))
      nodes.push(txt(x + 14, 199, 16, String(i + 1), { fontSize: 11, bold: true, color: '#fff', alignment: 'center' }))
      nodes.push(txt(x + 12, 232, colW - 24, it.h, { fontSize: 11, bold: true, color: NAVY }))
      nodes.push(txt(x + 12, 252, colW - 24, it.t, { fontSize: 8, color: TEXT, lineHeight: 1.35 }))
    }
    nodes.push(...footer('LEISTUNGEN'))
    pages.push(nodes)
  }

  // ---------- 5-8 · Feature slides ----------
  featureSlide(T.inbound, await A('warehouse_shelves_p.jpg'))
  featureSlide(T.pick, await A('barcode_scanner_p.jpg'), [], { phone: await A('screen-mobile.png') })
  {
    // shipping + carrier logos row
    const extra: any[] = [txt(30, 334, 340, T.shipping.carriers, { fontSize: 7.5, bold: true, color: MUTED, characterSpacing: 0.5 })]
    const keys = ['dhl', 'dhlexpress', 'dpd', 'gls']
    let x = 30
    for (const k of keys) {
      const f = LOGO_FILES[k]
      const d = await A(f)
      extra.push(rect(x, 348, 60, 30, '#fff', 6))
      extra.push(f.endsWith('.svg') ? svg(d, x + 8, 353, 44, 20) : img(d, x + 8, 353, undefined, undefined, [44, 20]))
      x += 68
    }
    featureSlide(T.shipping, await A('delivery_truck_p.jpg'), extra)
  }
  featureSlide(T.returns, await A('screen-returns.png'), [], { screenshot: true })

  // ---------- 9 · LogShip Cloud (big screenshot) ----------
  pageNo += 1
  {
    const orders = await A('screen-orders.png')
    const stock = await A('screen-stock.png')
    const nodes: any[] = [rect(0, 0, W, H, NAVY), rect(0, H - 6, W, 6, ORANGE),
      img(logoLogshipLight, 30, 30, 92),
      ...headline(30, 60, 300, T.cloud.title, T.cloud.sub, true)]
    let y = 176
    for (const b of T.cloud.bullets) { nodes.push(...bullet(30, y, 300, b, true)); y += 60 }
    const h1 = Math.round(330 * 652 / 1207), h2 = Math.round(250 * 652 / 1207)
    nodes.push(rect(356, 40, 340, h1 + 10, '#0e1a29', 8))
    nodes.push(img(orders, 361, 45, 330))
    nodes.push(rect(436, 40 + h1 + 24, 260, h2 + 10, '#0e1a29', 8))
    nodes.push(img(stock, 441, 45 + h1 + 24, 250))
    nodes.push(...footer(T.cloud.tag, true))
    pages.push(nodes)
  }

  // ---------- 10 · Customer experience (tracking) ----------
  featureSlide(T.experience, await A('screen-tracking.png'), [], { screenshot: true })

  // ---------- 11 · VideoShip ----------
  featureSlide(T.videoship, await A('conveyor_packages_p.jpg'))

  // ---------- 12 · Integrations ----------
  pageNo += 1
  {
    const nodes: any[] = [rect(0, 0, W, H, '#fff'), ...headline(30, 40, 600, T.integrations.title, T.integrations.sub)]
    let y = 150
    for (const g of T.integrations.groups) {
      nodes.push(txt(30, y, 300, g.h, { fontSize: 8, bold: true, color: MUTED, characterSpacing: 0.6 }))
      let x = 30
      for (const k of g.keys) {
        const f = LOGO_FILES[k]
        const d = f ? await A(f) : null
        nodes.push(rect(x, y + 14, 76, 56, LIGHT, 8))
        if (d) nodes.push(f.endsWith('.svg') ? svg(d, x + 12, y + 22, 52, 24) : img(d, x + 12, y + 22, undefined, undefined, [52, 24]))
        nodes.push(txt(x, y + 52, 76, LOGO_LABELS[k] || k, { fontSize: 7, color: MUTED, alignment: 'center' }))
        x += 82
      }
      y += 92
    }
    nodes.push(txt(30, y + 4, 600, T.integrations.more, { fontSize: 9, color: TEXT, italics: true }))
    nodes.push(...footer(T.integrations.tag))
    pages.push(nodes)
  }

  // ---------- 13 · Special services ----------
  pageNo += 1
  {
    const nodes: any[] = [rect(0, 0, W, H, LIGHT), ...headline(30, 40, 620, T.special.title, T.special.sub)]
    const cw = 210, ch = 86
    T.special.items.forEach((it: any, i: number) => {
      const x = 30 + (i % 3) * (cw + 15)
      const y = 146 + Math.floor(i / 3) * (ch + 12)
      nodes.push(rect(x, y, cw, ch, '#fff', 10))
      nodes.push(rect(x, y + 12, 4, ch - 24, ORANGE, 2))
      nodes.push(txt(x + 16, y + 12, cw - 28, it.h, { fontSize: 10.5, bold: true, color: NAVY }))
      nodes.push(txt(x + 16, y + 30, cw - 28, it.t, { fontSize: 8, color: TEXT, lineHeight: 1.35 }))
    })
    nodes.push(...footer(T.special.tag))
    pages.push(nodes)
  }

  // ---------- 14 · Pricing structure ----------
  pageNo += 1
  {
    const nodes: any[] = [rect(0, 0, W, H, '#fff'), ...headline(30, 40, 620, T.pricing.title, T.pricing.sub)]
    const cw = 210, ch = 66
    T.pricing.items.forEach((it: any, i: number) => {
      const x = 30 + (i % 3) * (cw + 15)
      const y = 138 + Math.floor(i / 3) * (ch + 10)
      nodes.push(rect(x, y, cw, ch, LIGHT, 8))
      nodes.push(circle(x + 18, y + 20, 9, i < 3 ? ORANGE : NAVY))
      nodes.push(txt(x + 13, y + 15, 10, String(i + 1), { fontSize: 8, bold: true, color: '#fff', alignment: 'center' }))
      nodes.push(txt(x + 36, y + 12, cw - 46, it.h, { fontSize: 10, bold: true, color: NAVY }))
      nodes.push(txt(x + 36, y + 30, cw - 46, it.t, { fontSize: 7.8, color: TEXT, lineHeight: 1.3 }))
    })
    nodes.push(rect(30, 296, 660, 56, NAVY, 8))
    nodes.push(txt(46, 308, 630, T.pricing.note, { fontSize: 8.5, color: '#dbe3ec', lineHeight: 1.35 }))
    nodes.push(...footer(T.pricing.tag))
    pages.push(nodes)
  }

  // ---------- 15 · Start / contact ----------
  pageNo += 1
  {
    const bg = await A('warehouse_scanning_w.jpg')
    const nodes: any[] = [rect(0, 0, W, H, NAVY), img(bg, 0, 0, W, H, [W, H]), rect(0, 0, W, H, NAVY, 0, 0.88), rect(0, H - 6, W, 6, ORANGE),
      txt(30, 36, 640, T.start.title, { fontSize: 21, bold: true, color: '#fff' })]
    T.start.steps.forEach((s: any, i: number) => {
      const x = 30 + i * 226
      nodes.push(rect(x, 84, 206, 150, '#ffffff', 10, 0.1))
      nodes.push(circle(x + 26, 110, 15, ORANGE))
      nodes.push(txt(x + 18, 102, 16, String(i + 1), { fontSize: 12, bold: true, color: '#fff', alignment: 'center' }))
      nodes.push(txt(x + 16, 134, 178, s.h, { fontSize: 11.5, bold: true, color: '#fff' }))
      nodes.push(txt(x + 16, 156, 178, s.t, { fontSize: 8.5, color: '#dbe3ec', lineHeight: 1.35 }))
    })
    nodes.push(txt(30, 252, 660, T.start.promise, { fontSize: 10, italics: true, color: '#fff', lineHeight: 1.35 }))
    nodes.push(rect(30, 290, 420, 78, '#fff', 10))
    nodes.push(txt(46, 300, 390, T.start.contact.h, { fontSize: 11, bold: true, color: NAVY }))
    nodes.push(txt(46, 318, 390, T.start.contact.lines.join('\n'), { fontSize: 8.5, color: TEXT, lineHeight: 1.4 }))
    nodes.push(img(logoLogyouDark, 480, 300, 100))
    nodes.push(img(logoLogshipLight, 480, 338, 100))
    nodes.push(...footer(T.start.tag, true))
    pages.push(nodes)
  }

  const content: any[] = []
  pages.forEach((nodes, i) => {
    if (i > 0) content.push(pageBreak())
    content.push(...nodes)
  })

  return {
    pageSize: { width: W, height: H },
    pageMargins: [0, 0, 0, 0],
    info: { title: T.docTitle, author: 'LogYou GmbH', subject: T.docTitle },
    content,
    defaultStyle: { font: 'Roboto', fontSize: 9, color: TEXT }
  }
}

const pdfCache: Record<string, { buffer: Buffer; at: number }> = {}

export const flyerFilename = (language: string) => (language === 'en' ? 'LogYou-LogShip_Overview.pdf' : 'LogYou-LogShip_Ueberblick.pdf')

export const generateFlyerPdf = async (language: string, force = false): Promise<{ buffer: Buffer; filename: string; language: string }> => {
  const lang = language === 'en' ? 'en' : 'de'
  const cached = pdfCache[lang]
  if (!force && cached && Date.now() - cached.at < 3600_000) return { buffer: cached.buffer, filename: flyerFilename(lang), language: lang }
  const def = await buildFlyerDocDefinition(lang)
  const buffer = await renderPdfmake(def)
  pdfCache[lang] = { buffer, at: Date.now() }
  return { buffer, filename: flyerFilename(lang), language: lang }
}
