import refreshTokenHelper from "../../../utils/refreshTokenHelper"
import forceLogoutHelper from "../../../utils/forceLogoutHelper"
import errorHandlingHelper from "../../../utils/errorHandlingHelper"
import {
  resolveOrderSourceAmazonConnection,
  getListingsItem,
  patchListingsItemQuantity,
  updateCachedListingQuantity,
  withListingsPushQueue
} from "../../../utils/amazonSpApi"

const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))

// POST /api/amazon/stocks/sync
// Pushes ONE merchant-fulfilled quantity to Amazon for the Amazon stock page
// (/fulfillment/amazon-stocks). Body: { orderSourceId, sku, quantity }.
//
// Quantity only — no price, no attributes. Mirrors sales/sis/price-update:
// Listings Items PATCH of `fulfillment_availability`, which Amazon answers
// with an async "ACCEPTED" submission; we poll the read briefly for a
// confirmed value and otherwise trust the accepted submission. FBA listings
// (fulfillment channel != DEFAULT) are refused — their stock is Amazon's.
const handleFunc = async (event: any, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const body = await readBody(event)
  const orderSourceId = Number(body?.orderSourceId)
  const sku = String(body?.sku || '').trim()
  const quantity = Number(body?.quantity)

  if (!orderSourceId) return { status: 400, success: false, message: 'orderSourceId is required' }
  if (!sku) return { status: 400, success: false, message: 'sku is required' }
  if (!Number.isFinite(quantity) || quantity < 0) return { status: 400, success: false, message: 'quantity must be a number >= 0' }
  const targetQty = Math.trunc(quantity)

  const { sellerId, marketplaceId, accessToken } = await resolveOrderSourceAmazonConnection(event, token, orderSourceId)

  let userLabel = 'unknown'
  try {
    const raw = getCookie(event, 'logship_user')
    const user = raw ? JSON.parse(raw) : null
    userLabel = user?.Name || user?.email || getCookie(event, 'logship_user_id') || 'unknown'
  } catch {
    userLabel = getCookie(event, 'logship_user_id') || 'unknown'
  }

  return withListingsPushQueue(orderSourceId, async () => {
    let before: any = null
    try {
      before = await getListingsItem(accessToken, sellerId, sku, marketplaceId)
    } catch (e: any) {
      if (Number(e?.status) === 404) {
        return { status: 404, success: false, sku, message: `SKU "${sku}" is not listed in this marketplace` }
      }
      throw e
    }

    const channel = String(before?.fulfillmentChannel || 'DEFAULT').toUpperCase()
    if (channel !== 'DEFAULT') {
      return {
        status: 400,
        success: false,
        sku,
        message: `SKU "${sku}" is fulfilled by Amazon (${channel}) — its quantity cannot be set from here`
      }
    }

    let patchResult: any = null
    try {
      patchResult = await patchListingsItemQuantity(accessToken, sellerId, sku, marketplaceId, targetQty, before)
    } catch (e: any) {
      console.error('[amazon-stocks] qty push FAILED', { user: userLabel, orderSourceId, sku, oldQty: before?.quantity ?? null, targetQty, error: e?.message || String(e) })
      throw e
    }

    const blockingIssues = (patchResult?.issues || []).filter((i: any) => (i?.severity || '').toUpperCase() !== 'WARNING')
    if (patchResult?.status !== 'ACCEPTED' || blockingIssues.length > 0) {
      const msg = blockingIssues.map((i: any) => i.message).join('; ') || `Amazon rejected the submission (status: ${patchResult?.status})`
      console.error('[amazon-stocks] qty push REJECTED', { user: userLabel, orderSourceId, sku, targetQty, issues: patchResult?.issues })
      return { status: 502, success: false, sku, message: `Amazon rejected the quantity update: ${msg}` }
    }

    // Poll briefly for the read to catch up — Amazon applies ACCEPTED
    // submissions asynchronously. Not required for success.
    let after: any = null
    for (let attempt = 0; attempt < 4; attempt++) {
      await sleep(1500)
      after = await getListingsItem(accessToken, sellerId, sku, marketplaceId).catch(() => null)
      if (after?.quantity != null && Number(after.quantity) === targetQty) break
    }
    const confirmed = after?.quantity != null && Number(after.quantity) === targetQty
    const pending = !confirmed

    updateCachedListingQuantity(orderSourceId, sku, targetQty)

    console.log('[amazon-stocks] qty push', {
      user: userLabel,
      orderSourceId,
      sku,
      oldQty: before?.quantity ?? null,
      targetQty,
      confirmed,
      pending
    })

    return {
      status: 200,
      success: true,
      sku,
      oldQty: before?.quantity ?? null,
      requestedQty: targetQty,
      updatedQty: targetQty,
      pending,
      message: pending
        ? `Amazon accepted ${targetQty} for ${sku} (still applying)`
        : `Amazon stock set to ${targetQty} for ${sku}`
    }
  })
}

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

  try {
    data = await handleFunc(event)
  } catch (err: any) {
    // An Amazon-side failure is not an auth problem — never re-run the whole
    // push through the token-refresh path (see sales/sis/price-update).
    if (err?.isAmazonError) {
      data = errorHandlingHelper(err?.data ?? err, err?.data ?? err)
      return { ...data, success: false }
    }
    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)
      data = { ...data, success: false }
    }
  }

  return data
})
