import dhlHelper from "../../../../utils/dhlHelper"
import errorHandlingHelper from "../../../../utils/errorHandlingHelper"

const toCm = (val: any): number => {
  if (val === null || val === undefined || val === '') return 0
  const raw = String(val).trim()
  if (raw === '' || raw === '0') return 0
  const hasDecimal = raw.includes('.') || raw.includes(',')
  const numeric = parseFloat(raw.replace(',', '.'))
  if (isNaN(numeric) || numeric <= 0) return 0
  const cm = hasDecimal ? numeric * 100 : numeric / 10
  return parseFloat(cm.toFixed(2))
}

export default defineEventHandler(async (event) => {
  const data: any = {}
  const body: any = await readBody(event)

  const country = String(body.country ?? '').toUpperCase().trim()
  const countryIso3 = String(body.countryIso3 ?? '').toUpperCase().trim()

  // Normalize parcels: accept either body.parcels (array) for multi-parcel mode,
  // or fall back to the flat weight/length/width/height for single-parcel mode.
  const rawParcels: any[] = Array.isArray(body.parcels) && body.parcels.length > 0
    ? body.parcels
    : [{ weight: body.weight, length: body.length, width: body.width, height: body.height }]

  const parcels = rawParcels
    .map(p => ({
      weightKg: parseFloat(p.weight ?? 0) || 0,
      length: p.length,
      width: p.width,
      height: p.height
    }))
    .filter(p => p.weightKg > 0)

  if(!body.name || !body.address || !body.postalCode || !body.city || !country || !countryIso3 || parcels.length === 0) {
    return {
      status: 400,
      message: 'Missing required fields: name, address, postalCode, city, country, and at least one parcel with weight > 0'
    }
  }

  const isDE = country === 'DE'
  const extraWeight = 0.25

  const baseRefNo = `MANUAL-${Date.now()}`

  // Optional shipper EORI (used on the CN23 customs form for non-EU shipments).
  // Only attached when the user supplied one and the destination is non-EU.
  const shipperEoriRaw = String(body.shipperEori || '').trim()
  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']
  const isNonEUDestination = !EU_COUNTRIES.includes(country)
  // DHL accepts "EORI<value>/<sub>" formatted refs (matches the existing
  // commission flow's hard-coded value). For manual we trust what the user
  // typed; if they entered a raw EORI we prefix it automatically.
  const shipperCustomsRef = isNonEUDestination && shipperEoriRaw
    ? (shipperEoriRaw.toUpperCase().startsWith('EORI') ? shipperEoriRaw : `EORI${shipperEoriRaw}/0000`)
    : ''

  // Customs declaration (parallel to DPD). DHL maps reason for export to:
  //   01 Sale → COMMERCIAL_GOODS / OTHER (we keep OTHER for flexibility)
  //   02 Return → RETURN_OF_GOODS
  //   03 Gift → GIFT
  const customsInput: any = body.customs || {}
  const reasonCode = ['01', '02', '03'].includes(customsInput.reasonForExport) ? customsInput.reasonForExport : '01'
  const dhlExportType = reasonCode === '02' ? 'RETURN_OF_GOODS' : (reasonCode === '03' ? 'GIFT' : 'OTHER')
  const customsCurrency = String(customsInput.currency || 'EUR').toUpperCase().substring(0, 3)
  // Customs items derived from per-parcel customs fields when the user filled them in
  const customsItems = (Array.isArray(body.parcels) ? body.parcels : [])
    .map((p: any) => ({
      description: String(p.description || '').trim(),
      hsCode: String(p.hsCode || '').trim(),
      countryOfOrigin: String(p.countryOfOrigin || '').trim().toUpperCase(),
      quantity: Math.max(1, parseInt(p.quantity || 1) || 1),
      value: parseFloat(p.value) || 0,
      weightKg: parseFloat(p.weight ?? 0) || 0
    }))
    .filter((it: any) => it.description && it.value > 0)
  const totalCustomsValue = customsItems.reduce((s: number, it: any) => s + it.value * it.quantity, 0)

  // Build one DHL shipment per parcel. Each shipment gets a unique refNo
  // suffix so DHL can distinguish them in their billing/tracking.
  const shipments = parcels.map((p, i) => {
    // Kleinpaket eligibility is per-parcel
    const meetsV62KPCriteria = isDE && p.weightKg < 1
    const product = meetsV62KPCriteria ? 'V62KP' : (isDE ? 'V01PAK' : 'V53WPAK')
    const billingNumber = meetsV62KPCriteria ? '63807218926201' : (isDE ? '63807218920101' : '63807218925301')
    const refNo = parcels.length > 1 ? `${baseRefNo}-P${i + 1}` : baseRefNo
    return {
      product,
      billingNumber,
      refNo,
      shipper: {
        name1: 'LogYou GmbH',
        addressStreet: 'Mühlenweg',
        addressHouse: '4',
        postalCode: '35510',
        city: 'Butzbach',
        country: 'DEU',
        email: 'info@logyou.de',
        phone: '+4960339160570'
      },
      consignee: {
        name1: String(body.name).trim(),
        addressStreet: String(body.address).trim(),
        addressHouse: String(body.houseNumber ?? '').trim(),
        postalCode: String(body.postalCode).trim(),
        city: String(body.city).trim(),
        country: countryIso3,
        email: String(body.email ?? '').trim(),
        phone: String(body.phone ?? '').trim()
      },
      details: {
        dim: {
          uom: 'cm',
          height: toCm(p.height),
          length: toCm(p.length),
          width: toCm(p.width)
        },
        weight: {
          uom: 'kg',
          value: parseFloat((p.weightKg + extraWeight).toFixed(2))
        }
      },
      // Customs declaration for non-EU shipments. Built from the customs +
      // per-parcel items the user filled in. shipperCustomsRef is the EORI.
      ...(isNonEUDestination && customsItems.length > 0 ? {
        customs: {
          exportType: dhlExportType,
          ...(shipperCustomsRef ? { shipperCustomsRef } : {}),
          postalCharges: { currency: customsCurrency, value: 0 },
          invoiceNo: baseRefNo,
          items: customsItems.map(it => ({
            itemDescription: it.description.substring(0, 256),
            packagedQuantity: it.quantity,
            itemValue: { currency: customsCurrency, value: it.value },
            itemWeight: { uom: 'kg', value: it.weightKg },
            ...(it.hsCode ? { hsCode: it.hsCode.substring(0, 11) } : {}),
            ...(it.countryOfOrigin ? { countryOfOrigin: it.countryOfOrigin.substring(0, 3) } : {})
          }))
        }
      } : {})
    }
  })

  try {
    const res: any = await dhlHelper(event, 'shipping/v2/orders?printFormat=910-300-400', 'POST', {
      profile: 'STANDARD_GRUPPENPROFIL',
      shipments
    })

    if(res?.items?.[0]?.label?.b64) {
      const first = res.items[0]
      const allItems = (res.items || []).filter((it: any) => it?.shipmentNo)
      const trackingNumbers = allItems.map((it: any) => it.shipmentNo)
      data['status'] = 200
      data['message'] = ''
      data['label_b64'] = first.label.b64                       // first label for preview
      data['tracking_number'] = first.shipmentNo                // first for backwards compat
      data['tracking_numbers'] = trackingNumbers                // all parcels
      data['parcel_count'] = trackingNumbers.length
      data['shipment_code'] = first.shipmentNo
      data['routing_code'] = first.routingCode
      data['product'] = shipments[0].product
      data['billingNumber'] = shipments[0].billingNumber
      // Per-parcel labels for multi-parcel mode (so frontend can print all of them)
      data['parcels'] = allItems.map((it: any) => ({
        tracking_number: it.shipmentNo,
        label_b64: it?.label?.b64 || '',
        routing_code: it.routingCode || ''
      }))
    } else {
      data['status'] = 500
      data['message'] = res?.status?.detail ?? 'DHL label was not created'
    }
  } catch(dhlErr: any) {
    const dhlData = dhlErr?.data
    const itemErrors: string[] = []
    if(dhlData?.items && Array.isArray(dhlData.items)) {
      for(const item of dhlData.items) {
        if(item?.validationMessages && Array.isArray(item.validationMessages)) {
          for(const vm of item.validationMessages) {
            itemErrors.push(`${vm.property || ''}: ${vm.validationMessage || vm.message || ''}`.trim())
          }
        }
        if(item?.sstatus?.detail) {
          itemErrors.push(item.sstatus.detail)
        }
      }
    }
    const errorDetail = itemErrors.length > 0
      ? itemErrors.join(' | ')
      : (dhlData?.status?.detail ?? dhlData?.detail ?? dhlErr?.message ?? 'DHL API Error')

    data['status'] = dhlData?.status?.statusCode ?? dhlErr?.statusCode ?? 400
    data['message'] = errorDetail
    data['dhl_errors'] = itemErrors
  }

  return data
})
