import { date } from 'alga-js'
import refreshTokenHelper from "../../../../utils/refreshTokenHelper"
import getTokenHelper from "../../../../utils/getTokenHelper"
import errorHandlingHelper from "../../../../utils/errorHandlingHelper"
import fetchHelper from "../../../../utils/fetchHelper"
import laravelHelper from "../../../../utils/laravelHelper"
import strapiHelper from "../../../../utils/strapiHelper"
import { commissionTableFkPatch } from "../../../../utils/commissionTable"
import {
  dpdGetAuth,
  dpdStoreOrders,
  extractOrderSourceDpdCreds,
  xmlEscape,
  kgTo10GramUnits,
  toCm,
  buildVolumeString,
  iso2ToCustomsOrigin,
  type DpdCredentials
} from "../../../../utils/dpdHelper"

/**
 * DPD Multi-Parcel Label Creation
 *
 * DPD supports multiple <parcels> elements inside a single <order>, all
 * tracking numbers are returned in one response. This matches DHL's
 * single-API-call multi-parcel flow.
 *
 * DPD requires sequential shipment service calls, but we make a SINGLE call
 * containing multiple parcels — that fits inside one sequential slot.
 */

const EU_COUNTRIES = ['AT','BE','BG','HR','CY','CZ','DK','EE','FI','FR','DE','GR','HU','IE','IT','LV','LT','LU','MT','NL','PL','PT','RO','SK','SI','ES','SE']

// ----------------------------------------------------------------------------
// Strapi: save customs document to order attachments (mirrors DHL multi flow)
// ----------------------------------------------------------------------------
const saveCustomsDocToOrder = async (event: any, orderId: number, orderUid: string, customsDocBase64: string, shipmentNo: string) => {
  const config = useRuntimeConfig()
  try {
    let strapiAttachmentId: number | null = null
    const existingResponse: any = await strapiHelper(event, `ad-attachments?filters[AD_Table_ID][$eq]=259&filters[Record_ID][$eq]=${orderId}`, 'GET', null)
    if(existingResponse?.data?.[0]?.id) {
      strapiAttachmentId = existingResponse.data[0].id
    } else {
      const newAttachmentResp: any = await strapiHelper(event, `ad-attachments`, 'POST', {
        data: { AD_Table_ID: 259, Record_ID: orderId, Record_UU: orderUid }
      })
      if(newAttachmentResp?.data?.id) strapiAttachmentId = newAttachmentResp.data.id
    }
    if(strapiAttachmentId) {
      const timestamp = date.now().replace(/[-:]/g, '_').replace(' ', '-')
      const fileName = `CN23-DPD-${shipmentNo}-${timestamp}.pdf`
      const pdfBuffer = Buffer.from(customsDocBase64, 'base64')
      const FormData = (await import('form-data')).default
      const formData = new FormData()
      formData.append('field', 'attachment')
      formData.append('ref', 'api::ad-attachment.ad-attachment')
      formData.append('refId', String(strapiAttachmentId))
      formData.append('files', pdfBuffer, { filename: fileName, contentType: 'application/pdf' })
      formData.append('fileInfo', JSON.stringify({
        caption: `CN23 Customs Document - DPD Multi-Parcel Shipment ${shipmentNo}`,
        alternativeText: `CN23-DPD-${shipmentNo}`,
        name: fileName
      }))
      const uploadResponse = await $fetch(`${config.api.strapi}/upload`, {
        method: 'POST',
        headers: { Authorization: `Bearer ${config.api.strapitoken}`, ...formData.getHeaders() },
        body: formData
      })
      return { success: true, strapiAttachmentId, uploadResponse }
    }
    return { success: false, error: 'Could not get or create attachment record' }
  } catch(error: any) {
    console.error('[CN23 DPD Multi] Error saving customs document to Strapi:', error)
    return { success: false, error: error.message || 'Unknown error' }
  }
}

// ----------------------------------------------------------------------------
// Build the multi-parcel <order> XML
// ----------------------------------------------------------------------------
interface BuildMultiOrderArgs {
  refNo: string
  depot: string
  customerNumber: string
  sender: {
    name1: string; name2?: string; street: string; houseNo: string;
    country: string; zipCode: string; city: string; email?: string; phone?: string;
  }
  recipient: {
    name1: string; name2?: string; street: string; houseNo: string;
    country: string; zipCode: string; city: string; state?: string;
    email?: string; phone?: string;
  }
  parcels: Array<{
    weightKg: number
    dims?: { length: number; width: number; height: number }
    customsValueTotal?: number  // per-parcel customs total
    items?: Array<{ description: string; quantity: number; value: number; weightKg: number; hsCode?: string; countryOfOrigin?: string }>
  }>
  predictEmail?: string
  customsCurrency?: string
  invoiceNo?: string
  isInternational: boolean
  incoterm: 'DAP' | 'DDP' | 'EXW'
  reasonForExport?: '01' | '02' | '03'
  shipperEori?: string
}

function buildMultiOrderXml(a: BuildMultiOrderArgs): string {
  const parts: string[] = []
  parts.push(`   <generalShipmentData>`)
  parts.push(`    <mpsCustomerReferenceNumber1>${xmlEscape(a.refNo.substring(0, 35))}</mpsCustomerReferenceNumber1>`)
  parts.push(`    <sendingDepot>${xmlEscape(a.depot)}</sendingDepot>`)
  parts.push(`    <product>CL</product>`)
  parts.push(`    <sender>`)
  parts.push(`     <name1>${xmlEscape(a.sender.name1.substring(0, 35))}</name1>`)
  if (a.sender.name2) parts.push(`     <name2>${xmlEscape(a.sender.name2.substring(0, 35))}</name2>`)
  parts.push(`     <street>${xmlEscape(a.sender.street.substring(0, 35))}</street>`)
  parts.push(`     <houseNo>${xmlEscape(a.sender.houseNo.substring(0, 8))}</houseNo>`)
  parts.push(`     <country>${xmlEscape(a.sender.country.substring(0, 2).toUpperCase())}</country>`)
  parts.push(`     <zipCode>${xmlEscape(a.sender.zipCode.substring(0, 9))}</zipCode>`)
  parts.push(`     <city>${xmlEscape(a.sender.city.substring(0, 35))}</city>`)
  parts.push(`     <customerNumber>${xmlEscape(a.customerNumber.substring(0, 17))}</customerNumber>`)
  // DPD XSD order: customerNumber, contact, phone, mobile, fax, email, ...
  if (a.sender.phone) parts.push(`     <phone>${xmlEscape(a.sender.phone.substring(0, 30))}</phone>`)
  if (a.sender.email) parts.push(`     <email>${xmlEscape(a.sender.email)}</email>`)
  parts.push(`    </sender>`)
  parts.push(`    <recipient>`)
  parts.push(`     <name1>${xmlEscape(a.recipient.name1.substring(0, 35))}</name1>`)
  if (a.recipient.name2) parts.push(`     <name2>${xmlEscape(a.recipient.name2.substring(0, 35))}</name2>`)
  parts.push(`     <street>${xmlEscape(a.recipient.street.substring(0, 35))}</street>`)
  if (a.recipient.houseNo) parts.push(`     <houseNo>${xmlEscape(a.recipient.houseNo.substring(0, 8))}</houseNo>`)
  if (a.recipient.state) parts.push(`     <state>${xmlEscape(a.recipient.state.substring(0, 2).toUpperCase())}</state>`)
  parts.push(`     <country>${xmlEscape(a.recipient.country.substring(0, 2).toUpperCase())}</country>`)
  parts.push(`     <zipCode>${xmlEscape(a.recipient.zipCode.substring(0, 9))}</zipCode>`)
  parts.push(`     <city>${xmlEscape(a.recipient.city.substring(0, 35))}</city>`)
  // Phone must precede email per the DPD XSD
  if (a.recipient.phone) parts.push(`     <phone>${xmlEscape(a.recipient.phone.substring(0, 30))}</phone>`)
  if (a.recipient.email) parts.push(`     <email>${xmlEscape(a.recipient.email)}</email>`)
  parts.push(`    </recipient>`)
  // softwareVersion is V4_5-only; omitted for the V4_4 production endpoint.
  parts.push(`   </generalShipmentData>`)

  // Each parcel as its own <parcels> element
  for (const p of a.parcels) {
    parts.push(`   <parcels>`)
    parts.push(`    <weight>${kgTo10GramUnits(p.weightKg + 0.25)}</weight>`) // +0.25kg packaging
    if (p.dims && p.dims.length && p.dims.width && p.dims.height) {
      parts.push(`    <volume>${buildVolumeString(p.dims.length, p.dims.width, p.dims.height)}</volume>`)
    }
    parts.push(`   </parcels>`)
  }

  parts.push(`   <productAndServiceData>`)
  parts.push(`    <orderType>consignment</orderType>`)
  if (a.predictEmail) {
    parts.push(`    <predict>`)
    parts.push(`     <channel>1</channel>`)
    parts.push(`     <value>${xmlEscape(a.predictEmail)}</value>`)
    parts.push(`     <language>DE</language>`)
    parts.push(`    </predict>`)
  }
  if (a.isInternational) {
    // Aggregate all items from all parcels into a single customs declaration
    const allItems = a.parcels.flatMap(p => p.items || [])
    const totalValue = allItems.reduce((s, it) => s + (Number(it.value) * Number(it.quantity || 1)), 0)
    const customsAmount = Math.round(totalValue * 100)
    parts.push(`    <international>`)
    // parcelType must be first per V4_4 XSD (false = regular parcel)
    parts.push(`     <parcelType>false</parcelType>`)
    parts.push(`     <customsAmount>${customsAmount}</customsAmount>`)
    parts.push(`     <customsCurrency>${xmlEscape((a.customsCurrency || 'EUR').substring(0, 3).toUpperCase())}</customsCurrency>`)
    parts.push(`     <customsAmountExport>${customsAmount}</customsAmountExport>`)
    parts.push(`     <customsCurrencyExport>${xmlEscape((a.customsCurrency || 'EUR').substring(0, 3).toUpperCase())}</customsCurrencyExport>`)
    // V4_4-only: 02 = sender pays duties+taxes (DDP), 01 = recipient pays
    parts.push(`     <customsTerms>${a.incoterm === 'DDP' ? '02' : '01'}</customsTerms>`)
    parts.push(`     <customsPaper>A</customsPaper>`)
    parts.push(`     <customsEnclosure>true</customsEnclosure>`)
    if (a.invoiceNo) parts.push(`     <customsInvoice>${xmlEscape(a.invoiceNo.substring(0, 20))}</customsInvoice>`)
    parts.push(`     <numberOfArticle>${Math.min(99, allItems.length)}</numberOfArticle>`)
    // reasonForExport is V4_5-only; omitted for V4_4 production endpoint.
    // V4_4: EORI as sibling commercialInvoiceConsignorVatNumber (not inside the address)
    if (a.shipperEori) {
      parts.push(`     <commercialInvoiceConsignorVatNumber>${xmlEscape(String(a.shipperEori).substring(0, 20))}</commercialInvoiceConsignorVatNumber>`)
      parts.push(`     <commercialInvoiceConsignor>`)
      parts.push(`      <name1>${xmlEscape(a.sender.name1.substring(0, 35))}</name1>`)
      if (a.sender.name2) parts.push(`      <name2>${xmlEscape(a.sender.name2.substring(0, 35))}</name2>`)
      parts.push(`      <street>${xmlEscape(a.sender.street.substring(0, 35))}</street>`)
      parts.push(`      <houseNo>${xmlEscape(a.sender.houseNo.substring(0, 8))}</houseNo>`)
      parts.push(`      <country>${xmlEscape(a.sender.country.substring(0, 2).toUpperCase())}</country>`)
      parts.push(`      <zipCode>${xmlEscape(a.sender.zipCode.substring(0, 9))}</zipCode>`)
      parts.push(`      <city>${xmlEscape(a.sender.city.substring(0, 35))}</city>`)
      parts.push(`      <customerNumber>${xmlEscape(a.customerNumber.substring(0, 17))}</customerNumber>`)
      parts.push(`     </commercialInvoiceConsignor>`)
    }
    // incoterm + paymentTerm are V4_5-only; V4_4 uses <customsTerms> emitted above.
    for (let i = 0; i < allItems.length && i < 99; i++) {
      const it = allItems[i]
      parts.push(`     <additionalInvoiceLines>`)
      parts.push(`      <customsInvoicePosition>${i + 1}</customsInvoicePosition>`)
      parts.push(`      <quantityItems>${Math.max(1, Math.round(it.quantity))}</quantityItems>`)
      // V4_4 has no dedicated HS code field — embed it in the description text
      const desc = it.hsCode ? `${it.description} [HS: ${it.hsCode}]` : it.description
      parts.push(`      <customsContent>${xmlEscape(String(desc).substring(0, 200))}</customsContent>`)
      parts.push(`      <customsAmountLine>${Math.round(it.value * it.quantity * 100)}</customsAmountLine>`)
      if (it.countryOfOrigin) parts.push(`      <customsOrigin>${iso2ToCustomsOrigin(it.countryOfOrigin)}</customsOrigin>`)
      parts.push(`      <customsNetWeight>${kgTo10GramUnits(it.weightKg)}</customsNetWeight>`)
      parts.push(`      <customsGrossWeight>${kgTo10GramUnits(it.weightKg)}</customsGrossWeight>`)
      // unitPrice is V4_5-only; per-line total is already in customsAmountLine.
      parts.push(`     </additionalInvoiceLines>`)
    }
    parts.push(`    </international>`)
  }
  parts.push(`   </productAndServiceData>`)

  return `   <order>\n${parts.join('\n')}\n   </order>`
}

function buildStoreOrdersInner(orderXml: string): string {
  return `   <printOptions>
    <printOption>
     <outputFormat>PDF</outputFormat>
     <paperFormat>A6</paperFormat>
    </printOption>
    <splitByParcel>true</splitByParcel>
   </printOptions>
${orderXml}`
}

// ----------------------------------------------------------------------------
// M_Inout + marketplace ack (same pattern as DHL multi)
// ----------------------------------------------------------------------------
const handleInoutFunc = async (event: any, authToken: any = null, option: any) => {
  let data: any = {}
  const token = authToken ?? await getTokenHelper(event)
  const trackingNoArray = option.all_tracking_numbers.slice(1)
  const trackingPayload: any = {
    TrackingNo: option.tracking_number,
    DPD_Shipment_Code: option.shipment_code,
    DPD_Label_Base64: option.label_base64,
    IsCommissioned: true,
    shipping_date: date.now('', '', {timeZone: 'UTC'}).replace(' ', 'T')+'Z',
    shipping_service_name: option.shippingService,
    tableName: 'M_Inout',
    trackingnoarray: trackingNoArray.length > 0 ? JSON.stringify(trackingNoArray) : null
  }
  if(option.paket_type) trackingPayload['M_Paket_Type_ID'] = option.paket_type
  // Link the commissioning table (Tisch) so the correct camera's video can be
  // resolved later. No-op when the printer is unknown/unmapped.
  Object.assign(trackingPayload, await commissionTableFkPatch(event, option.shippingPrinter, token))

  const resp: any = await fetchHelper(event, 'models/m_inout/'+option.inout_id, 'PUT', token, trackingPayload)
  if(resp) {
    data['shipment'] = resp
    data['status'] = 200
    data['message'] = ''

    if(resp?.IsCommissionedConfirmed !== true) {
      const resp2: any = await fetchHelper(event, 'models/m_inout/'+option.inout_id+'?$expand=c_order_id,m_inoutline,c_bpartner_location_id,ad_org_id', 'GET', token, null)

      const formatOrderNumber = () => {
        const documentNo = resp2?.C_Order_ID?.DocumentNo ?? '0'
        const companyName = resp2?.AD_Org_ID?.companyname ?? ''
        const firstWord = companyName.trim().split(/\s+/)[0] || ''
        return firstWord ? `${documentNo}-${firstWord}` : documentNo
      }

      if(resp2?.C_Order_ID?.C_OrderSource_ID?.id) {
        const resp3: any = await fetchHelper(event, 'models/c_ordersource/'+resp2.C_Order_ID.C_OrderSource_ID.id, 'GET', token, null)

        const mailPayload = {
          email: option.customerEmail,
          isSentCustomTrackingMail: option.isSentCustomTrackingMail,
          orderNumber: formatOrderNumber(),
          name: resp2?.C_Order_ID?.C_BPartner?.identifier ?? 'Mr/Ms',
          company: 'LogYou GmbH',
          carrier: option.shippingService ?? 'DPD',
          lines: resp2?.m_inoutline?.filter((i: any) => i.M_Product_ID && !i.C_Charge_ID).map((i: any) => ({
            description: i.M_Product_ID.identifier,
            quantity: i.QtyEntered
          })) ?? [],
          address1: resp2?.C_Order_ID?.C_BPartner_Location_ID?.C_Location_ID?.Address1 ?? '',
          address2: resp2?.C_Order_ID?.C_BPartner_Location_ID?.C_Location_ID?.Address2 ?? '',
          city: resp2?.C_Order_ID?.C_BPartner_Location_ID?.C_Location_ID?.City ?? '',
          country: resp2?.C_Order_ID?.C_BPartner_Location_ID?.C_Location_ID?.C_Country_ID?.identifier ?? '',
          postal: resp2?.C_Order_ID?.C_BPartner_Location_ID?.C_Location_ID?.Postal ?? ''
        }

        const markConfirmed = async () => {
          await fetchHelper(event, 'models/m_inout/'+option.inout_id, 'PUT', token, {
            IsCommissionedConfirmed: true,
            ack_commissioned_laravel: true,
            tableName: 'M_Inout'
          })
        }

        if(resp2?.C_Order_ID?.shopware6_order_id && resp3?.marketplace_url) {
          try {
            const resp4: any = await laravelHelper(event, 'sales/orders/mark-shopware-order-delivery', 'POST', {
              marketplace_url: resp3.marketplace_url,
              marketplace_key: resp3.marketplace_key,
              marketplace_secret: resp3.marketplace_secret,
              id: resp2.C_Order_ID.shopware6_order_id,
              trackingCodes: [option.tracking_number],
              mail: mailPayload
            })
            if(resp4) await markConfirmed()
          } catch(err: any) { data['shopware'] = errorHandlingHelper(err?.data ?? err, err?.data ?? err) }
        }
        if(resp2?.C_Order_ID?.shopify_order_id && resp3?.marketplace_url) {
          try {
            const resp4: any = await laravelHelper(event, 'sales/orders/mark-shopify-order-delivery', 'POST', {
              orderSource: resp3,
              id: resp2.C_Order_ID.shopify_order_id,
              trackingCodes: { number: option.tracking_number, url: option.tracking_url, company: 'DPD' },
              mail: mailPayload
            })
            if(resp4) await markConfirmed()
          } catch(err: any) { data['shopify'] = errorHandlingHelper(err?.data ?? err, err?.data ?? err) }
        }
        if(resp2?.C_Order_ID?.amazon_order_id && resp3?.marketplace_url) {
          try {
            const resp4: any = await laravelHelper(event, 'sales/orders/mark-amazon-order-delivery', 'POST', {
              orderSource: resp3,
              id: resp2.C_Order_ID.amazon_order_id,
              details: { shippingDate: trackingPayload.shipping_date, carrierCode: 'DPD', shippingMethod: 'Paket', referenceId: resp2?.DocumentNo ?? option.inout_id },
              trackingCodes: { number: option.tracking_number, url: option.tracking_url },
              mail: mailPayload
            })
            if(resp4) await markConfirmed()
          } catch(err: any) { data['amazon'] = errorHandlingHelper(err?.data ?? err, err?.data ?? err) }
        }
        if(resp2?.C_Order_ID?.plentyone_order_id && resp3?.marketplace_url) {
          try {
            const plentyOneWeight = resp2?.m_inoutline?.reduce((acc: any, prev: any) => Number(acc['Weight'] ?? 0) + Number(prev['Weight'] ?? 0), 0)
            const additionalTrackingNumbers = option.all_tracking_numbers?.slice(1) ?? []
            const resp4: any = await laravelHelper(event, 'sales/orders/mark-plentyone-order-delivery', 'POST', {
              orderSource: resp3,
              id: resp2.C_Order_ID.plentyone_order_id,
              details: { shippingDate: trackingPayload.shipping_date, carrierCode: 'DPD', shippingMethod: 'Paket', referenceId: resp2?.DocumentNo ?? option.inout_id, weight: plentyOneWeight ?? 0 },
              trackingCodes: { number: option.tracking_number, url: option.tracking_url, trackingNoArray: additionalTrackingNumbers.length > 0 ? additionalTrackingNumbers : null },
              mail: mailPayload
            })
            if(resp4) await markConfirmed()
          } catch(err: any) { data['plentyone'] = errorHandlingHelper(err?.data ?? err, err?.data ?? err) }
        }
        if(resp2?.C_Order_ID?.ExternalOrderId && resp3?.Marketplace?.identifier === 'jtl-ffn' && resp3?.marketplace_url) {
          try {
            const resp4: any = await laravelHelper(event, 'sales/orders/mark-jtl-order-delivery', 'POST', {
              orderSource: resp3,
              id: resp2.C_Order_ID.ExternalOrderId,
              details: { shippingDate: trackingPayload.shipping_date, carrierCode: 'DPD', shippingMethod: 'Paket', referenceId: resp2?.DocumentNo ?? option.inout_id, weight: 0 },
              trackingCodes: { number: option.tracking_number, url: option.tracking_url },
              mail: mailPayload
            })
            if(resp4) await markConfirmed()
          } catch(err: any) { data['jtl'] = errorHandlingHelper(err?.data ?? err, err?.data ?? err) }
        }
        if(resp2?.C_Order_ID?.ebay_order_id) {
          try {
            const resp4: any = await laravelHelper(event, 'sales/orders/mark-ebay-order-delivery', 'POST', {
              orderSource: resp3,
              id: resp2.C_Order_ID.ebay_order_id,
              details: { shippingDate: trackingPayload.shipping_date, carrierCode: 'DPD', shippingMethod: 'Paket', referenceId: resp2?.DocumentNo ?? option.inout_id },
              trackingCodes: { number: option.tracking_number, url: option.tracking_url },
              mail: mailPayload
            })
            if(resp4) await markConfirmed()
          } catch(err: any) { data['ebay'] = errorHandlingHelper(err?.data ?? err, err?.data ?? err) }
        }
      }
    }
  }

  return data
}

// ----------------------------------------------------------------------------
// Main
// ----------------------------------------------------------------------------
const handleFunc = async (event: any) => {
  let data: any = {}
  const body = await readBody(event)

  if (!body.parcels || !Array.isArray(body.parcels) || body.parcels.length === 0) {
    return { status: 400, message: 'Multi-parcel mode requires parcels array with at least one parcel' }
  }

  let customCreds: Partial<DpdCredentials> | null = null
  let customerEmail = 'fulfillcustomer@logyou.de'
  let isSentCustomTrackingMail = false
  const tokenEmail = await getTokenHelper(event)

  const respInout: any = await fetchHelper(event, 'models/m_inout/'+body.inOutId+'?$expand=c_order_id,ad_org_id', 'GET', tokenEmail, null)

  if(respInout?.C_Order_ID?.C_OrderSource_ID?.id) {
    const respOrderSource: any = await fetchHelper(event, 'models/c_ordersource/'+respInout.C_Order_ID.C_OrderSource_ID.id, 'GET', tokenEmail, null)
    isSentCustomTrackingMail = respOrderSource?.isSentCustomTrackingMail ?? false
    if(body.email) {
      customerEmail = (respOrderSource?.isExcludetrackingmail ? 'fulfillcustomer@logyou.de' : body.email)
    }
    const extracted = extractOrderSourceDpdCreds(respOrderSource)
    if (extracted) {
      if (extracted.missing.length > 0) {
        console.warn('[DPD Multi] OrderSource missing fields:', extracted.missing, {
          id: respOrderSource?.id, Name: respOrderSource?.Name
        })
        return {
          status: 400,
          message: `OrderSource ${respOrderSource?.id} (${respOrderSource?.Name || '?'}) is missing required DPD field(s): ${extracted.missing.join(', ')}. Open Settings → Order Sources → ${respOrderSource?.Name || respOrderSource?.id} and fill them in.`
        }
      }
      customCreds = extracted.creds
    }
  }

  let customerPhone = body.telephone || '+49 987654321'

  const companyName = respInout?.AD_Org_ID?.companyname ?? ''
  const firstWord = companyName.trim().split(/\s+/)[0]?.replace(/[^a-zA-Z0-9]/g, '') || ''
  const baseOrderNumber = body.orderNumber ?? body.inOutUId.replaceAll('-', '')
  const formattedOrderNumber = firstWord ? `${baseOrderNumber}-${firstWord}` : baseOrderNumber

  let orgSenderEmail: string = ''
  const orgId = respInout?.AD_Org_ID?.id
  if (orgId) {
    try {
      const orgRes: any = await fetchHelper(event, `models/ad_org/${orgId}?$select=C_BPartner_ID`, 'GET', tokenEmail, null)
      const orgBpartnerId = orgRes?.C_BPartner_ID?.id
      if (orgBpartnerId) {
        const partnerRes: any = await fetchHelper(event, `models/c_bpartner/${orgBpartnerId}?$select=freight_service_sender_mail`, 'GET', tokenEmail, null)
        orgSenderEmail = String(partnerRes?.freight_service_sender_mail ?? '').trim()
      }
    } catch(err: any) {
      console.error(`[DPD Multi] Error fetching org sender email:`, err?.message || err)
    }
  }

  let auth, creds
  try {
    const r = await dpdGetAuth(event, customCreds)
    auth = r.auth
    creds = r.creds
  } catch(loginErr: any) {
    data['status'] = 500
    data['message'] = loginErr?.message || 'DPD authentication failed'
    return data
  }

  const country = String(body.country ?? '').toUpperCase().trim()
  const isInternational = !EU_COUNTRIES.includes(country)

  const orderXml = buildMultiOrderXml({
    refNo: formattedOrderNumber,
    depot: auth.depot,
    customerNumber: creds.customerNumber,
    sender: {
      name1: respInout?.AD_Org_ID?.companyname && respInout?.AD_Org_ID !== 1000000 ? respInout?.AD_Org_ID?.companyname : 'LogYou GmbH',
      name2: respInout?.AD_Org_ID?.companyname && respInout?.AD_Org_ID !== 1000000 ? 'c/o LogYou GmbH' : undefined,
      street: 'Mühlenweg',
      houseNo: '4',
      country: 'DE',
      zipCode: '35510',
      city: 'Butzbach',
      email: orgSenderEmail || 'info@logyou.de',
      phone: '+4960339160570'
    },
    recipient: {
      name1: String(body.name ?? '').trim(),
      name2: body.name2 ? String(body.name2).trim() : undefined,
      street: String(body.address ?? '').trim(),
      houseNo: String(body.houseNumber || '').trim(),
      country: country,
      zipCode: String(body.postalCode ?? '').trim(),
      city: String(body.city ?? '').trim(),
      state: body.countryState ? String(body.countryState).trim() : undefined,
      email: customerEmail,
      phone: customerPhone
    },
    parcels: body.parcels.map((p: any) => ({
      weightKg: Number(p.weight ?? 0),
      dims: (body.length && body.width && body.height) ? {
        length: toCm(body.length), width: toCm(body.width), height: toCm(body.height)
      } : undefined,
      items: (p.items || []).map((it: any) => ({
        description: it.description || '',
        quantity: Number(it.quantity || 1),
        value: Number(it.value || 0),
        weightKg: Number(it.weight || 0.1),
        // taricCode = M_Product.taricCode fallback for labels created without the
        // customs modal normalizing it into hsCode
        hsCode: it.hsCode || it.taricCode || undefined,
        countryOfOrigin: it.countryOfOrigin || undefined
      }))
    })),
    predictEmail: customerEmail && /@/.test(customerEmail) ? customerEmail : undefined,
    customsCurrency: body.totalOrderValueCurrency || 'EUR',
    invoiceNo: body.orderNumber ? String(body.orderNumber).substring(0, 20) : undefined,
    isInternational: isInternational && body.enableCN23 === true,
    incoterm: (body.customsIncoterm === 'DDP' || body.customsIncoterm === 'EXW' ? body.customsIncoterm : 'DAP') as 'DAP' | 'DDP' | 'EXW',
    reasonForExport: (['01', '02', '03'].includes(body.customsReasonForExport) ? body.customsReasonForExport : '01') as '01' | '02' | '03',
    shipperEori: body.shipperEori ? String(body.shipperEori).trim() : undefined
  })

  let dpdResult
  try {
    const { result } = await dpdStoreOrders(event, customCreds, buildStoreOrdersInner(orderXml))
    dpdResult = result
  } catch(dpdErr: any) {
    const detail = dpdErr?.dpdFault ? `${dpdErr.dpdFault.code}: ${dpdErr.dpdFault.message}` : (dpdErr?.message || 'DPD API Error')
    console.error('[DPD Multi] DPD API rejected shipment:', detail)
    data['status'] = 400
    data['message'] = detail
    data['dpd_errors'] = [detail]
    return data
  }

  if (dpdResult.faults && dpdResult.faults.length > 0) {
    const detail = dpdResult.faults.map(f => `${f.code}: ${f.message}`).join(' | ')
    data['status'] = 400
    data['message'] = detail
    data['dpd_errors'] = dpdResult.faults.map(f => `${f.code}: ${f.message}`)
    return data
  }

  const allTrackingNumbers = dpdResult.parcelLabelNumbers
  if (!allTrackingNumbers.length || !dpdResult.labelPdfBase64) {
    data['status'] = 500
    data['message'] = 'DPD response missing tracking numbers or label'
    return data
  }

  // Build per-parcel labels for the frontend's print loop.
  // parcelLabels comes from the helper: when splitByParcel=true (our case),
  // each <parcelInformation> in DPD's response has its own <output><content>.
  // We pair them with tracking numbers and emit the same shape DHL multi uses
  // (label.b64 per parcel), so the existing commission.vue printing loop works
  // identically for DPD without any frontend changes.
  const perParcelLabels = dpdResult.parcelLabels && dpdResult.parcelLabels.length > 0
    ? dpdResult.parcelLabels
    : allTrackingNumbers.map((tn, i) => ({ trackingNumber: tn, pdfBase64: i === 0 ? dpdResult.labelPdfBase64 : '' }))

  data['dpd_parcels'] = perParcelLabels.map(p => ({
    shipmentNo: p.trackingNumber,
    routingCode: '',
    label: { b64: p.pdfBase64 }
  }))
  // Also emit dhl_parcels-shaped key so commission.vue's normalization that
  // copies dpd_parcels → dhl_parcels keeps the existing print loop happy.
  data['tracking_numbers'] = allTrackingNumbers
  data['parcel_count'] = allTrackingNumbers.length
  data['mpsId'] = dpdResult.mpsId

  // Persist
  try {
    const res2 = await handleInoutFunc(event, null, {
      inout_id: body.inOutId,
      tracking_number: allTrackingNumbers[0],
      tracking_url: '',
      shipment_code: dpdResult.mpsId || allTrackingNumbers.join(','),
      label_base64: dpdResult.labelPdfBase64,
      paket_type: body.paketType,
      shippingService: body.shippingService || 'DPD',
      shippingPrinter: body.shippingPrinter,
      customerEmail: customerEmail,
      isSentCustomTrackingMail: isSentCustomTrackingMail,
      all_tracking_numbers: allTrackingNumbers
    })
    data = { ...data, ...res2 }
  } catch(err: any) {
    try {
      const authToken: any = await refreshTokenHelper(event)
      const res3 = await handleInoutFunc(event, authToken, {
        inout_id: body.inOutId,
        tracking_number: allTrackingNumbers[0],
        tracking_url: '',
        shipment_code: dpdResult.mpsId || allTrackingNumbers.join(','),
        label_base64: dpdResult.labelPdfBase64,
        paket_type: body.paketType,
        shippingService: body.shippingService || 'DPD',
        shippingPrinter: body.shippingPrinter,
        customerEmail: customerEmail,
        isSentCustomTrackingMail: isSentCustomTrackingMail,
        all_tracking_numbers: allTrackingNumbers
      })
      data = { ...data, ...res3 }
    } catch(error: any) {
      data = errorHandlingHelper(err?.data ?? err, error?.data ?? error)
    }
  }

  return data
}

export default defineEventHandler(async (event) => {
  let data: any = {}
  try {
    data = await handleFunc(event)
  } catch(err: any) {
    data = errorHandlingHelper(err?.data ?? err, err?.data ?? err)
  }
  return data
})
