/**
 * 快手 send-code 数据接入发单平台（工单侧）。
 *
 * 定位：91 回调是订单骨架权威源，快手 send-code 是数据补全源与兜底源。
 * - 订单已存在（91 先到）：回填 shop_id（91 的 productNo 无店铺后缀时）、
 *   补建缺失工单、把凭证信息回填已建工单 material_json
 * - 订单不存在（91 未到/缺失）：用快手数据兜底建单 + 建工单 + 凭证回填
 *
 * 幂等依据：orders 唯一键 provider+platform+shop_id+platform_order_id
 * （由 91 侧查重逻辑保证同 oid 单条记录）、work_orders.order_item_id 唯一索引、
 * listWorkOrdersByPlatformOrderId 查重。
 *
 * 本服务只写 orders / order_items / work_orders，不触碰
 * upsertOrderFromSource / syncDeliveryTasksForOrder / readiness / 回调链路。
 */

import {
  createOrder,
  findLatestOrderByPlatformOrderId,
  updateOrder,
} from '../../repositories/order-repo.js'
import { listOrderItemsByOrderId, replaceOrderItems } from '../../repositories/order-item-repo.js'
import {
  listWorkOrdersByPlatformOrderId,
  updateWorkOrder,
} from '../../repositories/worker-platform/work-order-repo.js'
import { syncWorkerOrdersForSourceOrder } from './admin-service.js'
import { createWorkOrderEvent } from '../../repositories/worker-platform/work-order-repo.js'
import { OPEN_91_PLATFORM, OPEN_91_PROVIDER } from '../open-91/config.js'
import { asJsonObject, type JsonObject } from '../../types/json.js'
import type { OrderUpdateInput } from '../../types/repository/inputs.js'
import type {
  KuaishouIndustryVoucherRow,
  OrderRow,
} from '../../types/repository/rows.js'

const KUAISHOU_SEND_CODE_SOURCE = 'kuaishou_send_code'
const KUAISHOU_SEND_CODE_ORDER_STATUS = 'paid'

export type SyncWorkOrdersFromSendCodeInput = {
  oid: string
  sellerId: string
  itemId: string
  itemTitle: string
  skuId: string
  num: number
  paymentFen: number
  rawParams: JsonObject
  vouchers: KuaishouIndustryVoucherRow[]
  now: string
}

export type SyncWorkOrdersFromSendCodeResult = {
  order: OrderRow | null
  orderId: number | null
  workOrderIds: number[]
  createdWorkOrderCount: number
  backfilledVoucherCount: number
  skipped: string[]
}

export async function syncWorkOrdersFromKuaishouSendCode(
  input: SyncWorkOrdersFromSendCodeInput,
): Promise<SyncWorkOrdersFromSendCodeResult> {
  const normalizedOid = String(input.oid || '').trim()
  const skipped: string[] = []

  if (!normalizedOid) {
    return {
      order: null,
      orderId: null,
      workOrderIds: [],
      createdWorkOrderCount: 0,
      backfilledVoucherCount: 0,
      skipped: ['missing_oid'],
    }
  }

  let order = await findLatestOrderByPlatformOrderId({
    provider: OPEN_91_PROVIDER,
    platform: OPEN_91_PLATFORM,
    platformOrderId: normalizedOid,
  })

  if (order) {
    const orderResult = await backfillOrderShopId(order, input)
    order = orderResult.order
    if (orderResult.skipped) {
      skipped.push(orderResult.skipped)
    }
  } else {
    const created = await createFallbackOrder(input)
    if (created.order) {
      order = created.order
    } else {
      skipped.push(created.reason || 'order_create_failed')
    }
  }

  const workOrderIds: number[] = []
  let createdWorkOrderCount = 0

  if (order) {
    const orderItems = await listOrderItemsByOrderId(order.id)

    const syncResult = await syncWorkerOrdersForSourceOrder(order, orderItems, {
      source: KUAISHOU_SEND_CODE_SOURCE,
      autoOnly: true,
    })
    createdWorkOrderCount = syncResult.createdCount
    for (const item of syncResult.skipped) {
      skipped.push(`work_order:${item.reason}`)
    }
  }

  const backfilled = await backfillVouchersToWorkOrders(normalizedOid, input.vouchers, input.now)
  for (const workOrderId of backfilled.workOrderIds) {
    workOrderIds.push(workOrderId)
  }
  if (backfilled.skipped) {
    skipped.push(backfilled.skipped)
  }

  return {
    order,
    orderId: order?.id ?? null,
    workOrderIds,
    createdWorkOrderCount,
    backfilledVoucherCount: backfilled.count,
    skipped,
  }
}

async function backfillOrderShopId(
  order: OrderRow,
  input: SyncWorkOrdersFromSendCodeInput,
): Promise<{ order: OrderRow; skipped?: string }> {
  const sellerId = String(input.sellerId || '').trim()
  const currentShopId = String(order.shop_id || '').trim()

  if (!sellerId || currentShopId === sellerId) {
    return { order }
  }

  const isPlaceholderShopId = !currentShopId || currentShopId === OPEN_91_PROVIDER

  if (!isPlaceholderShopId) {
    return { order, skipped: `shop_id_conflict:${currentShopId}` }
  }

  const updated = await updateOrder(order.id, {
    ...buildOrderUpdateBase(order),
    shopId: sellerId,
    updatedAt: input.now,
  })

  return {
    order: updated || order,
  }
}

function buildOrderUpdateBase(order: OrderRow): Omit<OrderUpdateInput, 'updatedAt'> {
  return {
    provider: String(order.provider || ''),
    platform: String(order.platform || ''),
    shopId: String(order.shop_id || ''),
    shopName: String(order.shop_name || ''),
    platformOrderId: String(order.platform_order_id || ''),
    orderStatus: String(order.order_status || ''),
    payStatus: String(order.pay_status || ''),
    buyerId: String(order.buyer_id || ''),
    buyerName: String(order.buyer_name || ''),
    receiverContact: String(order.receiver_contact || ''),
    totalAmount: Number(order.total_amount) || 0,
    currency: String(order.currency || 'CNY'),
    rawPayloadJson: order.raw_payload_json || '{}',
    paidAt: order.paid_at || null,
  }
}

async function createFallbackOrder(input: SyncWorkOrdersFromSendCodeInput): Promise<{
  order: OrderRow | null
  reason?: string
}> {
  const now = input.now
  const sellerId = String(input.sellerId || '').trim()
  const itemId = String(input.itemId || '').trim()
  const itemTitle = String(input.itemTitle || '').trim()
  const num = Math.max(1, Number(input.num) || 1)
  const paymentFen = Math.max(0, Number(input.paymentFen) || 0)

  if (!itemId && !itemTitle) {
    return { order: null, reason: 'order_item_missing' }
  }

  const order = await createOrder({
    provider: OPEN_91_PROVIDER,
    platform: OPEN_91_PLATFORM,
    shopId: sellerId,
    shopName: sellerId ? `快手店铺-${sellerId}` : '',
    platformOrderId: input.oid,
    orderStatus: KUAISHOU_SEND_CODE_ORDER_STATUS,
    payStatus: 'paid',
    buyerId: '',
    buyerName: '',
    receiverContact: '',
    totalAmount: paymentFen,
    currency: 'CNY',
    rawPayloadJson: {
      source: KUAISHOU_SEND_CODE_SOURCE,
      receivedAt: now,
      body: input.rawParams,
    },
    paidAt: now,
    createdAt: now,
    updatedAt: now,
  })

  if (!order) {
    return { order: null, reason: 'order_create_failed' }
  }

  await replaceOrderItems(order.id, [
    {
      skuCode: itemId,
      skuName: itemTitle,
      quantity: num,
      specJson: JSON.stringify({
        sellerId,
        skuId: String(input.skuId || '').trim(),
        paymentFen,
        source: KUAISHOU_SEND_CODE_SOURCE,
      }),
      itemSnapshotJson: JSON.stringify({
        source: KUAISHOU_SEND_CODE_SOURCE,
        params: input.rawParams,
      }),
      createdAt: now,
      updatedAt: now,
    },
  ])

  return { order }
}

async function backfillVouchersToWorkOrders(
  oid: string,
  vouchers: KuaishouIndustryVoucherRow[],
  now: string,
): Promise<{ workOrderIds: number[]; count: number; skipped?: string }> {
  const workOrders = await listWorkOrdersByPlatformOrderId(oid)
  if (workOrders.length === 0) {
    return { workOrderIds: [], count: 0, skipped: 'work_order_not_found' }
  }

  const voucherItems = vouchers.map((voucher) => ({
    voucherCode: String(voucher.voucher_code || ''),
    token: String(voucher.token || ''),
    eticketType: String(voucher.eticket_type || ''),
    status: String(voucher.status || ''),
    validStartTime: Number(voucher.valid_start_time) || 0,
    validEndTime: Number(voucher.valid_end_time) || 0,
  }))

  const workOrderIds: number[] = []
  let count = 0

  for (const workOrder of workOrders) {
    const material = asJsonObject(safeParseJson(workOrder.material_json))
    const existing = Array.isArray(material.kuaishouIndustryVoucher)
      ? (material.kuaishouIndustryVoucher as unknown[])
      : []
    const existingCodes = new Set(
      existing.map((item) =>
        String((item as JsonObject)?.voucherCode || (item as JsonObject)?.code || ''),
      ),
    )
    const merged = [
      ...existing,
      ...voucherItems.filter((item) => !existingCodes.has(item.voucherCode)),
    ]

    material.kuaishouIndustryVoucher = merged

    const updated = await updateWorkOrder(workOrder.id, {
      material_json: JSON.stringify(material),
      updated_at: now,
    })

    if (!updated) {
      continue
    }

    await createWorkOrderEvent({
      workOrderId: workOrder.id,
      actorType: 'system',
      actorId: KUAISHOU_SEND_CODE_SOURCE,
      eventType: 'voucher_backfilled',
      fromStatus: workOrder.status,
      toStatus: workOrder.status,
      payloadJson: JSON.stringify({
        oid,
        voucherCount: voucherItems.length,
      }),
      now,
    })

    workOrderIds.push(Number(workOrder.id))
    count += 1
  }

  return { workOrderIds, count }
}

function safeParseJson(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 {}
  }
}
