import { string } from 'alga-js'
import refreshTokenHelper from "../../../utils/refreshTokenHelper"
import forceLogoutHelper from "../../../utils/forceLogoutHelper"
import errorHandlingHelper from "../../../utils/errorHandlingHelper"
import fetchHelper from "../../../utils/fetchHelper"
import getTokenHelper from "../../../utils/getTokenHelper"

const handleFunc = async (event: any, authToken: any = null) => {
  let data: any = { records: [], 'row-count': 0 }
  const token = authToken ?? await getTokenHelper(event)
  const query = getQuery(event)
  const orgId = query?.org_id as string

  if (!orgId) {
    return { status: 400, message: 'Organization ID is required', records: [], 'row-count': 0 }
  }

  // Build filter for products owned by organization
  const orgFilter = string.urlEncode(`AD_Org_ID eq ${orgId} and IsActive eq true`)

  // Step 1: Fetch all locators for this organization first
  // This is more efficient than querying by IDs later
  const locatorMap = new Map<number, any>()
  try {
    const locatorOrgFilter = string.urlEncode(`AD_Org_ID eq ${orgId}`)
    const locatorRes: any = await fetchHelper(
      event,
      `models/m_locator?$filter=${locatorOrgFilter}&$expand=M_LocatorType_ID&$top=5000`,
      'GET',
      token,
      null
    )

    if (locatorRes?.records) {
      for (const locator of locatorRes.records) {
        locatorMap.set(locator.id, locator)
      }
    }
    console.log('[qty-on-hand-by-locator] Loaded', locatorMap.size, 'locators for org', orgId)
  } catch (err) {
    console.error('[qty-on-hand-by-locator] Error fetching locators:', err)
    // Continue without locator details - we'll still show products
  }

  // Step 2: Fetch products with storage data
  const res: any = await fetchHelper(
    event,
    `models/m_product?$select=${string.urlEncode('M_Product_ID,Name,SKU,UPC,Value,mpn,AD_Org_ID')}&$expand=M_Storage,AD_Org_ID($select=Name)&$filter=${orgFilter}&$orderby=${string.urlEncode('Name asc')}&$top=5000`,
    'GET',
    token,
    null
  )

  if (!res?.records) {
    return data
  }

  // Group records by product + locator (X, Y, Z) and aggregate qtyOnHand
  // Key format: productId_locatorX_locatorY_locatorZ
  const groupedMap = new Map<string, any>()

  for (const product of res.records) {
    const storages = product?.M_Storage || []
    const productId = product.M_Product_ID || product.id
    const orgName = product.AD_Org_ID?.Name || ''
    const orgIdVal = product.AD_Org_ID?.id || orgId

    if (Array.isArray(storages) && storages.length > 0) {
      for (const storage of storages) {
        const locatorId = storage?.M_Locator_ID?.id
        const locator = locatorId ? locatorMap.get(locatorId) : null
        const qtyOnHand = Number(storage?.QtyOnHand || 0)

        const locatorX = locator?.X || ''
        const locatorY = locator?.Y || ''
        const locatorZ = locator?.Z || ''

        // Create a unique key for product + locator coordinates
        const groupKey = `${productId}_${locatorX}_${locatorY}_${locatorZ}`

        if (groupedMap.has(groupKey)) {
          // Add to existing group
          const existing = groupedMap.get(groupKey)
          existing.qtyOnHand += qtyOnHand
        } else {
          // Create new group entry
          groupedMap.set(groupKey, {
            id: `${productId}_${locatorId || 'no_locator'}`,
            productId: productId,
            locatorId: locatorId || null,
            name: product.Name || '',
            sku: product.SKU || '',
            ean: product.UPC || '',
            value: product.Value || '',
            mpn: product.mpn || '',
            qtyOnHand: qtyOnHand,
            locatorX: locatorX,
            locatorY: locatorY,
            locatorZ: locatorZ,
            locatorValue: locator?.Value || '',
            locatorPriority: locator?.PriorityNo ?? null,
            locatorTypeId: locator?.M_LocatorType_ID?.id || null,
            locatorTypeName: locator?.M_LocatorType_ID?.Name || '',
            organization: orgName,
            organizationId: orgIdVal
          })
        }
      }
    } else {
      // Product has no storage entries - include with null locator data
      const groupKey = `${productId}_no_storage`
      if (!groupedMap.has(groupKey)) {
        groupedMap.set(groupKey, {
          id: `${productId}_no_storage`,
          productId: productId,
          locatorId: null,
          name: product.Name || '',
          sku: product.SKU || '',
          ean: product.UPC || '',
          value: product.Value || '',
          mpn: product.mpn || '',
          qtyOnHand: 0,
          locatorX: '',
          locatorY: '',
          locatorZ: '',
          locatorValue: '',
          locatorPriority: null,
          locatorTypeId: null,
          locatorTypeName: '',
          organization: orgName,
          organizationId: orgIdVal
        })
      }
    }
  }

  const transformedRecords = Array.from(groupedMap.values())

  data = {
    status: 200,
    records: transformedRecords,
    'row-count': transformedRecords.length
  }

  return data
}

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
})