import getTokenHelper from "../../utils/getTokenHelper"
import refreshTokenHelper from "../../utils/refreshTokenHelper"
import errorHandlingHelper from "../../utils/errorHandlingHelper"
import fetchHelper from "../../utils/fetchHelper"
import { resolveMerchantPartner, pickMerchantFields, MERCHANT_PARTNER_FIELDS } from "../../utils/merchantPartner"

/**
 * Merchant self-service update of the own company partner (C_BPartner).
 * Writes with the iDempiere service token (limited roles cannot write
 * c_bpartner), but ONLY keys present in MERCHANT_PARTNER_FIELDS are accepted
 * — anything else in the body is ignored. The target partner is resolved
 * server-side from the caller's own identity; the client cannot pick one.
 */
const handleFunc = async (event: any, authToken: string | null = null) => {
  const config = useRuntimeConfig()
  const serviceToken = (config.api as any)?.idempieretoken
  const token = serviceToken || authToken || await getTokenHelper(event)
  const body = await readBody(event)

  // Build the write payload strictly from the whitelist.
  const updatePayload: Record<string, any> = {}
  for (const [key, def] of Object.entries(MERCHANT_PARTNER_FIELDS)) {
    if (!body || !Object.prototype.hasOwnProperty.call(body, key)) continue
    const value = String(body[key] ?? '').trim()
    if (key === 'eMailInvoice') {
      // Empty clears the field (invoice emails then fall back to the general
      // partner EMail); otherwise require a plausible address.
      if (value !== '' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
        return { status: 422, message: 'Invalid email address' }
      }
      if (value.length > 254) {
        return { status: 422, message: 'Email address is too long' }
      }
    }
    updatePayload[def.writeKey] = value
  }

  if (Object.keys(updatePayload).length === 0) {
    return { status: 400, message: 'No editable field in request' }
  }

  const partner = await resolveMerchantPartner(event, token)
  if (!partner) {
    return { status: 404, message: 'No business partner is linked to this account' }
  }

  const res: any = await fetchHelper(event, `models/c_bpartner/${partner.id}`, 'PUT', token, updatePayload)

  return {
    status: 200,
    companyName: res?.Name || partner.record?.Name || '',
    ...pickMerchantFields(res ?? partner.record)
  }
}

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

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

  return data
})
