// Unit tests for the pure username policy (no DB): validation, reserved-name
// blocklist, case normalization, SSO derivation + the dedup suffix loop.
const { test } = require('node:test')
const assert = require('node:assert/strict')

const policy = require('../src/auth/usernamePolicy')

test('validateUsername accepts a normal name and trims whitespace', () => {
  const r = policy.validateUsername('  Frodo_99  ')
  assert.equal(r.ok, true)
  assert.equal(r.name, 'Frodo_99') // trimmed, case preserved
})

test('validateUsername rejects too-short / too-long / bad-charset names', () => {
  assert.equal(policy.validateUsername('ab').ok, false) // < 3
  assert.equal(policy.validateUsername('x'.repeat(33)).ok, false) // > 32
  assert.equal(policy.validateUsername('has space').ok, false)
  assert.equal(policy.validateUsername('emoji😀here').ok, false)
})

test('reserved names are rejected case-insensitively', () => {
  for (const name of ['admin', 'ADMIN', 'Administrator', 'root', 'moderator', 'support', 'me']) {
    assert.equal(policy.isReserved(name), true, `${name} should be reserved`)
    assert.equal(policy.validateUsername(name).ok, false, `${name} should be rejected`)
  }
  assert.equal(policy.isReserved('frodo'), false)
})

test('sanitizeToUsername strips disallowed chars and leading punctuation', () => {
  assert.equal(policy.sanitizeToUsername('Fró.do Baggins!'), 'Fro.doBaggins')
  assert.equal(policy.sanitizeToUsername('...weird'), 'weird')
  assert.equal(policy.sanitizeToUsername('a'.repeat(50)).length, policy.MAX_LEN)
})

test('deriveUsernameBase prefers display name, then email local-part, then player', () => {
  assert.equal(policy.deriveUsernameBase({ name: 'Gandalf', email: 'g@x.com' }), 'Gandalf')
  assert.equal(policy.deriveUsernameBase({ name: '💥', email: 'samwise@shire.net' }), 'samwise')
  assert.equal(policy.deriveUsernameBase({ name: '', email: '' }), 'player')
  // A reserved derived base is skipped in favor of the next candidate.
  assert.equal(policy.deriveUsernameBase({ name: 'admin', email: 'realuser@x.com' }), 'realuser')
})

test('candidateUsername yields the base then increasing suffixes, clamped to length', () => {
  assert.equal(policy.candidateUsername('bilbo', 0), 'bilbo')
  assert.equal(policy.candidateUsername('bilbo', 1), 'bilbo2')
  assert.equal(policy.candidateUsername('bilbo', 2), 'bilbo3')
  // Long base: the numeric suffix must survive the MAX_LEN clamp.
  const long = 'a'.repeat(policy.MAX_LEN)
  const c = policy.candidateUsername(long, 10)
  assert.ok(c.length <= policy.MAX_LEN)
  assert.ok(c.endsWith('11'))
})
