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

import {
  TASK_STATUS,
  canRedeemKuaishouCloudClaimStatus,
  canTaskTransition,
  normalizeTaskStatus,
} from '../../domain/task-status.js'
import {
  assertBoundUidMatchesExpected,
  assertClaimExpectedUidReady,
  isClaimUidMatched,
} from './claim-identity.js'

/**
 * 一键兑换前置：waiting_binding + UID 匹配 → 可升到 role_confirmed → redeeming
 */
function canPromoteWaitingBindingToRedeem(options: {
  status: unknown
  expectedUid: string
  boundUid: string
}) {
  const status = normalizeTaskStatus(options.status)
  if (!canRedeemKuaishouCloudClaimStatus(status)) {
    return { ok: false, reason: 'status_not_redeemable' as const }
  }
  if (!options.expectedUid) {
    return { ok: false, reason: 'uid_missing' as const }
  }
  if (!isClaimUidMatched(options.expectedUid, options.boundUid)) {
    return { ok: false, reason: 'uid_mismatch' as const }
  }
  if (status === TASK_STATUS.WAITING_BINDING) {
    if (!canTaskTransition(TASK_STATUS.WAITING_BINDING, TASK_STATUS.ROLE_CONFIRMED)) {
      return { ok: false, reason: 'cannot_promote' as const }
    }
  }
  if (!canTaskTransition(TASK_STATUS.ROLE_CONFIRMED, TASK_STATUS.REDEEMING)) {
    return { ok: false, reason: 'cannot_redeem' as const }
  }
  return { ok: true as const, reason: 'ok' as const }
}

test('waiting_binding + uid 匹配可一键兑换', () => {
  const result = canPromoteWaitingBindingToRedeem({
    status: TASK_STATUS.WAITING_BINDING,
    expectedUid: '10001',
    boundUid: '10001',
  })
  assert.deepEqual(result, { ok: true, reason: 'ok' })
})

test('waiting_binding + uid 不一致不可兑换', () => {
  const result = canPromoteWaitingBindingToRedeem({
    status: TASK_STATUS.WAITING_BINDING,
    expectedUid: '10001',
    boundUid: '99999',
  })
  assert.equal(result.ok, false)
  assert.equal(result.reason, 'uid_mismatch')
})

test('link_generated 状态不可直接 redeem', () => {
  const result = canPromoteWaitingBindingToRedeem({
    status: TASK_STATUS.LINK_GENERATED,
    expectedUid: '10001',
    boundUid: '10001',
  })
  assert.equal(result.ok, false)
  assert.equal(result.reason, 'status_not_redeemable')
})

test('assertBoundUidMatchesExpected 在不匹配时抛错', () => {
  assert.throws(
    () =>
      assertBoundUidMatchesExpected(
        {
          context_json: JSON.stringify({
            claimIdentity: { expectedUid: '10001' },
          }),
        },
        {
          binding: { roleId: '999', roleName: 'x', vnPhone: '1' },
          role: { rid: '999', name: 'x' },
        },
      ),
    /不一致/,
  )
})

test('assertClaimExpectedUidReady 要求 claimIdentity', () => {
  assert.throws(() => assertClaimExpectedUidReady({ context_json: '{}' }), /填写游戏 UID/)
})
