import { test } from 'node:test'
import assert from 'node:assert/strict'
import { bucketize, BUCKETS } from '../src/data/regionBuckets.js'

// Unit-test the presence.online region roll-up for the "Players Online" widget.
// The load-bearing invariant: the bucket counts ALWAYS reconcile to the true
// total — anything unmatched lands in Wilderness — so the widget can never show
// a sum that disagrees with the headline online count.

test('bucketize groups named regions into their buckets', () => {
  const { rows, total } = bucketize({
    'Britain': 4,
    'Moonglow': 2,
    'Despise': 3,
    'Green Acres House 12': 1, // not a town/dungeon name → Housing
  })
  const byId = Object.fromEntries(rows.map((r) => [r.id, r.count]))
  assert.equal(byId.britain, 4)
  assert.equal(byId.towns, 2)
  assert.equal(byId.dungeons, 3)
  assert.equal(byId.housing, 1)
  assert.equal(total, 10)
})

test('first match wins by BUCKETS order: a town-named house region counts as Towns, not Housing', () => {
  // The towns regex is ^-anchored and towns is checked BEFORE housing, so a house
  // region whose name starts with a town name is bucketed as Towns. Pinning this
  // documents the ordering dependency for anyone retuning BUCKETS.
  const { rows } = bucketize({ 'Trinsic House 12': 1 })
  const byId = Object.fromEntries(rows.map((r) => [r.id, r.count]))
  assert.equal(byId.towns, 1)
  assert.equal(byId.housing, undefined) // empty bucket dropped
})

test('an unmatched region falls through to Wilderness so counts always reconcile', () => {
  const { rows, total } = bucketize({ 'Some Unnamed Field': 5, 'Wilderness': 2 })
  const wilderness = rows.find((r) => r.id === 'wilderness')
  assert.equal(wilderness.count, 7)
  assert.equal(total, 7)
  // The reconciliation guarantee: the buckets sum to the total, exactly.
  assert.equal(rows.reduce((s, r) => s + r.count, 0), total)
})

test('bucketize returns rows in BUCKETS order and drops empty buckets', () => {
  const { rows } = bucketize({ 'Despise': 1, 'Britain': 1 })
  assert.deepEqual(rows.map((r) => r.id), ['britain', 'dungeons']) // BUCKETS order, no empty towns/housing/wilderness
})

test('bucketize coerces non-numeric counts and tolerates empty/nullish input', () => {
  assert.deepEqual(bucketize({}), { rows: [], total: 0 })
  assert.deepEqual(bucketize(), { rows: [], total: 0 })
  const { total } = bucketize({ 'Britain': '3', 'Minoc': 'oops' })
  assert.equal(total, 3) // '3' → 3, 'oops' → 0
})

test('the last bucket is the catch-all (its match accepts anything)', () => {
  const last = BUCKETS[BUCKETS.length - 1]
  assert.equal(last.id, 'wilderness')
  assert.equal(last.match('literally anything'), true)
})
