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

import { syncDeliveryTasksForOrderWithDeps } from './delivery-task-service.js'
import type { OrderItemRow, OrderRow, TaskRow } from '../../types/repository/rows.js'
import type { JsonObject } from '../../types/json.js'

type CreatedTaskInput = {
  orderId?: number
  orderItemId?: number
  unitIndex?: number
  contextJson?: string
  taskStatus?: string
  executorKey?: string
  [key: string]: unknown
}

function stubOrder(
  patch: Partial<OrderRow> & Pick<OrderRow, 'id' | 'platform_order_id'>,
): OrderRow {
  return {
    id: patch.id,
    order_id: patch.id,
    provider: patch.provider || 'open_91',
    platform: patch.platform || 'kuaishou',
    shop_id: patch.shop_id || 'shop-1',
    shop_name: patch.shop_name || '测试店铺',
    platform_order_id: patch.platform_order_id,
    order_status: patch.order_status || 'created',
    pay_status: patch.pay_status || 'pending_payment',
    buyer_id: '',
    buyer_name: '',
    receiver_contact: '',
    total_amount: 0,
    currency: 'CNY',
    raw_payload_json: '{}',
    paid_at: null,
    created_at: '2026-05-29T00:00:00.000Z',
    updated_at: '2026-05-29T00:00:00.000Z',
    ...patch,
  } as OrderRow
}

function stubOrderItem(
  patch: Partial<OrderItemRow> & Pick<OrderItemRow, 'id' | 'order_id' | 'sku_code'>,
): OrderItemRow {
  return {
    id: patch.id,
    order_id: patch.order_id,
    sku_code: patch.sku_code,
    sku_name: patch.sku_name || patch.sku_code,
    quantity: patch.quantity || 1,
    spec_json: '{}',
    item_snapshot_json: patch.item_snapshot_json || {},
    created_at: '2026-05-29T00:00:00.000Z',
    updated_at: '2026-05-29T00:00:00.000Z',
    ...patch,
  } as OrderItemRow
}

function stubCreatedTask(id: number, input: CreatedTaskInput): TaskRow {
  return {
    id,
    order_id: Number(input.orderId || 0),
    order_item_id: Number(input.orderItemId || 0),
    unit_index: Number(input.unitIndex || 1),
    platform_order_id: '',
    profile_id: 0,
    task_no: 'DT-test',
    executor_key: String(input.executorKey || ''),
    task_status: String(input.taskStatus || 'pending'),
    delivery_status: 'pending',
    result_code: '',
    result_message: '',
    automation_mode: 'manual',
    requires_claim: true,
    user_action_status: 'pending_claim',
    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: String(input.contextJson || '{}'),
    screenshot_path: '',
    last_error: '',
    retry_count: 0,
    created_at: '2026-05-29T00:00:00.000Z',
    updated_at: '2026-05-29T00:00:00.000Z',
    claimed_at: null,
    role_confirmed_at: null,
    redeemed_at: null,
  } as TaskRow
}

test('syncDeliveryTasksForOrder 多账号候选时不提前固定 cloudtentacles 账号', async () => {
  const createdInputs: CreatedTaskInput[] = []

  await syncDeliveryTasksForOrderWithDeps(
    stubOrder({
      id: 1,
      pay_status: 'pending_payment',
      platform_order_id: '2614900602069169',
    }),
    [
      stubOrderItem({
        id: 10,
        order_id: 1,
        sku_code: 'SKU-1',
        sku_name: '荣耀勋章礼包（30个）',
        quantity: 1,
        item_snapshot_json: {
          cloudtentacles: {
            cloudSourceKeys: ['account-a', 'account-b'],
            resolvedSourceKey: 'account-a',
            cloudSkuId: 74,
            cloudSkuName: '荣耀勋章礼包（30个）',
            deliveryItems: [
              {
                cloudSkuId: 74,
                cloudSkuName: '荣耀勋章礼包（30个）',
                quantity: 1,
              },
            ],
          },
        } as JsonObject,
      }),
    ],
    {
      listTasksByOrderId: async () => [],
      getFulfillmentProfileByKey: async () => ({
        id: 9,
        profile_key: 'kuaishou_ct_assisted',
        profile_name: 'kuaishou-lewan 履约',
        executor_key: 'kuaishou_ct_assisted',
      }),
      createTask: async (input) => {
        createdInputs.push(input as CreatedTaskInput)
        return stubCreatedTask(100, input as CreatedTaskInput)
      },
      nowIso: () => '2026-05-29T09:05:46.658Z',
      randomId: () => 'DT-test',
      createTaskEvent: async () => null,
    },
  )

  const context = JSON.parse(String(createdInputs[0]?.contextJson || '{}')) as JsonObject
  const fulfillment = context.kuaishouCloudFulfillment as JsonObject
  const binding = fulfillment.binding as JsonObject
  assert.deepEqual(binding.cloudSourceKeys, ['account-a', 'account-b'])
  assert.equal(binding.resolvedSourceKey, '')
})

test('syncDeliveryTasksForOrder 单账号候选时保留固定 cloudtentacles 账号', async () => {
  const createdInputs: CreatedTaskInput[] = []

  await syncDeliveryTasksForOrderWithDeps(
    stubOrder({
      id: 2,
      pay_status: 'pending_payment',
      platform_order_id: '2614900602069170',
    }),
    [
      stubOrderItem({
        id: 11,
        order_id: 2,
        sku_code: 'SKU-1',
        sku_name: '荣耀勋章礼包（30个）',
        quantity: 1,
        item_snapshot_json: {
          cloudtentacles: {
            cloudSourceKeys: ['account-a'],
            cloudSkuId: 74,
            cloudSkuName: '荣耀勋章礼包（30个）',
          },
        } as JsonObject,
      }),
    ],
    {
      listTasksByOrderId: async () => [],
      getFulfillmentProfileByKey: async () => ({
        id: 9,
        profile_key: 'kuaishou_ct_assisted',
        profile_name: 'kuaishou-lewan 履约',
        executor_key: 'kuaishou_ct_assisted',
      }),
      createTask: async (input) => {
        createdInputs.push(input as CreatedTaskInput)
        return stubCreatedTask(101, input as CreatedTaskInput)
      },
      nowIso: () => '2026-05-29T09:05:46.658Z',
      randomId: () => 'DT-test',
      createTaskEvent: async () => null,
    },
  )

  const context = JSON.parse(String(createdInputs[0]?.contextJson || '{}')) as JsonObject
  const fulfillment = context.kuaishouCloudFulfillment as JsonObject
  const binding = fulfillment.binding as JsonObject
  assert.deepEqual(binding.cloudSourceKeys, ['account-a'])
  assert.equal(binding.resolvedSourceKey, 'account-a')
})

test('syncDeliveryTasksForOrder 已有部分任务时按订单项补建缺失任务', async () => {
  const existingTask = stubCreatedTask(201, {
    orderId: 3,
    orderItemId: 20,
    unitIndex: 1,
    executorKey: 'kuaishou_ct_assisted',
  })
  const createdInputs: CreatedTaskInput[] = []
  const taskEvents: Array<{ taskId: number; eventType: string }> = []

  const tasks = await syncDeliveryTasksForOrderWithDeps(
    stubOrder({ id: 3, platform_order_id: 'partial-order' }),
    [
      stubOrderItem({
        id: 20,
        order_id: 3,
        sku_code: 'SKU-existing',
        item_snapshot_json: buildCloudSnapshot(74, '商品 A'),
      }),
      stubOrderItem({
        id: 21,
        order_id: 3,
        sku_code: 'SKU-missing',
        item_snapshot_json: buildCloudSnapshot(75, '商品 B'),
      }),
    ],
    {
      listTasksByOrderId: async () => [existingTask],
      getFulfillmentProfileByKey: async () => buildCloudProfile(),
      createTask: async (input) => {
        createdInputs.push(input as CreatedTaskInput)
        return stubCreatedTask(202, input as CreatedTaskInput)
      },
      createTaskEvent: async (taskId, eventType) => {
        taskEvents.push({ taskId: Number(taskId), eventType })
        return null
      },
      logInfo: () => null,
      logWarn: () => null,
      nowIso: () => '2026-05-29T09:05:46.658Z',
      randomId: () => 'DT-partial',
    },
  )

  assert.deepEqual(
    createdInputs.map((input) => [input.orderItemId, input.unitIndex]),
    [[21, 1]],
  )
  assert.deepEqual(
    tasks.map((task) => task.id),
    [201, 202],
  )
  assert.deepEqual(taskEvents, [{ taskId: 202, eventType: 'fulfillment_task_planned' }])
})

test('syncDeliveryTasksForOrder 数量增加时只补建缺失单元', async () => {
  const existingTask = stubCreatedTask(301, {
    orderId: 4,
    orderItemId: 30,
    unitIndex: 1,
    executorKey: 'kuaishou_ct_assisted',
  })
  const createdInputs: CreatedTaskInput[] = []

  const tasks = await syncDeliveryTasksForOrderWithDeps(
    stubOrder({ id: 4, platform_order_id: 'quantity-increased' }),
    [
      stubOrderItem({
        id: 30,
        order_id: 4,
        sku_code: 'SKU-quantity',
        quantity: 2,
        item_snapshot_json: buildCloudSnapshot(74, '商品 A'),
      }),
    ],
    {
      listTasksByOrderId: async () => [existingTask],
      getFulfillmentProfileByKey: async () => buildCloudProfile(),
      createTask: async (input) => {
        createdInputs.push(input as CreatedTaskInput)
        return stubCreatedTask(302, input as CreatedTaskInput)
      },
      createTaskEvent: async () => null,
      logInfo: () => null,
      logWarn: () => null,
      nowIso: () => '2026-05-29T09:05:46.658Z',
      randomId: () => 'DT-quantity',
    },
  )

  assert.deepEqual(
    createdInputs.map((input) => input.unitIndex),
    [2],
  )
  assert.deepEqual(
    tasks.map((task) => task.unit_index),
    [1, 2],
  )
})

test('syncDeliveryTasksForOrder 规划失败时记录可定位的路由诊断', async () => {
  const warnings: Array<{ message: string; detail: Record<string, unknown> }> = []

  const tasks = await syncDeliveryTasksForOrderWithDeps(
    stubOrder({ id: 5, platform_order_id: 'planning-failed' }),
    [
      stubOrderItem({
        id: 40,
        order_id: 5,
        sku_code: 'SKU-broken',
        item_snapshot_json: {
          isConfigured: true,
          fulfillmentRoute: {
            selectedExecutorKey: 'kuaishou_ct_assisted',
            reason: '规则指定云履约',
          },
          cloudtentacles: {
            cloudSkuId: 74,
            cloudSkuName: '商品 A',
            cloudSourceKeys: [],
          },
        } as JsonObject,
      }),
    ],
    {
      listTasksByOrderId: async () => [],
      getFulfillmentProfileByKey: async () => buildCloudProfile(),
      createTaskEvent: async () => null,
      logInfo: () => null,
      logWarn: (_scope, message, detail) => {
        warnings.push({
          message: String(message),
          detail: detail as Record<string, unknown>,
        })
        return null
      },
    },
  )

  assert.deepEqual(tasks, [])
  assert.equal(warnings.length, 1)
  assert.equal(warnings[0]?.message, '订单项已配置履约路由但无法生成任务计划')
  assert.equal(warnings[0]?.detail.orderItemId, 40)
  assert.deepEqual(warnings[0]?.detail.missingUnitIndexes, [1])
  assert.deepEqual(warnings[0]?.detail.planningDiagnostic, {
    snapshotIsConfigured: true,
    selectedExecutorKey: 'kuaishou_ct_assisted',
    routeReason: '规则指定云履约',
    candidateAvailability: [],
    sourceItemTitle: '',
    sourceSkuNick: '',
    cloudSkuId: 74,
    cloudSkuName: '商品 A',
    cloudSourceKeys: [],
    feifeiProductCode: '',
    affiliateDashSku: '',
  })
})

test('syncDeliveryTasksForOrder 并发创建冲突时复用已落库任务', async () => {
  const concurrentTask = stubCreatedTask(401, {
    orderId: 6,
    orderItemId: 50,
    unitIndex: 1,
    executorKey: 'kuaishou_ct_assisted',
  })
  let listCount = 0
  let eventCount = 0

  const tasks = await syncDeliveryTasksForOrderWithDeps(
    stubOrder({ id: 6, platform_order_id: 'concurrent-order' }),
    [
      stubOrderItem({
        id: 50,
        order_id: 6,
        sku_code: 'SKU-concurrent',
        item_snapshot_json: buildCloudSnapshot(74, '商品 A'),
      }),
    ],
    {
      listTasksByOrderId: async () => (listCount++ === 0 ? [] : [concurrentTask]),
      getFulfillmentProfileByKey: async () => buildCloudProfile(),
      createTask: async () => {
        throw new Error('duplicate key value violates unique constraint')
      },
      createTaskEvent: async () => {
        eventCount += 1
        return null
      },
      logInfo: () => null,
      logWarn: () => null,
      nowIso: () => '2026-05-29T09:05:46.658Z',
      randomId: () => 'DT-concurrent',
    },
  )

  assert.deepEqual(
    tasks.map((task) => task.id),
    [401],
  )
  assert.equal(eventCount, 0)
})

function buildCloudSnapshot(cloudSkuId: number, cloudSkuName: string): JsonObject {
  return {
    isConfigured: true,
    fulfillmentRoute: {
      selectedExecutorKey: 'kuaishou_ct_assisted',
    },
    cloudtentacles: {
      cloudSourceKeys: ['account-a'],
      cloudSkuId,
      cloudSkuName,
    },
  }
}

function buildCloudProfile() {
  return {
    id: 9,
    profile_key: 'kuaishou_ct_assisted',
    profile_name: 'kuaishou-lewan 履约',
    executor_key: 'kuaishou_ct_assisted',
  }
}
