// Generates the same "Picklist" PDF that /generate-shipments produces, but
// from an arbitrary set of m_inout document numbers (e.g. the currently-open
// "Zu kommissionieren" shipments on the dashboard).
//
// Mirrors the data fetch + aggregation + sort of pages/generate-shipments.vue; the
// pdfmake layout itself is the shared buildPicklistDocDefinition
// (~/utils/picklistPdf.ts), so both code paths produce identical output.

interface PicklistOptions {
  docNos: string[]
  sortBy?: 'locator' | 'value' | 'sku' | 'mpn' | 'upc' | 'name' | 'qty' | ''
  userName?: string
  title?: string
}

const loadPdfMake = async () => {
  const pdfMakeModule: any = await import('pdfmake/build/pdfmake.js')
  const pdfFontsModule: any = await import('pdfmake/build/vfs_fonts.js')
  const pdfMake = pdfMakeModule.default || pdfMakeModule

  let vfs: any = null
  if (pdfFontsModule.pdfMake?.vfs) vfs = pdfFontsModule.pdfMake.vfs
  else if (pdfFontsModule.default?.pdfMake?.vfs) vfs = pdfFontsModule.default.pdfMake.vfs
  else if (pdfFontsModule.default?.vfs) vfs = pdfFontsModule.default.vfs
  else if (pdfFontsModule.default) {
    const keys = Object.keys(pdfFontsModule.default)
    if (keys.some(k => k.endsWith('.ttf'))) vfs = pdfFontsModule.default
  }
  pdfMake.vfs = vfs
  return pdfMake
}

// Shared comparator: organization first, then the chosen field. Used both to sort
// the aggregated picklist rows AND to derive the shipment print order, so the
// shipments print in exactly the same order the picklist is sorted in.
const lineComparator = (sortBy: string) => (a: any, b: any) => {
  const orgCompare = (a.AD_Org_ID?.identifier || '').localeCompare(b.AD_Org_ID?.identifier || '')
  if (orgCompare !== 0) return orgCompare
  if (!sortBy) return 0
  switch (sortBy) {
    case 'value':
      return (a.M_Product_ID?.Value || '').localeCompare(b.M_Product_ID?.Value || '')
    case 'sku':
      return (a.M_Product_ID?.SKU || '').localeCompare(b.M_Product_ID?.SKU || '')
    case 'mpn':
      return (a.M_Product_ID?.mpn || '').localeCompare(b.M_Product_ID?.mpn || '')
    case 'upc':
      return (a.M_Product_ID?.UPC || '').localeCompare(b.M_Product_ID?.UPC || '')
    case 'name':
      return (a.M_Product_ID?.Name || '').localeCompare(b.M_Product_ID?.Name || '')
    case 'qty':
      return Number(b.QtyEntered) - Number(a.QtyEntered)
    case 'locator': {
      const xCompare = (a.M_Locator_ID?.X || '').toString().localeCompare((b.M_Locator_ID?.X || '').toString(), undefined, { numeric: true })
      if (xCompare !== 0) return xCompare
      const yCompare = (a.M_Locator_ID?.Y || '').toString().localeCompare((b.M_Locator_ID?.Y || '').toString(), undefined, { numeric: true })
      if (yCompare !== 0) return yCompare
      return (a.M_Locator_ID?.Z || '').toString().localeCompare((b.M_Locator_ID?.Z || '').toString(), undefined, { numeric: true })
    }
    default:
      return 0
  }
}

const sortPicklistData = (data: any[], sortBy: string) => [...data].sort(lineComparator(sortBy))

export const useGenerateOpenPicklistPdf = () => {
  const generate = async ({ docNos, sortBy = 'locator', userName = 'SUPERUSER', title = 'Picklist' }: PicklistOptions) => {
    if (!docNos?.length) return { ok: false, reason: 'no-docs' as const }

    const aggregated: any[] = []
    const relatedDocNos: string[] = []
    // Flat product lines tagged with their shipment + a docNo→shipment map, used to
    // derive the shipment print order (same comparator as the picklist). Does not
    // affect the picklist PDF itself.
    const orderLines: any[] = []
    const shipmentByDocNo = new Map<string, { id: any, documentNo: string }>()

    for (const docNo of docNos) {
      if (!docNo) continue
      let res: any
      try {
        res = await $fetch('/api/processes/inouts/' + docNo)
      } catch (e) {
        continue
      }
      if (!res?.records?.[0]) continue
      if (!relatedDocNos.includes(docNo)) relatedDocNos.push(docNo)

      const docRes = res.records[0]
      if (!shipmentByDocNo.has(docNo)) shipmentByDocNo.set(docNo, { id: docRes.id, documentNo: docNo })
      const productLines = (docRes.m_inoutline || []).filter((l: any) => l.M_Product_ID && l.M_Locator_ID && !l.C_Charge_ID)

      for (const drl of productLines) {
        orderLines.push({ ...drl, _docNo: docNo })
        const existingIdx = aggregated.findIndex(i =>
          i.AD_Org_ID?.id == drl.AD_Org_ID?.id &&
          i.M_Product_ID?.Value == drl.M_Product_ID?.Value &&
          i.M_Locator_ID?.X == drl.M_Locator_ID?.X &&
          i.M_Locator_ID?.Y == drl.M_Locator_ID?.Y &&
          i.M_Locator_ID?.Z == drl.M_Locator_ID?.Z
        )
        if (existingIdx >= 0) {
          aggregated[existingIdx].QtyEntered = Number(aggregated[existingIdx].QtyEntered) + Number(drl.QtyEntered)
        } else {
          aggregated.push({ ...drl })
        }
      }
    }

    if (!aggregated.length) return { ok: false, reason: 'no-lines' as const }

    const sorted = sortPicklistData(aggregated, sortBy)

    // Shipment print order — same comparator the picklist uses, first occurrence per
    // shipment, so the referenced shipments print in the picklist's order.
    const orderedShipments: { id: any, documentNo: string }[] = []
    const seenDoc = new Set<string>()
    for (const line of [...orderLines].sort(lineComparator(sortBy))) {
      if (seenDoc.has(line._docNo)) continue
      seenDoc.add(line._docNo)
      const sh = shipmentByDocNo.get(line._docNo)
      if (sh) orderedShipments.push(sh)
    }
    // Shipments without pickable product lines still belong in the batch — append them.
    for (const [doc, sh] of shipmentByDocNo) {
      if (!seenDoc.has(doc)) { seenDoc.add(doc); orderedShipments.push(sh) }
    }

    const today = new Date().toLocaleString('de-DE', {
      day: '2-digit', month: '2-digit', year: 'numeric',
      hour: '2-digit', minute: '2-digit', second: '2-digit'
    })

    const pdfMake = await loadPdfMake()

    // Same shared layout as the normal picklist (~/utils/picklistPdf.ts).
    const docDefinition: any = buildPicklistDocDefinition({ rows: sorted, relatedDocNos, today, title })

    const stamp = new Date().toISOString().replace(/[-:T]/g, '_').slice(0, 19)
    const fileName = `${stamp}-PICKLIST-${userName}.pdf`

    // Return the pdfmake document handle instead of triggering a download here, so
    // the caller can preview it, download it (pdf.download), or push it to a server
    // printer (pdf.getBase64 → /api/print/picklist). See PicklistGenerateModal.vue.
    const pdf = pdfMake.createPdf(docDefinition)

    return { ok: true, pdf, fileName, count: aggregated.length, docs: relatedDocNos.length, orderedShipments }
  }

  return { generate }
}
