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

/**
 * GET /api/materials/products[?top=&skip=]
 *
 * Full product list with storage rows. Historically this was ONE iDempiere call
 * with `$expand=M_Storage` over all ~3.3k products — the single most expensive
 * request in the app (see productStorageHelper.ts for why the expand is a
 * global-lock hazard in idempiere-rest). It ran ~65×/day and was the request
 * that tipped iDempiere over on 2026-09-10.
 *
 * Now: plain product query + paged m_storage join, a short server-side cache so
 * a burst of identical calls (page reloads, several users) costs one backend
 * round-trip, and single-flight so concurrent identical calls share it.
 * Optional `top`/`skip` let callers page instead of pulling everything.
 */

const RESPONSE_CACHE_TTL_MS = 60_000
const responseCache = new Map<string, { at: number; data: any }>()
const inflight = new Map<string, Promise<any>>()

const SELECT = string.urlEncode('M_Product_ID,M_Product_UU,Name,Value,SKU,mpn,UPC,Weight,IsBOM,AD_Org_ID,Strapi_Product_documentId')

function paging(query: any): { top: number | null; skip: number } {
  const top = Number(query?.top)
  const skip = Number(query?.skip)
  return {
    top: Number.isFinite(top) && top > 0 ? Math.min(Math.floor(top), 5000) : null,
    skip: Number.isFinite(skip) && skip > 0 ? Math.floor(skip) : 0,
  }
}

function cacheKey(event: any, top: number | null, skip: number): string {
  const c = getCookie(event, 'logship_client_id') || ''
  const r = getCookie(event, 'logship_role_id') || ''
  const o = getCookie(event, 'logship_organization_id') || ''
  return `${c}:${r}:${o}:${top ?? 'all'}:${skip}`
}

const loadProducts = async (event: any, token: any, top: number | null, skip: number) => {
  let url = `models/m_product?$select=${SELECT}&$filter=${string.urlEncode('isActive eq true OR isActive eq false')}&$orderby=${string.urlEncode('M_Product_ID desc')}`
  if (top) url += `&$top=${top}`
  if (skip) url += `&$skip=${skip}`
  return await fetchProductsWithStorage(event, token, url)
}

const handleFunc = async (event: any, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const { top, skip } = paging(getQuery(event))
  const key = cacheKey(event, top, skip)

  const hit = responseCache.get(key)
  if (hit && Date.now() - hit.at < RESPONSE_CACHE_TTL_MS) return hit.data

  const running = inflight.get(key)
  if (running) return await running

  const p = loadProducts(event, token, top, skip)
    .then((data: any) => {
      if (data && Array.isArray(data.records)) responseCache.set(key, { at: Date.now(), data })
      return data ?? {}
    })
    .finally(() => inflight.delete(key))
  inflight.set(key, p)
  return await p
}

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