import { findLatestOrderByPlatformOrderId } from '../../repositories/order-repo.js'
import { listKuaishouIndustryVouchersByOid } from '../../repositories/kuaishou-industry-voucher-repo.js'
import { listTasksByOrderId } from '../../repositories/task-repo.js'
import { resolveTaskDeliveryLink } from '../fulfillment/delivery-link-service.js'
import { logIntegration } from '../../utils/logger.js'
import { asJsonObject, type JsonObject } from '../../types/json.js'
import {
  OPEN_91_MANUAL_FAILED_STATUS,
  OPEN_91_PENDING_CONFIG_STATUS,
} from '../platforms/ninetyone/order-service.js'
import {
  isKuaishouIndustryVoucherSendCallbackSuccess,
  resolveKuaishouIndustryVoucherSendCallbackMessage,
} from '../platforms/kuaishou-industry/voucher-service.js'
import {
  assertOpen91Config,
  OPEN_91_DEFAULT_FAIL_CODE,
  OPEN_91_PLATFORM,
  OPEN_91_PROVIDER,
} from './config.js'
import { consumeIndustryVouchersBeforeOpen91Deliver } from './consume-on-deliver.js'
import {
  assertOpen91QueryPayload,
  assertOpen91Timestamp,
  normalizeOpen91QueryPayload,
} from './payload.js'
import { assertOpen91Signature, buildOpen91Cards } from './crypto.js'
import {
  buildOpen91CardItem,
  buildOpen91OrderCost,
  buildOpen91OutTradeNo,
  buildOpen91SuccessResponse,
  resolveOpen91QueryState,
} from './response.js'
import type { KuaishouIndustryVoucherRow, OrderRow, TaskRow } from '../../types/repository/rows.js'

export async function queryOpen91Order(payload: JsonObject = {}, { requestId = '' } = {}) {
  const config = assertOpen91Config()
  const normalized = normalizeOpen91QueryPayload(payload)

  assertOpen91QueryPayload(normalized, config)
  assertOpen91Timestamp(normalized.timestamp, config.timestampToleranceSeconds)
  assertOpen91Signature(payload, config)

  const order = await findLatestOrderByPlatformOrderId({
    provider: OPEN_91_PROVIDER,
    platform: OPEN_91_PLATFORM,
    platformOrderId: normalized.orderNo,
  })

  if (!order) {
    return buildOpen91SuccessResponse({
      orderNo: normalized.orderNo,
      outTradeNo: '',
      orderStatus: 30,
      failCode: OPEN_91_DEFAULT_FAIL_CODE,
      failReason: '订单不存在',
    })
  }

  const tasks = await listTasksByOrderId(order.id)
  const industryVoucherState = await resolveOpen91IndustryVoucherState(order, tasks)

  if (tasks.length === 0) {
    if (String(order.order_status || '').trim() === OPEN_91_PENDING_CONFIG_STATUS) {
      return buildOpen91SuccessResponse({
        orderNo: normalized.orderNo,
        outTradeNo: buildOpen91OutTradeNo(order),
        orderStatus: 10,
        failCode: 0,
        failReason: '',
        orderCost: buildOpen91OrderCost(0),
        cards: '',
      })
    }

    if (String(order.order_status || '').trim() === OPEN_91_MANUAL_FAILED_STATUS) {
      return buildOpen91SuccessResponse({
        orderNo: normalized.orderNo,
        outTradeNo: buildOpen91OutTradeNo(order),
        orderStatus: 30,
        failCode: OPEN_91_DEFAULT_FAIL_CODE,
        failReason: resolveOpen91OrderFailReason(order) || '商家手动标记无法履约',
      })
    }

    if (industryVoucherState.voucherCount > 0) {
      return buildOpen91SuccessResponse({
        orderNo: normalized.orderNo,
        outTradeNo: buildOpen91OutTradeNo(order),
        orderStatus: 10,
        failCode: 0,
        failReason: '',
        orderCost: buildOpen91OrderCost(0),
        cards: '',
      })
    }
  }

  const cardItems = []
  const readyTaskIds = []
  const industryReadyTaskIds = new Set(industryVoucherState.readyTaskIds)

  for (const task of tasks) {
    const deliveryLink = await resolveTaskDeliveryLink(task)
    const claimUrl = String(deliveryLink?.claimUrl || '').trim()

    if (!claimUrl) {
      continue
    }

    if (!industryReadyTaskIds.has(Number(task.id))) {
      continue
    }

    readyTaskIds.push(Number(task.id))
    cardItems.push(
      buildOpen91CardItem({
        claimUrl,
        expireTime: deliveryLink?.expireTime || '',
      }),
    )
  }

  const queryState = resolveOpen91QueryState({
    tasks,
    readyTaskIds,
  })

  logIntegration('[open-91/query]', '91卡券订单查询已处理', {
    requestId,
    orderNo: normalized.orderNo,
    orderId: order.id,
    taskCount: tasks.length,
    readyTaskCount: readyTaskIds.length,
    voucherCount: industryVoucherState.voucherCount,
    voucherReadyTaskCount: industryVoucherState.readyTaskIds.length,
    voucherPendingReason: industryVoucherState.pendingReason,
    orderStatus: queryState.orderStatus,
  })

  if (queryState.orderStatus === 30) {
    return buildOpen91SuccessResponse({
      orderNo: normalized.orderNo,
      outTradeNo: buildOpen91OutTradeNo(order),
      orderStatus: 30,
      failCode: queryState.failCode,
      failReason: queryState.failReason,
    })
  }

  if (queryState.orderStatus === 10) {
    return buildOpen91SuccessResponse({
      orderNo: normalized.orderNo,
      outTradeNo: buildOpen91OutTradeNo(order),
      orderStatus: 10,
      failCode: 0,
      failReason: '',
      orderCost: buildOpen91OrderCost(0),
      cards: '',
    })
  }

  // 即将交付 cards：先同步核销行业电子凭证，成功后再返回 20，避免未核销发链导致误退款。
  const deliverConsume = await consumeIndustryVouchersBeforeOpen91Deliver({
    order,
    tasks,
    readyTaskIds,
    requestId,
  })

  if (!deliverConsume.ok) {
    logIntegration('[open-91/query]', '91卡券订单查询因交付前核销失败返回处理中', {
      requestId,
      orderNo: normalized.orderNo,
      orderId: order.id,
      readyTaskCount: readyTaskIds.length,
      failedTaskIds: deliverConsume.failedTaskIds,
      errorMessage: deliverConsume.errorMessage,
    })

    return buildOpen91SuccessResponse({
      orderNo: normalized.orderNo,
      outTradeNo: buildOpen91OutTradeNo(order),
      orderStatus: 10,
      failCode: 0,
      failReason: '',
      orderCost: buildOpen91OrderCost(0),
      cards: '',
    })
  }

  const outTradeNo = buildOpen91OutTradeNo(order)
  const encryptedCards = buildOpen91Cards(cardItems, config)
  const responseData = {
    orderNo: normalized.orderNo,
    outTradeNo,
    orderStatus: 20,
    failCode: 0,
    failReason: '',
    orderCost: buildOpen91OrderCost(0),
    cards: encryptedCards,
  }

  logIntegration('[open-91/query]', '91卡券订单查询返回 cards 已生成', {
    requestId,
    orderNo: normalized.orderNo,
    orderId: order.id,
    outTradeNo,
    cardsEncoding: config.cardsEncoding,
    cardsPlain: cardItems,
    cardsEncrypted: encryptedCards,
    deliverConsumedTaskIds: deliverConsume.consumedTaskIds,
    deliverAlreadyConsumedTaskIds: deliverConsume.alreadyConsumedTaskIds,
    responseData,
  })

  return buildOpen91SuccessResponse(responseData)
}

function resolveOpen91OrderFailReason(order: OrderRow) {
  const payload = parseJsonObject(order?.raw_payload_json)
  return String(payload.manualFailedReason || '').trim()
}

async function resolveOpen91IndustryVoucherState(order: OrderRow, tasks: TaskRow[]) {
  const vouchers = await listKuaishouIndustryVouchersByOid(order.platform_order_id)
  const voucherByTaskId = new Map<number, KuaishouIndustryVoucherRow>()
  const voucherByUnitIndex = new Map<number, KuaishouIndustryVoucherRow>()

  for (const voucher of vouchers) {
    const taskId = Number(voucher.task_id || 0)
    const unitIndex = Number(voucher.unit_index || 0)
    if (taskId > 0 && !voucherByTaskId.has(taskId)) {
      voucherByTaskId.set(taskId, voucher)
    }
    if (unitIndex > 0 && !voucherByUnitIndex.has(unitIndex)) {
      voucherByUnitIndex.set(unitIndex, voucher)
    }
  }

  const readyTaskIds: number[] = []
  let pendingReason = ''

  for (const task of tasks) {
    const taskId = Number(task.id || 0)
    const unitIndex = Number(task.unit_index || 0)
    const voucher = voucherByTaskId.get(taskId) || voucherByUnitIndex.get(unitIndex) || null

    if (!voucher) {
      pendingReason = pendingReason || '电子凭证发码通知尚未完成'
      continue
    }

    if (!isKuaishouIndustryVoucherSendCallbackSuccess(voucher)) {
      pendingReason = pendingReason || resolveKuaishouIndustryVoucherSendCallbackMessage(voucher)
      continue
    }

    readyTaskIds.push(taskId)
  }

  return {
    voucherCount: vouchers.length,
    readyTaskIds,
    pendingReason,
  }
}

function parseJsonObject(value: unknown): JsonObject {
  if (!value) {
    return {}
  }

  if (typeof value === 'object' && !Array.isArray(value)) {
    return value
  }

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