import refreshTokenHelper from "../../../../utils/refreshTokenHelper"
import forceLogoutHelper from "../../../../utils/forceLogoutHelper"
import errorHandlingHelper from "../../../../utils/errorHandlingHelper"
import fetchHelper from "../../../../utils/fetchHelper"

// Bulk upsert of cross-dock allocations (CUST_CrossDockAlloc) for ONE PO↔SO pair.
// Called by the board's allocation confirm dialog.
//
// Body: {
//   poOrderId, soOrderId,
//   rows: [{ id?, poOrderLineId, soOrderLineId, qty }]
// }
// Per row: id + qty>0 → update qty; id + qty<=0 → delete; no id + qty>0 → create.
// Every row is validated against the two orders' real lines (line belongs to the
// order, products match) so the client can never persist a mismatched pair.
const handleFunc = async (event: any, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const body = await readBody(event)
  const organizationId = getCookie(event, 'logship_organization_id')

  const poOrderId = Number(body.poOrderId)
  const soOrderId = Number(body.soOrderId)
  const rows: any[] = Array.isArray(body.rows) ? body.rows : []
  if (!poOrderId || !soOrderId) {
    return { status: 400, message: 'poOrderId and soOrderId are required' }
  }

  // One lines fetch per order — used to validate every row in memory.
  const [poLinesRes, soLinesRes]: any[] = await Promise.all([
    fetchHelper(event, `models/c_orderline?$filter=C_Order_ID eq ${poOrderId}&$select=M_Product_ID`, 'GET', token, null),
    fetchHelper(event, `models/c_orderline?$filter=C_Order_ID eq ${soOrderId}&$select=M_Product_ID`, 'GET', token, null)
  ])
  const productByLine = (res: any) => {
    const map: Record<number, number> = {}
    for (const r of (res?.records ?? [])) map[Number(r.id)] = Number(r?.M_Product_ID?.id ?? 0)
    return map
  }
  const poLines = productByLine(poLinesRes)
  const soLines = productByLine(soLinesRes)

  const results: any[] = []
  const errors: any[] = []

  for (const row of rows) {
    const poLineId = Number(row.poOrderLineId)
    const soLineId = Number(row.soOrderLineId)
    const qty = Number(row.qty)
    const existingId = row.id ? Number(row.id) : null

    if (!(poLineId in poLines) || !(soLineId in soLines)) {
      errors.push({ poLineId, soLineId, message: 'line does not belong to the given order' })
      continue
    }
    if (poLines[poLineId] !== soLines[soLineId] || !poLines[poLineId]) {
      errors.push({ poLineId, soLineId, message: 'products of PO line and SO line do not match' })
      continue
    }

    try {
      if (existingId && qty > 0) {
        const res: any = await fetchHelper(event, 'models/cust_crossdockalloc/' + existingId, 'PUT', token, {
          qtyAllocated: qty,
          tableName: 'CUST_CrossDockAlloc'
        })
        results.push({ id: existingId, action: 'updated', qty, res: res?.id })
      } else if (existingId && qty <= 0) {
        await fetchHelper(event, 'models/cust_crossdockalloc/' + existingId, 'DELETE', token, null)
        results.push({ id: existingId, action: 'deleted' })
      } else if (!existingId && qty > 0) {
        const res: any = await fetchHelper(event, 'models/cust_crossdockalloc', 'POST', token, {
          AD_Org_ID: {
            id: Number(organizationId),
            tableName: 'AD_Org'
          },
          PO_OrderLine_ID: {
            id: poLineId,
            tableName: 'C_OrderLine'
          },
          SO_OrderLine_ID: {
            id: soLineId,
            tableName: 'C_OrderLine'
          },
          isActive: true,
          qtyAllocated: qty,
          description: row.description ?? '',
          tableName: 'CUST_CrossDockAlloc'
        })
        results.push({ id: res?.id, action: 'created', qty })
      }
      // no id + qty<=0 → nothing to do
    } catch (err: any) {
      errors.push({ poLineId, soLineId, message: err?.data?.detail ?? err?.message ?? 'save failed' })
    }
  }

  return { status: 200, message: '', results, errors }
}

export default defineEventHandler(async (event) => {
  let data: any = {}

  try {
    data = await handleFunc(event)
  } catch(err: any) {
    try {
      let authToken: any = await refreshTokenHelper(event)
      data = await handleFunc(event, authToken)
    } catch(error: any) {
      data = errorHandlingHelper(err?.data ?? err, error?.data ?? error)
      forceLogoutHelper(event, data)
    }
  }

  return data
})
