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

import { selectCloudtentaclesSourceForFulfillment } from './account-selector.js'

const contexts = {
  'account-a': {
    baseUrl: 'https://cloud.example.com',
    token: 'token-a',
    deviceId: '-',
    deviceType: 0,
    resolvedSourceKey: 'account-a',
  },
  'account-b': {
    baseUrl: 'https://cloud.example.com',
    token: 'token-b',
    deviceId: '-',
    deviceType: 0,
    resolvedSourceKey: 'account-b',
  },
}

const listEmptyVirtualNumbers = async () => ({
  baseUrl: 'https://cloud.example.com',
  key: '1',
  itemCount: 0,
  occupiedItemCount: 0,
  items: [],
  rawItems: [],
})

test('selectCloudtentaclesSourceForFulfillment 已固定账号时不按压力切换', async () => {
  const selection = await selectCloudtentaclesSourceForFulfillment(
    {
      binding: {
        resolvedSourceKey: 'account-a',
        cloudSourceKeys: ['account-a', 'account-b'],
        vnId: 123,
      },
    },
    {
      resolveContextBySourceKeys: (sourceKeys) => {
        const key = String(sourceKeys[0] || '').trim()
        return contexts[key as keyof typeof contexts]
      },
      listSourceLoadStats: async () => [
        { sourceKey: 'account-a', activeCount: 99, redeemingCount: 99 },
        { sourceKey: 'account-b', activeCount: 0, redeemingCount: 0 },
      ],
      listVirtualNumbers: listEmptyVirtualNumbers,
    },
  )

  assert.equal(selection.sourceKey, 'account-a')
  assert.equal(selection.fixed, true)
})

test('selectCloudtentaclesSourceForFulfillment 无号码时忽略残留固定账号', async () => {
  const selection = await selectCloudtentaclesSourceForFulfillment(
    {
      binding: {
        resolvedSourceKey: 'account-a',
        cloudSourceKeys: ['account-a', 'account-b'],
        vnId: 0,
      },
    },
    {
      resolveContextBySourceKeys: (sourceKeys) =>
        contexts[String(sourceKeys[0]) as keyof typeof contexts],
      listSourceLoadStats: async () => [
        { sourceKey: 'account-a', activeCount: 20, redeemingCount: 0 },
        { sourceKey: 'account-b', activeCount: 1, redeemingCount: 0 },
      ],
      listVirtualNumbers: listEmptyVirtualNumbers,
    },
  )

  try {
    assert.equal(selection.sourceKey, 'account-b')
    assert.equal(selection.fixed, false)
  } finally {
    selection.release()
  }
})

test('selectCloudtentaclesSourceForFulfillment 跳过真实占用已达20的账号', async () => {
  const selection = await selectCloudtentaclesSourceForFulfillment(
    { binding: { cloudSourceKeys: ['account-a', 'account-b'] } },
    {
      resolveContextBySourceKeys: (sourceKeys) =>
        contexts[String(sourceKeys[0]) as keyof typeof contexts],
      listSourceLoadStats: async () => [],
      listVirtualNumbers: async (payload) => {
        const count = payload.sourceKey === 'account-a' ? 20 : 3
        return {
          baseUrl: 'https://cloud.example.com',
          key: '1',
          itemCount: count,
          occupiedItemCount: count,
          items: Array.from({ length: count }, (_, id) => ({ id: id + 1, status: 1 })),
          rawItems: [],
        }
      },
    },
  )

  try {
    assert.equal(selection.sourceKey, 'account-b')
    assert.equal(selection.occupiedCount, 3)
    assert.equal(selection.availableCount, 17)
  } finally {
    selection.release()
  }
})

test('selectCloudtentaclesSourceForFulfillment 不把 status=0 的空闲号码计入占用', async () => {
  const selection = await selectCloudtentaclesSourceForFulfillment(
    { binding: { cloudSourceKeys: ['account-a', 'account-b'] } },
    {
      resolveContextBySourceKeys: (sourceKeys) =>
        contexts[String(sourceKeys[0]) as keyof typeof contexts],
      listSourceLoadStats: async () => [],
      listVirtualNumbers: async (payload) => {
        const items =
          payload.sourceKey === 'account-a'
            ? Array.from({ length: 20 }, (_, id) => ({ id: id + 1, status: 0 }))
            : Array.from({ length: 3 }, (_, id) => ({ id: id + 1, status: 1 }))
        return {
          baseUrl: 'https://cloud.example.com',
          key: '1',
          itemCount: items.length,
          occupiedItemCount: items.filter((item) => item.status !== 0).length,
          items,
          rawItems: [],
        }
      },
    },
  )

  try {
    assert.equal(selection.sourceKey, 'account-a')
    assert.equal(selection.occupiedCount, 0)
  } finally {
    selection.release()
  }
})

test('selectCloudtentaclesSourceForFulfillment 真实占用优先于数据库历史压力', async () => {
  const selection = await selectCloudtentaclesSourceForFulfillment(
    { binding: { cloudSourceKeys: ['account-a', 'account-b'] } },
    {
      resolveContextBySourceKeys: (sourceKeys) =>
        contexts[String(sourceKeys[0]) as keyof typeof contexts],
      listSourceLoadStats: async () => [
        { sourceKey: 'account-a', activeCount: 99, redeemingCount: 10 },
        { sourceKey: 'account-b', activeCount: 0, redeemingCount: 0 },
      ],
      listVirtualNumbers: async (payload) => {
        const count = payload.sourceKey === 'account-a' ? 5 : 6
        return {
          baseUrl: 'https://cloud.example.com',
          key: '1',
          itemCount: count,
          occupiedItemCount: count,
          items: Array.from({ length: count }, (_, id) => ({ id: id + 1, status: 1 })),
          rawItems: [],
        }
      },
    },
  )

  try {
    assert.equal(selection.sourceKey, 'account-a')
    assert.equal(selection.occupiedCount, 5)
  } finally {
    selection.release()
  }
})

test('selectCloudtentaclesSourceForFulfillment 多候选时选择压力最低账号', async () => {
  const selection = await selectCloudtentaclesSourceForFulfillment(
    {
      binding: {
        cloudSourceKeys: ['account-a', 'account-b'],
      },
    },
    {
      resolveContextBySourceKeys: (sourceKeys) => {
        const key = String(sourceKeys[0] || '').trim()
        return contexts[key as keyof typeof contexts]
      },
      listSourceLoadStats: async () => [
        { sourceKey: 'account-a', activeCount: 3, redeemingCount: 1 },
        { sourceKey: 'account-b', activeCount: 0, redeemingCount: 0 },
      ],
      listVirtualNumbers: listEmptyVirtualNumbers,
    },
  )

  try {
    assert.equal(selection.sourceKey, 'account-b')
    assert.equal(selection.fixed, false)
  } finally {
    selection.release()
  }
})

test('selectCloudtentaclesSourceForFulfillment 会跳过不可用账号', async () => {
  const selection = await selectCloudtentaclesSourceForFulfillment(
    {
      binding: {
        cloudSourceKeys: ['account-a', 'account-b'],
      },
    },
    {
      resolveContextBySourceKeys: (sourceKeys) => {
        const key = String(sourceKeys[0] || '').trim()
        if (key === 'account-a') {
          throw new Error('账号已停用')
        }
        return contexts[key as keyof typeof contexts]
      },
      listSourceLoadStats: async () => [],
      listVirtualNumbers: listEmptyVirtualNumbers,
    },
  )

  try {
    assert.equal(selection.sourceKey, 'account-b')
    assert.equal(selection.candidateCount, 1)
  } finally {
    selection.release()
  }
})

test('selectCloudtentaclesSourceForFulfillment 用进程内占位分散并发准备', async () => {
  const deps = {
    resolveContextBySourceKeys: (sourceKeys: unknown[] = []) => {
      const key = String(sourceKeys[0] || '').trim()
      return contexts[key as keyof typeof contexts]
    },
    listSourceLoadStats: async () => [],
    listVirtualNumbers: listEmptyVirtualNumbers,
  }
  const flow = {
    binding: {
      cloudSourceKeys: ['account-a', 'account-b'],
    },
  }
  const first = await selectCloudtentaclesSourceForFulfillment(flow, deps)
  const second = await selectCloudtentaclesSourceForFulfillment(flow, deps)

  try {
    assert.equal(first.sourceKey, 'account-a')
    assert.equal(second.sourceKey, 'account-b')
  } finally {
    first.release()
    second.release()
  }
})
