/**
 * 91 卡券交付前核销：
 * 在查询接口即将返回 orderStatus=20 + cards 前，同步核销行业电子凭证，
 * 把「核销时间」提前到链接交付时刻，降低「拿链即退」误退窗口。
 *
 * 语义：核销 = 领取链接已交付（售出闭环），≠ 游戏内道具已到账。
 *
 * 交付后会 best-effort 自动准备 Cloud 绑定资源（取号/绑链），避免
 * 「已核销却停在待准备资源」只能靠后台手动点「准备资源」。
 */
import { attachKuaishouIndustryVoucherToTask } from '../platforms/kuaishou-industry/voucher-binding-service.js'
import { consumeKuaishouIndustryVoucher } from '../platforms/kuaishou-industry/voucher-service.js'
import { prepareFulfillmentBinding } from '../fulfillment/executors/registry.js'
import { normalizeKuaishouCloudFlow } from '../fulfillment/kuaishou-cloud/index.js'
import { listKuaishouIndustryVouchersByOid } from '../../repositories/kuaishou-industry-voucher-repo.js'
import { logIntegration, logWarn } from '../../utils/logger.js'
import { parseTaskContext } from '../../utils/task-json.js'
import type { KuaishouIndustryVoucherRow, OrderRow, TaskRow } from '../../types/repository/rows.js'

export const OPEN_91_DELIVER_CONSUME_SOURCE = 'open91_query_deliver'

export type Open91DeliverConsumeResult =
  | {
      ok: true
      consumedTaskIds: number[]
      alreadyConsumedTaskIds: number[]
    }
  | {
      ok: false
      errorMessage: string
      failedTaskIds: number[]
      consumedTaskIds: number[]
      alreadyConsumedTaskIds: number[]
    }

/**
 * 按 task_id / unit_index 解析任务对应的行业电子凭证（与 91 查询就绪判定一致）。
 */
export function resolveIndustryVoucherForTask(
  task: Pick<TaskRow, 'id' | 'unit_index'>,
  vouchers: KuaishouIndustryVoucherRow[],
): KuaishouIndustryVoucherRow | null {
  const taskId = Number(task.id || 0)
  const unitIndex = Number(task.unit_index || 0)

  if (taskId > 0) {
    const byTaskId = vouchers.find((row) => Number(row.task_id || 0) === taskId)
    if (byTaskId) {
      return byTaskId
    }
  }

  if (unitIndex > 0) {
    const byUnit = vouchers.find((row) => Number(row.unit_index || 0) === unitIndex)
    if (byUnit) {
      return byUnit
    }
  }

  return null
}

function isVoucherConsumed(voucher: Pick<KuaishouIndustryVoucherRow, 'status'>): boolean {
  return (
    String(voucher.status || '')
      .trim()
      .toUpperCase() === 'CONSUMED'
  )
}

/**
 * 对即将交付给 91 的 ready 任务同步核销行业凭证（幂等）。
 * 失败时调用方应返回 orderStatus=10，避免「未核销却已发链」。
 */
export async function consumeIndustryVouchersBeforeOpen91Deliver(options: {
  order: OrderRow
  tasks: TaskRow[]
  readyTaskIds: number[]
  requestId?: string
  source?: string
}): Promise<Open91DeliverConsumeResult> {
  const source =
    String(options.source || OPEN_91_DELIVER_CONSUME_SOURCE).trim() ||
    OPEN_91_DELIVER_CONSUME_SOURCE
  const readySet = new Set(
    (Array.isArray(options.readyTaskIds) ? options.readyTaskIds : [])
      .map((id) => Number(id))
      .filter((id) => id > 0),
  )
  const readyTasks = (Array.isArray(options.tasks) ? options.tasks : []).filter((task) =>
    readySet.has(Number(task.id || 0)),
  )

  if (readyTasks.length === 0) {
    return {
      ok: true,
      consumedTaskIds: [],
      alreadyConsumedTaskIds: [],
    }
  }

  const oid = String(options.order.platform_order_id || '').trim()
  const vouchers = oid ? await listKuaishouIndustryVouchersByOid(oid) : []
  const consumedTaskIds: number[] = []
  const alreadyConsumedTaskIds: number[] = []
  const failed: Array<{ taskId: number; errorMessage: string }> = []

  for (const task of readyTasks) {
    const taskId = Number(task.id || 0)
    const voucher = resolveIndustryVoucherForTask(task, vouchers)

    if (!voucher) {
      failed.push({
        taskId,
        errorMessage: '交付前核销失败：未找到对应电子凭证',
      })
      continue
    }

    const alreadyConsumed = isVoucherConsumed(voucher)
    const result = await consumeKuaishouIndustryVoucher(voucher, {
      source,
      task,
      token: String(voucher.token || '').trim(),
      consumeTime: Date.now(),
    })

    if (!result.ok || !result.voucher) {
      failed.push({
        taskId,
        errorMessage: result.errorMessage || '电子凭证核销回调失败',
      })
      continue
    }

    const attachedTask =
      (await attachKuaishouIndustryVoucherToTask(task, result.voucher, {
        source,
      })) || task

    // 核销后立刻补准备绑定资源；失败不阻断 cards（领取页仍会再兜底 prepare）
    await ensureBindingPreparedAfterDeliver({
      task: attachedTask,
      source,
      requestId: options.requestId || '',
      orderId: options.order.id,
      orderNo: oid,
    })

    if (alreadyConsumed) {
      alreadyConsumedTaskIds.push(taskId)
    } else {
      consumedTaskIds.push(taskId)
    }
  }

  if (failed.length > 0) {
    const errorMessage = failed[0]?.errorMessage || '电子凭证核销失败，暂缓交付领取链接'
    logWarn('[open-91/query]', '91交付前核销失败，暂不返回 cards', {
      requestId: options.requestId || '',
      orderId: options.order.id,
      orderNo: oid,
      failedTaskIds: failed.map((item) => item.taskId),
      failed,
      consumedTaskIds,
      alreadyConsumedTaskIds,
      errorMessage,
    })

    return {
      ok: false,
      errorMessage,
      failedTaskIds: failed.map((item) => item.taskId),
      consumedTaskIds,
      alreadyConsumedTaskIds,
    }
  }

  logIntegration('[open-91/query]', '91交付前核销完成', {
    requestId: options.requestId || '',
    orderId: options.order.id,
    orderNo: oid,
    readyTaskCount: readyTasks.length,
    consumedTaskIds,
    alreadyConsumedTaskIds,
    source,
  })

  return {
    ok: true,
    consumedTaskIds,
    alreadyConsumedTaskIds,
  }
}

async function ensureBindingPreparedAfterDeliver(options: {
  task: TaskRow
  source: string
  requestId: string
  orderId: number
  orderNo: string
}) {
  const executorKey = String(options.task.executor_key || '').trim()
  // lewan / 行业凭证任务才需要 Cloud 绑定资源
  if (
    executorKey !== 'kuaishou_ct_assisted' &&
    executorKey !== 'kuaishou-industry' &&
    !parseTaskContext(options.task).kuaishouCloudFulfillment
  ) {
    return
  }

  const flow = normalizeKuaishouCloudFlow(parseTaskContext(options.task).kuaishouCloudFulfillment)
  if (flow.binding.prepareStatus === 'ready' && String(flow.binding.bindUrl || '').trim()) {
    return
  }

  try {
    await prepareFulfillmentBinding(options.task, {
      source: `${options.source}_prepare_binding`,
      actor: { source: options.source },
    })
    logIntegration('[open-91/query]', '91交付后自动准备绑定资源成功', {
      requestId: options.requestId,
      orderId: options.orderId,
      orderNo: options.orderNo,
      taskId: options.task.id,
      source: options.source,
    })
  } catch (error) {
    logWarn('[open-91/query]', '91交付后自动准备绑定资源失败（不阻断 cards，领取页将再试）', {
      requestId: options.requestId,
      orderId: options.orderId,
      orderNo: options.orderNo,
      taskId: options.task.id,
      error: error instanceof Error ? error.message : String(error || ''),
    })
  }
}
