import { updateTask } from '../../../repositories/task-repo.js'
import type { JsonObject } from '../../../types/json.js'
import {
  listKuaishouIndustryVouchersByOid,
  updateKuaishouIndustryVoucherByCode,
} from '../../../repositories/kuaishou-industry-voucher-repo.js'
import { normalizeTimestampIso } from '../../../utils/time.js'
import { parseTaskContext } from '../../../utils/task-json.js'
import { normalizeKuaishouCloudFlow } from '../../fulfillment/kuaishou-cloud/domain.js'
import {
  isKuaishouIndustryVoucherSendCallbackSuccess,
  normalizeKuaishouIndustrySendCallbackStatus,
  resolveKuaishouIndustryVoucherSendCallbackMessage,
} from './voucher-service.js'
import type {
  KuaishouIndustryVoucherRow,
  OrderRow,
  TaskRow,
} from '../../../types/repository/rows.js'

export async function bindKuaishouIndustryVouchersToOrderTasks(
  order: OrderRow | null | undefined,
  tasks: TaskRow[] = [],
  options: {
    source?: string
    now?: string
  } = {},
) {
  const oid = String(order?.platform_order_id || '').trim()
  if (!order || !oid) {
    return []
  }

  const now = normalizeTimestampIso(options.now || new Date().toISOString())
  const vouchers = await listKuaishouIndustryVouchersByOid(oid)
  const bound: KuaishouIndustryVoucherRow[] = []

  for (const voucher of vouchers) {
    const task = resolveTaskForVoucher(voucher, tasks)
    const nextVoucher = await updateKuaishouIndustryVoucherByCode(voucher.voucher_code, {
      orderId: order.id,
      ...(task ? { taskId: task.id } : {}),
      updatedAt: now,
    })
    const currentVoucher = nextVoucher || voucher
    bound.push(currentVoucher)

    if (task && isKuaishouIndustryVoucherSendCallbackSuccess(currentVoucher)) {
      await attachKuaishouIndustryVoucherToTask(task, currentVoucher, {
        source: options.source || 'voucher_bind',
        now,
      })
    }
  }

  return bound
}

export async function attachKuaishouIndustryVoucherToTask(
  task: TaskRow,
  voucher: KuaishouIndustryVoucherRow,
  options: {
    source?: string
    now?: string
  } = {},
) {
  const now = normalizeTimestampIso(options.now || new Date().toISOString())
  const context = parseTaskContext(task)
  const nextVoucherContext = buildKuaishouIndustryVoucherContext(
    voucher,
    context.kuaishouIndustryVoucher,
    now,
  )
  const sendCallbackConfirmed = isKuaishouIndustryVoucherSendCallbackSuccess(voucher)
  const nextContext: JsonObject = {
    ...context,
    kuaishouIndustryVoucher: nextVoucherContext,
  }

  if (
    sendCallbackConfirmed &&
    (String(task.executor_key || '').trim() === 'kuaishou_ct_assisted' ||
      context.kuaishouCloudFulfillment)
  ) {
    const flow = normalizeKuaishouCloudFlow(context.kuaishouCloudFulfillment)
    const consumedAt = voucher.consumed_at || nextVoucherContext.consumedAt || null
    const status = String(voucher.status || 'UNUSED')
      .trim()
      .toUpperCase()

    nextContext.kuaishouCloudFulfillment = {
      ...flow,
      ticket: {
        ...flow.ticket,
        code: String(voucher.voucher_code || '').trim(),
        status: status === 'DESTROYED' ? 'destroyed' : 'verified',
        capturedAt: flow.ticket.capturedAt || now,
        capturedBy: flow.ticket.capturedBy || {
          source: options.source || 'kuaishou_industry_voucher',
        },
        verifiedAt: flow.ticket.verifiedAt || now,
        oid: String(voucher.oid || task.platform_order_id || '').trim(),
        formToken: String(voucher.token || '').trim(),
        leftCount: status === 'CONSUMED' || status === 'DESTROYED' ? 0 : 1,
        goodsTitle: flow.ticket.goodsTitle || task.sku_name || task.sku_code || '',
      },
      consume: {
        ...flow.consume,
        status: status === 'CONSUMED' ? 'success' : flow.consume.status,
        autoConsumeEnabled: true,
        consumedAt: status === 'CONSUMED' ? consumedAt : flow.consume.consumedAt,
        errorMessage: '',
      },
    }
  }

  if (JSON.stringify(context) === JSON.stringify(nextContext)) {
    return task
  }

  return updateTask(task.id, {
    context_json: JSON.stringify(nextContext),
    updated_at: now,
  })
}

function resolveTaskForVoucher(voucher: KuaishouIndustryVoucherRow, tasks: TaskRow[]) {
  const unitIndex = Number(voucher.unit_index || 0)
  if (unitIndex > 0) {
    const matched = tasks.find((task) => Number(task.unit_index || 0) === unitIndex)
    if (matched) {
      return matched
    }
  }

  return tasks[unitIndex - 1] || null
}

export function buildKuaishouIndustryVoucherContext(
  voucher: KuaishouIndustryVoucherRow,
  existingValue: unknown,
  now: string,
) {
  const existing =
    existingValue && typeof existingValue === 'object' && !Array.isArray(existingValue)
      ? (existingValue as JsonObject)
      : {}
  const status = String(voucher.status || 'UNUSED')
    .trim()
    .toUpperCase()

  return {
    ...existing,
    oid: String(voucher.oid || '').trim(),
    token: String(voucher.token || '').trim(),
    eticketId: String(voucher.voucher_code || '').trim(),
    voucherCode: String(voucher.voucher_code || '').trim(),
    unitIndex: Number(voucher.unit_index || 0) || 0,
    status,
    sendCallbackStatus: normalizeKuaishouIndustrySendCallbackStatus(voucher.send_callback_status),
    sendCallbackLastError: resolveKuaishouIndustryVoucherSendCallbackMessage(voucher),
    sendCallbackAttemptCount: Number(voucher.send_callback_attempt_count || 0) || 0,
    sendCallbackSentAt: voucher.send_callback_sent_at || existing.sendCallbackSentAt || null,
    validStartTime: Number(voucher.valid_start_time || 0) || 0,
    validEndTime: Number(voucher.valid_end_time || 0) || 0,
    verifiedAt: existing.verifiedAt || now,
    consumedAt: voucher.consumed_at || existing.consumedAt || null,
    destroyedAt: voucher.destroyed_at || existing.destroyedAt || null,
  }
}
