import { findLatestOrderByPlatformOrderId } from '../../../repositories/order-repo.js'
import { listTasksByOrderId } from '../../../repositories/task-repo.js'
import { asJsonObject, type JsonObject } from '../../../types/json.js'
import {
  findKuaishouIndustryVoucherByCode,
  listKuaishouIndustryVouchersByOid,
  listKuaishouIndustryVouchersForSendCallbackRetry,
  updateKuaishouIndustryVoucherByCode,
  upsertKuaishouIndustryVoucher,
} from '../../../repositories/kuaishou-industry-voucher-repo.js'
import { OPEN_91_PLATFORM, OPEN_91_PROVIDER } from '../../open-91/config.js'
import { retryOpen91Order } from '../ninetyone/order-service.js'
import { syncWorkOrdersFromKuaishouSendCode } from '../../worker-platform/sync-work-orders-from-send-code.js'
import { normalizeTimestampIso } from '../../../utils/time.js'
import { logWarn, logIntegration } from '../../../utils/logger.js'
import { getKuaishouIndustryConfig, assertMatchingAppKey } from './config.js'
import { normalizeSendCodePayload, assertSendCodePayload } from './payload.js'
import { assertKuaishouIndustrySignature } from './crypto.js'
import {
  buildIndustrySuccessResponse,
  buildIndustryEticketItem,
  buildIndustrySendCodeData,
} from './response.js'
import { sendCallback } from './send-callback-service.js'
import {
  buildKuaishouIndustryEticketFromVoucher,
  isKuaishouIndustryVoucherSendCallbackSuccess,
  KUAISHOU_INDUSTRY_SEND_CALLBACK_STATUS,
  resolveKuaishouIndustryEticketType,
  resolveKuaishouIndustryVoucherValidity,
} from './voucher-service.js'
import { bindKuaishouIndustryVouchersToOrderTasks } from './voucher-binding-service.js'
import { parseAmountToFen } from '../../../utils/money.js'
import {
  publishAdminOrderRealtimeChange,
  publishWorkOrderRealtimeChange,
} from '../../realtime/realtime-event-service.js'
import type { KuaishouIndustryVoucherRow, OrderRow } from '../../../types/repository/rows.js'

type SendCodeCallbackParams = {
  oid: string
  sendType: string
  sellerId: string
  token: string
  eticketType?: string
  ext?: string
}

const SEND_CALLBACK_INITIAL_DELAY_MS = 3_000
const SEND_CALLBACK_SCAN_INTERVAL_MS = 15_000
const SEND_CALLBACK_MAX_ATTEMPTS = 8
const SEND_CALLBACK_BACKOFF_MS = [3_000, 10_000, 30_000, 60_000, 120_000, 300_000]

const sendCallbackRetryTimers = new Map<string, NodeJS.Timeout>()
const sendCallbackInFlightOids = new Set<string>()
let sendCallbackWorkerTimer: NodeJS.Timeout | null = null
let sendCallbackWorkerRunning = false

export async function handleSendCode(rawBody: JsonObject = {}) {
  const config = getKuaishouIndustryConfig()

  assertKuaishouIndustrySignature(rawBody, config)

  const params = normalizeSendCodePayload(rawBody)
  assertSendCodePayload(params, config)
  assertMatchingAppKey(params.appKey)

  const now = normalizeTimestampIso(new Date().toISOString())
  const nowMs = Date.now()
  const normalizedOid = params.oid

  const order = await findLatestOrderByPlatformOrderId({
    provider: OPEN_91_PROVIDER,
    platform: OPEN_91_PLATFORM,
    platformOrderId: normalizedOid,
  })
  const targetTaskCount = params.num > 0 ? params.num : 1
  const tasks = order ? await listTasksByOrderId(order.id) : []
  const validity = resolveKuaishouIndustryVoucherValidity(params, nowMs)
  const vouchers: KuaishouIndustryVoucherRow[] = []

  for (let index = 0; index < targetTaskCount; index += 1) {
    const unitIndex = index + 1
    const task = tasks.find((item) => Number(item.unit_index || 0) === unitIndex) || null
    const voucher = await upsertKuaishouIndustryVoucher({
      oid: normalizedOid,
      unitIndex,
      sellerId: params.sellerId,
      token: params.token,
      eticketType: params.eticketType,
      orderId: order?.id || null,
      taskId: task?.id || null,
      status: 'UNUSED',
      sendCallbackStatus: KUAISHOU_INDUSTRY_SEND_CALLBACK_STATUS.PENDING,
      sendCallbackLastError: '',
      sendCallbackResponseJson: {},
      sendCallbackSentAt: null,
      validStartTime: validity.validStartTime,
      validEndTime: validity.validEndTime,
      rawPayloadJson: {
        source: 'kuaishou-industry/send-code',
        receivedAt: now,
        body: params,
      },
      createdAt: now,
      updatedAt: now,
    })

    if (voucher) {
      vouchers.push(voucher)
    }
  }

  const etickets = vouchers.map((voucher) =>
    buildKuaishouIndustryEticketFromVoucher(voucher, params.eticketType),
  )

  if (order) {
    await bindKuaishouIndustryVouchersToOrderTasks(order, tasks, {
      source: 'kuaishou_industry_send_code',
      now,
    })
  }

  try {
    const syncResult = await syncWorkOrdersFromKuaishouSendCode({
      oid: normalizedOid,
      sellerId: params.sellerId,
      itemId: params.itemId,
      itemTitle: params.itemTitle,
      skuId: params.skuId,
      num: params.num,
      paymentFen: resolveSendCodePaymentFen(params.ext),
      rawParams: params,
      vouchers,
      now,
    })
    if (syncResult.orderId) {
      publishAdminOrderRealtimeChange(syncResult.orderId)
    }
    for (const workOrderId of syncResult.workOrderIds) {
      publishWorkOrderRealtimeChange({ workOrderId })
    }
  } catch (error) {
    logWarn('[kuaishou-industry/send-code]', '发单平台工单同步失败，不影响发码主流程', {
      oid: normalizedOid,
      error: error instanceof Error ? error.message : String(error),
    })
  }

  scheduleKuaishouIndustrySendCallbackRetry(normalizedOid, SEND_CALLBACK_INITIAL_DELAY_MS, {
    source: 'send_code_accepted',
  })

  return buildIndustrySuccessResponse(
    buildIndustrySendCodeData({
      oid: normalizedOid,
      sendType: params.sendType,
      sendNum: etickets.length,
      etickets,
    }),
  )
}

export function startKuaishouIndustrySendCallbackRetryWorker() {
  if (sendCallbackWorkerTimer) {
    return
  }

  scheduleSendCallbackWorkerScan(5_000)
}

export function stopKuaishouIndustrySendCallbackRetryWorker() {
  if (sendCallbackWorkerTimer) {
    clearTimeout(sendCallbackWorkerTimer)
    sendCallbackWorkerTimer = null
  }

  for (const timer of sendCallbackRetryTimers.values()) {
    clearTimeout(timer)
  }
  sendCallbackRetryTimers.clear()
}

export async function resendKuaishouIndustryVoucherSendCallback(input: {
  voucherCode: string
  oid?: string
  preferredTotalGoodsValue?: number
}) {
  const voucher = await findKuaishouIndustryVoucherByCode(input.voucherCode, input.oid || '')
  if (!voucher) {
    return {
      success: false,
      error: '电子凭证不存在，无法重发发码回调',
      voucher: null,
    }
  }

  const rawPayload = parseJsonObject(voucher.raw_payload_json)
  const body = parseJsonObject(rawPayload.body)
  const params = resolveSendCodeCallbackParams(voucher, body)
  const eticketType = String(params.eticketType || '').trim()
  const eticket = buildKuaishouIndustryEticketFromVoucher(voucher, eticketType)
  const result = await sendAndRecordCallback({
    oid: params.oid,
    sendType: params.sendType,
    etickets: [eticket],
    vouchers: [voucher],
    sellerId: params.sellerId,
    token: params.token,
    eticketType,
    source: 'admin_resend',
    ...(input.preferredTotalGoodsValue !== undefined
      ? { preferredTotalGoodsValue: input.preferredTotalGoodsValue }
      : {}),
    ...(params.ext ? { ext: params.ext } : {}),
  })
  const updatedVoucher = await findKuaishouIndustryVoucherByCode(voucher.voucher_code, voucher.oid)

  if (result.success) {
    await syncOpen91OrderAfterSendCallbackSuccess(params.oid, {
      source: 'admin_resend',
    })
  }

  return {
    ...result,
    voucher: updatedVoucher || voucher,
  }
}

async function runKuaishouIndustrySendCallbackForOid(
  oid: string,
  { source = 'async_retry' }: { source?: string } = {},
) {
  const normalizedOid = String(oid || '').trim()
  if (!normalizedOid) {
    return {
      success: false,
      error: '缺少订单号，无法发起电子凭证发货回调',
    }
  }

  // 同一 oid 的回调可能被多个来源同时调度（内存重试链 timer、worker_scan 兜底扫描、
  // 快手重复推送 send-code 后的再次调度）。快手侧对同一 oid 的电子凭证发货回调有并发锁，
  // 并发请求会拿到 807000「获取并发锁失败」。这里用 in-flight 集合做进程内互斥：
  // 正在执行时其它调度直接跳过，由当前执行链路自己决定成功或按 backoff 重试。
  if (sendCallbackInFlightOids.has(normalizedOid)) {
    logIntegration(
      '[kuaishou-industry/send-code]',
      '电子凭证发货回调正在执行中，跳过本次并发调度',
      {
        source,
        oid: normalizedOid,
      },
    )
    return {
      success: false,
      skipped: true,
      reason: 'callback_in_flight',
    }
  }
  sendCallbackInFlightOids.add(normalizedOid)

  try {
    const vouchers = await listKuaishouIndustryVouchersByOid(normalizedOid)
    const pendingVouchers = vouchers
      .filter((voucher) => !isKuaishouIndustryVoucherSendCallbackSuccess(voucher))
      .filter(
        (voucher) =>
          normalizePositiveInteger(voucher.send_callback_attempt_count) <
          SEND_CALLBACK_MAX_ATTEMPTS,
      )

    if (pendingVouchers.length === 0) {
      return {
        success: vouchers.length > 0,
        skipped: true,
        reason:
          vouchers.length > 0 ? 'send_callback_already_success_or_max_attempts' : 'voucher_missing',
      }
    }

    const rawPayload = parseJsonObject(pendingVouchers[0]?.raw_payload_json)
    const body = parseJsonObject(rawPayload.body)
    const firstVoucher = pendingVouchers[0]
    if (!firstVoucher) {
      return {
        success: false,
        error: '缺少待回调电子凭证',
      }
    }

    const params = resolveSendCodeCallbackParams(firstVoucher, body)
    const eticketType = String(params.eticketType || '').trim()
    const etickets = pendingVouchers.map((voucher) =>
      buildKuaishouIndustryEticketFromVoucher(voucher, eticketType),
    )
    const order = await findLatestOrderByPlatformOrderId({
      provider: OPEN_91_PROVIDER,
      platform: OPEN_91_PLATFORM,
      platformOrderId: normalizedOid,
    })
    const result = await sendAndRecordCallback({
      oid: params.oid,
      sendType: params.sendType,
      etickets,
      vouchers: pendingVouchers,
      sellerId: params.sellerId,
      token: params.token,
      eticketType,
      source,
      preferredTotalGoodsValue: resolveSendCallbackPreferredTotalGoodsValue(order),
      ...(params.ext ? { ext: params.ext } : {}),
    })

    if (result.success) {
      await syncOpen91OrderAfterSendCallbackSuccess(normalizedOid, { source })
      return result
    }

    const nextAttemptCount =
      Math.max(
        ...pendingVouchers.map((voucher) =>
          normalizePositiveInteger(voucher.send_callback_attempt_count),
        ),
      ) + 1
    if (nextAttemptCount < SEND_CALLBACK_MAX_ATTEMPTS && isRetriableSendCallbackFailure(result)) {
      scheduleKuaishouIndustrySendCallbackRetry(
        normalizedOid,
        resolveSendCallbackBackoffMs(nextAttemptCount),
        {
          source: `${source}_retry`,
        },
      )
    }

    return result
  } finally {
    sendCallbackInFlightOids.delete(normalizedOid)
  }
}

function scheduleKuaishouIndustrySendCallbackRetry(
  oid: string,
  delayMs: number,
  { source = 'async_retry' }: { source?: string } = {},
) {
  const normalizedOid = String(oid || '').trim()
  if (!normalizedOid || sendCallbackRetryTimers.has(normalizedOid)) {
    return false
  }

  const normalizedDelayMs = Math.max(0, Number(delayMs) || 0)
  const timer = setTimeout(() => {
    sendCallbackRetryTimers.delete(normalizedOid)
    void runKuaishouIndustrySendCallbackForOid(normalizedOid, { source }).catch((error) => {
      logIntegration(
        '[kuaishou-industry/send-code]',
        '异步电子凭证发货回调执行异常',
        {
          source,
          oid: normalizedOid,
          error: error instanceof Error ? error.message : String(error),
        },
        { level: 'warn' },
      )
      scheduleKuaishouIndustrySendCallbackRetry(normalizedOid, resolveSendCallbackBackoffMs(1), {
        source: `${source}_exception_retry`,
      })
    })
  }, normalizedDelayMs)

  sendCallbackRetryTimers.set(normalizedOid, timer)
  logIntegration('[kuaishou-industry/send-code]', '电子凭证发货回调已进入异步队列', {
    source,
    oid: normalizedOid,
    delayMs: normalizedDelayMs,
  })
  return true
}

function scheduleSendCallbackWorkerScan(delayMs: number) {
  if (sendCallbackWorkerTimer) {
    return
  }

  sendCallbackWorkerTimer = setTimeout(
    () => {
      sendCallbackWorkerTimer = null
      void runSendCallbackWorkerScan().finally(() => {
        scheduleSendCallbackWorkerScan(SEND_CALLBACK_SCAN_INTERVAL_MS)
      })
    },
    Math.max(0, Number(delayMs) || 0),
  )
}

async function runSendCallbackWorkerScan() {
  if (sendCallbackWorkerRunning) {
    return
  }

  sendCallbackWorkerRunning = true
  try {
    const vouchers = await listKuaishouIndustryVouchersForSendCallbackRetry(
      200,
      SEND_CALLBACK_MAX_ATTEMPTS,
    )
    const dueOids = new Set<string>()
    for (const voucher of vouchers) {
      if (isVoucherDueForSendCallbackRetry(voucher)) {
        dueOids.add(String(voucher.oid || '').trim())
      }
    }

    for (const oid of dueOids) {
      scheduleKuaishouIndustrySendCallbackRetry(oid, 0, {
        source: 'worker_scan',
      })
    }
  } catch (error) {
    logIntegration(
      '[kuaishou-industry/send-code]',
      '扫描待重试电子凭证发货回调失败',
      {
        error: error instanceof Error ? error.message : String(error),
      },
      { level: 'warn' },
    )
  } finally {
    sendCallbackWorkerRunning = false
  }
}

function isVoucherDueForSendCallbackRetry(voucher: KuaishouIndustryVoucherRow) {
  if (isKuaishouIndustryVoucherSendCallbackSuccess(voucher)) {
    return false
  }

  const attemptCount = normalizePositiveInteger(voucher.send_callback_attempt_count)
  if (attemptCount >= SEND_CALLBACK_MAX_ATTEMPTS) {
    return false
  }

  const baseAt = voucher.send_callback_sent_at || voucher.created_at
  const baseTime = Date.parse(String(baseAt || ''))
  const elapsedMs = Date.now() - (Number.isFinite(baseTime) ? baseTime : 0)
  const requiredDelayMs =
    attemptCount === 0 ? SEND_CALLBACK_INITIAL_DELAY_MS : resolveSendCallbackBackoffMs(attemptCount)

  return elapsedMs >= requiredDelayMs
}

function resolveSendCallbackBackoffMs(attemptCount: unknown) {
  const attempt = Math.max(1, normalizePositiveInteger(attemptCount))
  return (
    SEND_CALLBACK_BACKOFF_MS[Math.min(attempt, SEND_CALLBACK_BACKOFF_MS.length - 1)] ||
    SEND_CALLBACK_BACKOFF_MS[SEND_CALLBACK_BACKOFF_MS.length - 1] ||
    SEND_CALLBACK_INITIAL_DELAY_MS
  )
}

async function syncOpen91OrderAfterSendCallbackSuccess(
  oid: string,
  { source = 'send_callback_success' }: { source?: string } = {},
) {
  const normalizedOid = String(oid || '').trim()
  if (!normalizedOid) {
    return
  }

  const order = await findLatestOrderByPlatformOrderId({
    provider: OPEN_91_PROVIDER,
    platform: OPEN_91_PLATFORM,
    platformOrderId: normalizedOid,
  })
  if (!order) {
    return
  }

  const tasks = await listTasksByOrderId(order.id)
  try {
    const result = await retryOpen91Order(order.id)
    const synchronizedTasks = result.tasks.length > 0 ? result.tasks : tasks
    if (synchronizedTasks.length > 0) {
      await bindKuaishouIndustryVouchersToOrderTasks(order, synchronizedTasks, {
        source,
        now: normalizeTimestampIso(new Date().toISOString()),
      })
    }
    logIntegration('[kuaishou-industry/send-code]', '电子凭证发货回调成功后已触发 91 订单重试', {
      source,
      oid: normalizedOid,
      orderId: order.id,
      taskCount: result.tasks.length,
      previousTaskCount: tasks.length,
    })
  } catch (error) {
    if (tasks.length > 0) {
      await bindKuaishouIndustryVouchersToOrderTasks(order, tasks, {
        source,
        now: normalizeTimestampIso(new Date().toISOString()),
      })
    }
    if (isOpen91OrderAwaitingFulfillmentConfig(error)) {
      return
    }
    logIntegration(
      '[kuaishou-industry/send-code]',
      '电子凭证发货回调成功后重试 91 订单失败',
      {
        source,
        oid: normalizedOid,
        orderId: order.id,
        error: error instanceof Error ? error.message : String(error),
      },
      { level: 'warn' },
    )
  }
}

function isOpen91OrderAwaitingFulfillmentConfig(error: unknown) {
  return Boolean(
    error &&
    typeof error === 'object' &&
    String((error as { errorCode?: unknown }).errorCode || '').trim() ===
      'open91_order_still_unconfigured',
  )
}

function isRetriableSendCallbackFailure(result: Awaited<ReturnType<typeof sendCallback>>) {
  if (result.success) {
    return false
  }

  if (String(result.error || '').trim()) {
    return true
  }

  const response = parseJsonObject(result.response)
  const marker = [
    response.result,
    response.code,
    response.sub_code,
    response.error_msg,
    response.sub_msg,
    response.msg,
  ]
    .map((item) => String(item || '').trim())
    .join(' ')

  return marker.includes('9994') || marker.includes('807000') || marker.includes('并发冲突')
}

async function sendAndRecordCallback(input: {
  oid: string
  sendType: string
  etickets: ReturnType<typeof buildIndustryEticketItem>[]
  vouchers: KuaishouIndustryVoucherRow[]
  sellerId: string
  token: string
  eticketType?: string
  ext?: string
  preferredTotalGoodsValue?: number
  source?: string
}) {
  const eticketItems = input.etickets.map((e) => ({
    id: String(e.id || ''),
    code: e.code,
    num: Number(e.num) || 1,
    validStartTime: Number(e.validStartTime) || 0,
    validEndTime: Number(e.validEndTime) || 0,
  }))
  const goodsValuePlan = resolveSendCallbackGoodsValuePlan(
    eticketItems,
    input.ext,
    input.preferredTotalGoodsValue,
  )
  const eticketItemsWithGoodsValue = eticketItems.map((item, index) => ({
    ...item,
    goodsValue: goodsValuePlan.goodsValues[index] || 1,
  }))
  const sendNum = eticketItems.reduce((sum, e) => sum + e.num, 0)
  const totalGoodsValue = goodsValuePlan.totalGoodsValue

  logIntegration('[kuaishou-industry/send-code]', '准备发起电子凭证发货回调', {
    source: input.source || 'send_code',
    oid: input.oid,
    sellerId: input.sellerId,
    sendType: input.sendType,
    sendNum,
    totalGoodsValue,
    goodsValueSource: goodsValuePlan.source,
    preferredTotalGoodsValue: normalizePositiveInteger(input.preferredTotalGoodsValue),
    etickets: eticketItemsWithGoodsValue,
    eticketType: input.eticketType || '',
  })

  let result: Awaited<ReturnType<typeof sendCallback>>
  try {
    result = await sendCallback({
      oid: input.oid,
      sendType: input.sendType,
      etickets: eticketItemsWithGoodsValue,
      sellerId: input.sellerId,
      sendNum,
      totalGoodsValue,
      token: input.token,
      ...(input.eticketType ? { eticketType: input.eticketType } : {}),
    })
  } catch (error) {
    result = {
      success: false,
      error: error instanceof Error ? error.message : String(error),
    }
  }

  const sentAt = normalizeTimestampIso(new Date().toISOString())
  await Promise.all(
    input.vouchers.map((voucher) =>
      updateKuaishouIndustryVoucherByCode(voucher.voucher_code, {
        sendCallbackStatus: result.success
          ? KUAISHOU_INDUSTRY_SEND_CALLBACK_STATUS.SUCCESS
          : KUAISHOU_INDUSTRY_SEND_CALLBACK_STATUS.FAILED,
        sendCallbackAttemptCount: normalizePositiveInteger(voucher.send_callback_attempt_count) + 1,
        sendCallbackLastError: result.success ? '' : resolveSendCallbackFailureMessage(result),
        sendCallbackResponseJson: result.response || {},
        sendCallbackSentAt: sentAt,
        updatedAt: sentAt,
      }),
    ),
  )

  if (!result.success) {
    logIntegration(
      '[kuaishou-industry/send-code]',
      '电子凭证发货回调执行失败，等待异步重试',
      {
        source: input.source || 'send_code',
        oid: input.oid,
        error: result.error || '',
        response: result.response || null,
      },
      { level: 'warn' },
    )
    return result
  }

  logIntegration('[kuaishou-industry/send-code]', '电子凭证发货回调执行完成', {
    source: input.source || 'send_code',
    oid: input.oid,
    response: result.response || null,
  })

  return result
}

function resolveSendCodeCallbackParams(
  voucher: KuaishouIndustryVoucherRow,
  body: JsonObject,
): SendCodeCallbackParams {
  return {
    oid: String(body.oid || voucher.oid || '').trim(),
    sendType: String(body.sendType || 'VIRTUAL').trim() || 'VIRTUAL',
    sellerId: String(body.sellerId || voucher.seller_id || '').trim(),
    token: String(body.token || voucher.token || '').trim(),
    eticketType: resolveKuaishouIndustryEticketType(voucher, body.eticketType),
    ext: String(body.ext || '').trim(),
  }
}

function resolveSendCallbackFailureMessage(result: Awaited<ReturnType<typeof sendCallback>>) {
  const error = String(result.error || '').trim()
  if (error) {
    return error
  }

  const response = parseJsonObject(result.response)
  const errorMsg = String(response.error_msg || response.message || response.msg || '').trim()
  if (errorMsg) {
    return errorMsg
  }

  const resultCode = String(response.result || response.code || '').trim()
  if (resultCode) {
    return `电子凭证发货回调失败，平台返回码：${resultCode}`
  }

  return '电子凭证发货回调失败'
}

export function resolveSendCallbackGoodsValuePlan(
  etickets: Array<{ goodsValue?: unknown; [key: string]: unknown }>,
  ext = '',
  preferredTotalGoodsValue: unknown = null,
) {
  const count = Math.max(etickets.length, 1)
  const preferredTotal = normalizePositiveInteger(preferredTotalGoodsValue)
  if (preferredTotal >= count) {
    return buildSplitGoodsValuePlan(preferredTotal, count, 'preferred')
  }

  const extTotal = resolveGoodsValueTotalFromExt(ext)
  if (extTotal >= count) {
    return buildSplitGoodsValuePlan(extTotal, count, 'ext')
  }

  const explicitGoodsValues = etickets
    .map((item) => normalizePositiveInteger(item.goodsValue))
    .filter((value) => value > 0)
  if (explicitGoodsValues.length === etickets.length && explicitGoodsValues.length > 0) {
    return {
      totalGoodsValue: explicitGoodsValues.reduce((sum, value) => sum + value, 0),
      goodsValues: explicitGoodsValues,
      source: 'eticket',
    }
  }

  const goodsValues = Array.from({ length: count }, () => 1)
  return {
    totalGoodsValue: count,
    goodsValues,
    source: 'fallback',
  }
}

export function resolveSendCallbackPreferredTotalGoodsValue(order: OrderRow | null): number {
  if (!order) {
    return 0
  }

  const rawPayload = parseJsonObject(order.raw_payload_json)
  const body = parseJsonObject(rawPayload.body)
  const maxAmountFen = normalizePositiveInteger(
    parseAmountToFen(body.maxAmount ?? rawPayload.maxAmount),
  )
  if (maxAmountFen > 0) {
    return maxAmountFen
  }

  return normalizePositiveInteger(order.total_amount)
}

function buildSplitGoodsValuePlan(totalGoodsValue: number, count: number, source: string) {
  const goodsValues = splitGoodsValue(totalGoodsValue, count)
  return {
    totalGoodsValue: goodsValues.reduce((sum, value) => sum + value, 0),
    goodsValues,
    source,
  }
}

function splitGoodsValue(totalGoodsValue: number, count: number): number[] {
  const base = Math.floor(totalGoodsValue / count)
  if (base <= 0) {
    return Array.from({ length: count }, () => 1)
  }

  return Array.from({ length: count }, (_item, index) =>
    index === count - 1 ? totalGoodsValue - base * (count - 1) : base,
  )
}

function resolveGoodsValueTotalFromExt(ext: unknown): number {
  const parsed = parseJsonObject(ext)
  return normalizePositiveInteger(
    parsed.totalGoodsValue ??
      parsed.goodsValue ??
      parsed.payment ??
      parsed.payAmount ??
      parsed.amount,
  )
}

function normalizePositiveInteger(value: unknown): number {
  const parsed = Number(value)
  return Number.isFinite(parsed) && parsed > 0 ? Math.trunc(parsed) : 0
}

function resolveSendCodePaymentFen(ext: unknown): number {
  const parsed = parseJsonObject(ext)
  return normalizePositiveInteger(
    parsed.payment ??
      parsed.totalGoodsValue ??
      parsed.goodsValue ??
      parsed.payAmount ??
      parsed.amount,
  )
}

function parseJsonObject(value: unknown): JsonObject {
  if (value && typeof value === 'object' && !Array.isArray(value)) {
    return value as JsonObject
  }

  try {
    const parsed = JSON.parse(String(value || '{}'))
    return asJsonObject(parsed)
  } catch {
    return {}
  }
}
