import getTokenHelper from "../../../utils/getTokenHelper"
import refreshTokenHelper from "../../../utils/refreshTokenHelper"
import fetchHelper from "../../../utils/fetchHelper"

/**
 * Resolves whether the logged-in user is allowed to manage product images,
 * driven by the IsEditProductImage flag on the org's linked C_BPartner.
 * Returns { canEditProductImage, orgId, bpartnerId }.
 *
 * Why this endpoint exists (and why it does NOT reuse the direct
 * /organizations/{id}/bpartner read):
 *  - A limited customer role ('c') is scoped to its OWN org (e.g. wonderhome
 *    1000008) and is denied/filtered on the admin tables ad_user / ad_org /
 *    c_bpartner via REST, so reading the flag with the USER's token returns
 *    nothing. We therefore read with the iDempiere service token (system,
 *    role-independent) — the same pattern adUserCredentials.ts uses for ad_user.
 *  - The org cookie is not a reliable source for limited users, so resolve the
 *    org straight from the user record (ad_user.AD_Org_ID), falling back to the
 *    org cookie when the user record has no usable org.
 *
 * Two requests (ad_user itself does not support expanding AD_Org_ID):
 *   1. models/ad_user/{userId}?$select=AD_Org_ID            -> the user's org id
 *   2. models/ad_org/{orgId}?$expand=C_BPartner_ID          -> linked partner
 */
const truthy = (v: any) =>
  v === true || v === 'Y' || v === 'y' || v === 'true' || v === 'Yes' || v === 1 || v === '1'

// iDempiere OData response casing varies by model, so match the flag key
// case-insensitively and accept every truthy representation it may return.
const readEditImageFlag = (bpartner: any): boolean => {
  if (!bpartner || typeof bpartner !== 'object') return false
  for (const k of Object.keys(bpartner)) {
    if (k.toLowerCase() === 'iseditproductimage') return truthy(bpartner[k])
  }
  return false
}

const handleFunc = async (event: any, authToken: string | null = null) => {
  const config = useRuntimeConfig()
  // Service token sees every org/column regardless of the caller's role; the
  // limited 'c' token cannot read these admin tables. Fall back to the user
  // token only if the env var is unset.
  const serviceToken = (config.api as any)?.idempieretoken
  const token = serviceToken || authToken || await getTokenHelper(event)
  const userId = getCookie(event, 'logship_user_id')
  const cookieOrgId = getCookie(event, 'logship_organization_id')

  // 1. Resolve the user's own org (reliable for limited roles); fall back to cookie.
  let orgId: any = cookieOrgId
  if (userId) {
    const userRes: any = await fetchHelper(event, `models/ad_user/${userId}?$select=AD_Org_ID`, 'GET', token, null)
    const userOrgId = userRes?.AD_Org_ID?.id
    if (userOrgId && Number(userOrgId) > 0) {
      orgId = userOrgId
    }
  }

  if (!orgId || Number(orgId) <= 0) {
    return { canEditProductImage: false, orgId: orgId ? Number(orgId) : null, bpartnerId: null }
  }

  // 2. Pull the org's linked C_BPartner inline via $expand.
  const orgRes: any = await fetchHelper(event, `models/ad_org/${orgId}?$expand=C_BPartner_ID`, 'GET', token, null)
  const bpartner: any = orgRes?.C_BPartner_ID ?? null

  return {
    canEditProductImage: readEditImageFlag(bpartner),
    orgId: Number(orgId),
    bpartnerId: bpartner?.id ?? null
  }
}

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

  try {
    data = await handleFunc(event)
  } catch (err: any) {
    try {
      const authToken: any = await refreshTokenHelper(event)
      data = await handleFunc(event, authToken)
    } catch (error: any) {
      // Fail-closed: never block the page, just deny the extra capability.
      data = { canEditProductImage: false }
    }
  }

  return data
})
