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

// GET /api/shopify-new/products?orderSourceId=123&limit=50&offset=0&search=
// Fetches local products for Shopify-New (GraphQL) sync
// The Shopify variant ID is stored in M_Product.SKU
// Returns qty on hand filtered by the order source's M_Warehouse_ID
const handleFunc = async (event: any, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const query = getQuery(event)
  const orderSourceId = query.orderSourceId as string
  const limit = Number(query.limit) || 50
  const offset = Number(query.offset) || 0
  const search = (query.search as string)?.trim() || ''

  if(!orderSourceId) {
    return { status: 400, message: 'orderSourceId is required' }
  }

  // Load order source to verify it's shopify-new and get warehouse info
  const os: any = await fetchHelper(event, `models/c_ordersource/${orderSourceId}`, 'GET', token, null)
  if(!os) {
    return { status: 404, message: 'Order Source not found' }
  }
  if(os?.Marketplace?.identifier !== 'shopify-new') {
    return { status: 400, message: 'Selected Order Source is not Shopify-New' }
  }

  // Get the local iDempiere warehouse ID from order source
  const localWarehouseId = os?.M_Warehouse_ID?.id
  // Get Shopify location ID for sync (if configured)
  const shopifyLocationId = os?.Shopify_Location_ID || null
  // Get organization ID from order source
  const orgId = os?.AD_Org_ID?.id

  try {
    // Build filter for products
    let filterParts = []

    if(orgId) {
      filterParts.push(`AD_Org_ID eq ${orgId}`)
    }

    if(search) {
      const escapedSearch = search.replace(/'/g, "''")
      filterParts.push(`(contains(mpn,'${escapedSearch}') or contains(Name,'${escapedSearch}') or contains(SKU,'${escapedSearch}'))`)
    }

    const filter = filterParts.length > 0 ? string.urlEncode(filterParts.join(' and ')) : ''
    const select = string.urlEncode('m_product_id,Name,SKU,mpn,Value,shopify_product_id')

    // Fetch products with SKU (Shopify variant ID)
    // Expand M_Storage to get qty on hand per locator
    let url = `models/m_product?$select=${select}&$expand=${string.urlEncode('M_Storage($expand=M_Locator_ID)')}&$top=${limit}&$skip=${offset}&$orderby=${string.urlEncode('Name asc')}`
    if(filter) {
      url += `&$filter=${filter}`
    }
    const res: any = await fetchHelper(
      event,
      url,
      'GET',
      token,
      null
    )

    if(!res?.records) {
      return { status: 200, records: [], _page: { total: 0, limit, offset }, warehouseId: localWarehouseId, shopifyLocationId }
    }

    // Stock sitting on "return" locators (M_LocatorType with all three
    // IsAvailableFor* flags = false) must not be reported as sellable stock.
    const returnLocatorIds = await getReturnLocatorIds(event, token, orgId || null)

    // Process all records
    const records = res.records.map((p: any) => {
      const storages = p?.M_Storage || []
      let qtyOnHand = 0
      let qtyOnHandAll = 0
      let returnQtyOnHand = 0

      if(Array.isArray(storages)) {
        for(const storage of storages) {
          const qty = Number(storage?.QtyOnHand || 0)
          const locator = storage?.M_Locator_ID
          const locatorId = locator?.id ?? locator
          const isReturnLocator =
            locatorId !== undefined && locatorId !== null && returnLocatorIds.has(Number(locatorId))

          qtyOnHandAll += qty
          if (isReturnLocator) {
            returnQtyOnHand += qty
            continue
          }

          if(localWarehouseId) {
            const storageWarehouseId = locator?.M_Warehouse_ID?.id || locator?.m_warehouse_id
            if(String(storageWarehouseId) === String(localWarehouseId)) {
              qtyOnHand += qty
            }
          } else {
            qtyOnHand += qty
          }
        }
      }

      return {
        id: Number(p.m_product_id || p.id),
        name: p.Name || '',
        sku: p.SKU || '',
        mpn: p.mpn || '',
        value: p.Value || '',
        shopifyVariantId: p.SKU || null,
        shopifyProductId: p.shopify_product_id || null,
        qtyOnHand, // Excludes return locators
        qtyOnHandAll,
        returnQtyOnHand,
        shopifyStock: null
      }
    })

    return {
      status: 200,
      records,
      _page: {
        total: res['@odata.count'] ?? records.length,
        limit,
        offset
      },
      warehouseId: localWarehouseId,
      warehouseName: os?.M_Warehouse_ID?.identifier || null,
      shopifyLocationId
    }
  } catch (err: any) {
    const data = errorHandlingHelper(err?.data ?? err, err?.data ?? err)
    return { status: Number(data?.status || 500), message: data?.message || 'Failed to fetch products' }
  }
}

export default defineEventHandler(async (event) => {
  try {
    return await handleFunc(event)
  } catch (err: any) {
    try {
      const authToken = await refreshTokenHelper(event)
      return await handleFunc(event, authToken)
    } catch (error: any) {
      const data = errorHandlingHelper(err?.data ?? err, error?.data ?? error)
      if([401, 402, 403, 407].includes(Number(data.status))) {
        //@ts-ignore
        setCookie(event, 'user', null)
      }
      return data
    }
  }
})
