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

import { closeAdminTaskWithDeps } from './admin-write-service.js'

test('closeAdminTaskWithDeps revokes claim link, releases reserved inventory, and closes browser session', async () => {
  const calls = {
    updateToken: [],
    releaseReserved: [],
    closeSession: [],
    updateTask: [],
    createEvent: [],
  }
  const task = {
    id: 30,
    task_status: 'link_generated',
    delivery_status: 'pending',
    inventory_status: 'reserved',
    user_action_status: 'pending_claim',
    browser_session_id: 'browser-session-30',
    primary_claim_token_id: 9,
    claim_expires_at: '2026-04-15T10:00:00.000Z',
    last_error: '',
    updated_at: '2026-04-14T10:00:00.000Z',
  }
  const now = '2026-04-14T10:16:18.000Z'

  const result = await closeAdminTaskWithDeps(task.id, {
    getRequiredTask: async () => task,
    listTaskInventoryBindingsByTaskId: async () => ([
      { inventory_item_id: 17, binding_status: 'reserved' },
      { inventory_item_id: 18, binding_status: 'released' },
      { inventory_item_id: 17, binding_status: 'reserved' },
    ]),
    releaseReservedInventoryItem: async (inventoryItemId, updatedAt) => {
      calls.releaseReserved.push({ inventoryItemId, updatedAt })
      return { id: inventoryItemId }
    },
    updateClaimToken: async (tokenId, patch) => {
      calls.updateToken.push({ tokenId, patch })
      return { id: tokenId, ...patch }
    },
    closeTencentBrowserSession: async (sessionId) => {
      calls.closeSession.push(sessionId)
      return { sessionId, closed: true }
    },
    updateTask: async (taskId, patch) => {
      calls.updateTask.push({ taskId, patch })
      return { ...task, ...patch }
    },
    createTaskEvent: async (taskId, eventType, payload, createdAt) => {
      calls.createEvent.push({ taskId, eventType, payload, createdAt })
      return null
    },
    nowIso: () => now,
  })

  assert.equal(calls.updateToken.length, 1)
  assert.deepEqual(calls.updateToken[0], {
    tokenId: 9,
    patch: {
      status: 'revoked',
      expired_at: now,
      updated_at: now,
    },
  })
  assert.deepEqual(calls.releaseReserved, [
    { inventoryItemId: 17, updatedAt: now },
  ])
  assert.deepEqual(calls.closeSession, ['browser-session-30'])
  assert.equal(calls.updateTask.length, 1)
  assert.equal(calls.updateTask[0].patch.task_status, 'closed')
  assert.equal(calls.updateTask[0].patch.delivery_status, 'closed')
  assert.equal(calls.updateTask[0].patch.inventory_status, 'pending')
  assert.equal(calls.updateTask[0].patch.user_action_status, 'closed')
  assert.equal(calls.updateTask[0].patch.browser_session_id, '')
  assert.equal(calls.updateTask[0].patch.claim_expires_at, now)
  assert.match(calls.updateTask[0].patch.last_error, /领取链接已失效/)
  assert.match(calls.updateTask[0].patch.last_error, /预占库存已释放/)
  assert.equal(calls.createEvent.length, 1)
  assert.deepEqual(calls.createEvent[0], {
    taskId: 30,
    eventType: 'task_closed',
    payload: {
      claimTokenRevoked: true,
      releasedInventoryItemIds: [17],
      releasedInventoryCount: 1,
      browserSessionClosed: true,
    },
    createdAt: now,
  })
  assert.equal(result.task.status, 'closed')
})

test('closeAdminTaskWithDeps rejects redeemed tasks', async () => {
  await assert.rejects(
    () => closeAdminTaskWithDeps(99, {
      getRequiredTask: async () => ({
        id: 99,
        task_status: 'redeemed',
      }),
    }),
    /已兑换任务不能关闭/,
  )
})
