import assert from 'node:assert/strict'
import test from 'node:test'

import type { WorkOrderRow } from '../../repositories/worker-platform/index.js'
import type { KuaishouIndustryVoucherRow, TaskRow } from '../../types/repository/rows.js'
import {
  consumeIndustryVouchersBeforeWorkOrderAssign,
  consumeIndustryVouchersBeforeWorkOrderPublish,
  resolveWorkOrderVoucherTargets,
} from './publish-voucher-service.js'

function buildWorkOrder(overrides: Partial<WorkOrderRow> = {}): WorkOrderRow {
  return {
    id: 1,
    work_order_no: 'WO001',
    order_id: 10,
    order_item_id: 20,
    task_id: null,
    platform_order_id: 'OID001',
    product_name: '测试商品',
    category_id: null,
    status: 'unassigned',
    reward_amount: 100,
    required_deposit_amount: 0,
    deposit_threshold_amount: 20000,
    assigned_worker_id: null,
    last_assigned_worker_id: null,
    material_json: '{}',
    requirement_json: '{}',
    acceptance_json: '{}',
    draft_acceptance_json: '{}',
    problem_note: '',
    sharing_enabled: false,
    sharing_total_quantity: 1,
    sharing_unit_reward: 0,
    published_at: null,
    hall_queued_at: null,
    pinned_at: null,
    assigned_at: null,
    submitted_at: null,
    accepted_at: null,
    deadline_at: null,
    timeout_minutes: 0,
    timeout_policy: 'reopen',
    created_at: '2026-08-16T00:00:00.000Z',
    updated_at: '2026-08-16T00:00:00.000Z',
    ...overrides,
  }
}

function buildTask(id: number, orderItemId: number): TaskRow {
  return {
    id,
    order_id: 10,
    order_item_id: orderItemId,
    unit_index: 1,
    platform_order_id: 'OID001',
    profile_id: 1,
    task_no: `DT${id}`,
    executor_key: 'manual_dispatch',
    task_status: 'pending',
    delivery_status: 'pending',
    result_code: '',
    result_message: '',
    automation_mode: 'manual',
    requires_claim: false,
    user_action_status: 'not_required',
    attempt_count: 0,
    runtime_session_id: '',
    login_type: '',
    nickname: '',
    role_name: '',
    role_id: '',
    area: '',
    partition_name: '',
    claim_token: '',
    primary_claim_token: '',
    primary_claim_token_id: null,
    primary_claim_token_status: '',
    artifacts_json: '{}',
    context_json: '{}',
    screenshot_path: '',
    last_error: '',
    retry_count: 0,
    created_at: '2026-08-16T00:00:00.000Z',
    updated_at: '2026-08-16T00:00:00.000Z',
    claimed_at: null,
    role_confirmed_at: null,
    redeemed_at: null,
  }
}

function buildVoucher(
  id: number,
  taskId: number | null,
  status = 'UNUSED',
): KuaishouIndustryVoucherRow {
  return {
    id,
    voucher_code: `KSV${id}`,
    oid: 'OID001',
    order_id: 10,
    task_id: taskId,
    unit_index: id,
    seller_id: 'seller-1',
    token: 'token',
    eticket_type: 'GAME_OPEN_TICKET_CONSUME',
    status,
    valid_start_time: 0,
    valid_end_time: 0,
    consume_serial_num: '',
    consume_details_json: [],
    consumed_at: status === 'CONSUMED' ? '2026-08-16T00:00:00.000Z' : null,
    destroyed_at: null,
    send_callback_status: 'success',
    send_callback_attempt_count: 1,
    send_callback_last_error: '',
    send_callback_response_json: {},
    send_callback_sent_at: '2026-08-16T00:00:00.000Z',
    raw_payload_json: {},
    created_at: '2026-08-16T00:00:00.000Z',
    updated_at: '2026-08-16T00:00:00.000Z',
  }
}

test('发布核销优先选择当前订单商品关联任务的券码', () => {
  const tasks = [buildTask(100, 20), buildTask(200, 30)]
  const vouchers = [buildVoucher(1, 100), buildVoucher(2, 200)]

  const targets = resolveWorkOrderVoucherTargets(buildWorkOrder(), tasks, vouchers)

  assert.deepEqual(
    targets.map((target) => target.voucher.voucher_code),
    ['KSV1'],
  )
  assert.equal(targets[0]?.task?.id, 100)
})

test('历史券码未绑定任务时回退核销同一平台订单的券码', () => {
  const targets = resolveWorkOrderVoucherTargets(
    buildWorkOrder(),
    [buildTask(100, 20)],
    [buildVoucher(1, null)],
  )

  assert.deepEqual(
    targets.map((target) => target.voucher.voucher_code),
    ['KSV1'],
  )
  assert.equal(targets[0]?.task, null)
})

test('不会核销已明确绑定到其他商品任务的券码', () => {
  const targets = resolveWorkOrderVoucherTargets(
    buildWorkOrder(),
    [buildTask(100, 20), buildTask(200, 30)],
    [buildVoucher(2, 200)],
  )

  assert.deepEqual(targets, [])
})

test('核销失败时阻止发布并返回失败信息', async () => {
  const voucher = buildVoucher(1, null)
  const result = await consumeIndustryVouchersBeforeWorkOrderPublish(buildWorkOrder(), {
    listVouchersByOid: async () => [voucher],
    listTasksByOrderId: async () => [],
    consumeVoucher: async () => ({
      ok: false,
      voucher,
      callbackSuccess: false,
      errorMessage: '快手核销回调失败',
    }),
    attachVoucherToTask: async (task) => task,
  })

  assert.equal(result.ok, false)
  assert.equal(result.failedCount, 1)
  assert.equal(result.errorMessage, '快手核销回调失败')
})

test('发布前核销券码并同步关联任务状态', async () => {
  const task = buildTask(100, 20)
  const voucher = buildVoucher(1, 100)
  const consumedVoucher = {
    ...voucher,
    status: 'CONSUMED',
    consumed_at: '2026-08-16T01:00:00.000Z',
  }
  const consumedCodes: string[] = []
  const attachedTaskIds: number[] = []

  const result = await consumeIndustryVouchersBeforeWorkOrderPublish(buildWorkOrder(), {
    listVouchersByOid: async () => [voucher],
    listTasksByOrderId: async () => [task],
    consumeVoucher: async (currentVoucher) => {
      consumedCodes.push(currentVoucher.voucher_code)
      return { ok: true, voucher: consumedVoucher, callbackSuccess: true }
    },
    attachVoucherToTask: async (currentTask) => {
      attachedTaskIds.push(currentTask.id)
      return currentTask
    },
  })

  assert.equal(result.ok, true)
  assert.equal(result.voucherCount, 1)
  assert.equal(result.consumedCount, 1)
  assert.equal(result.alreadyConsumedCount, 0)
  assert.deepEqual(consumedCodes, ['KSV1'])
  assert.deepEqual(attachedTaskIds, [100])
})

test('已核销券码按幂等成功处理', async () => {
  const voucher = buildVoucher(1, null, 'CONSUMED')
  const result = await consumeIndustryVouchersBeforeWorkOrderPublish(buildWorkOrder(), {
    listVouchersByOid: async () => [voucher],
    listTasksByOrderId: async () => [],
    consumeVoucher: async () => ({ ok: true, voucher, callbackSuccess: true }),
    attachVoucherToTask: async (task) => task,
  })

  assert.equal(result.ok, true)
  assert.equal(result.voucherCount, 1)
  assert.equal(result.consumedCount, 0)
  assert.equal(result.alreadyConsumedCount, 1)
})

test('指派前核销使用独立来源并同步关联任务状态', async () => {
  const task = buildTask(100, 20)
  const voucher = buildVoucher(1, 100)
  const consumeSources: string[] = []
  const attachSources: string[] = []

  const result = await consumeIndustryVouchersBeforeWorkOrderAssign(buildWorkOrder(), {
    listVouchersByOid: async () => [voucher],
    listTasksByOrderId: async () => [task],
    consumeVoucher: async (currentVoucher, options) => {
      consumeSources.push(String(options.source || ''))
      return {
        ok: true,
        voucher: { ...currentVoucher, status: 'CONSUMED' },
        callbackSuccess: true,
      }
    },
    attachVoucherToTask: async (currentTask, _currentVoucher, options) => {
      attachSources.push(String(options.source || ''))
      return currentTask
    },
  })

  assert.equal(result.ok, true)
  assert.deepEqual(consumeSources, ['work_order_assign'])
  assert.deepEqual(attachSources, ['work_order_assign'])
})

test('指派前没有关联电子凭证时直接成功', async () => {
  let consumeCalled = false
  const result = await consumeIndustryVouchersBeforeWorkOrderAssign(buildWorkOrder(), {
    listVouchersByOid: async () => [],
    listTasksByOrderId: async () => [],
    consumeVoucher: async (voucher) => {
      consumeCalled = true
      return { ok: true, voucher, callbackSuccess: true }
    },
    attachVoucherToTask: async (task) => task,
  })

  assert.equal(result.ok, true)
  assert.equal(result.voucherCount, 0)
  assert.equal(consumeCalled, false)
})

test('指派前电子凭证核销失败时返回失败结果', async () => {
  const voucher = buildVoucher(1, null)
  const result = await consumeIndustryVouchersBeforeWorkOrderAssign(buildWorkOrder(), {
    listVouchersByOid: async () => [voucher],
    listTasksByOrderId: async () => [],
    consumeVoucher: async () => ({
      ok: false,
      voucher,
      callbackSuccess: false,
      errorMessage: '指派前核销失败',
    }),
    attachVoucherToTask: async (task) => task,
  })

  assert.equal(result.ok, false)
  assert.equal(result.failedCount, 1)
  assert.equal(result.errorMessage, '指派前核销失败')
})
