/**
 * What a username may be.
 *
 * Pure, with nothing under it, because the sign-in form checks the shape before
 * it asks the server anything and the form is a client component.
 *
 * HR chooses these; nothing here invents one. The rules are only wide enough to
 * keep out what would cause trouble later and narrow enough that two people
 * cannot end up with names that differ by something invisible.
 *
 * Lower case only, and folded before it is stored, because somebody typing on a
 * factory terminal with caps lock on should get in. Latin letters, digits, a
 * dot, a hyphen and an underscore. No spaces: a name with a space in it is a
 * name half of which gets lost to a trim somewhere.
 *
 * It is deliberately not the employee code. The code is the internal
 * identifier, a pillar of the accounting system, and the client's answer to
 * their own question 10 says it is a sync ID and never the login.
 */

export const USERNAME_MIN = 3
export const USERNAME_MAX = 32

const SHAPE = /^[a-z0-9][a-z0-9._-]*[a-z0-9]$/

/** Folded, so `N.Kulisra` and `n.kulisra` cannot become two people. */
export function normaliseUsername(value: string): string {
  return value.trim().toLowerCase()
}

export type UsernameProblem = "too_short" | "too_long" | "bad_characters"

export function checkUsername(value: string): UsernameProblem | null {
  const name = normaliseUsername(value)
  if (name.length < USERNAME_MIN) return "too_short"
  if (name.length > USERNAME_MAX) return "too_long"
  // The shape also refuses a leading or trailing dot, which is the one that
  // survives a copy and paste and then confuses everybody looking for it.
  if (!SHAPE.test(name)) return "bad_characters"
  return null
}

export function isUsername(value: string): boolean {
  return checkUsername(value) === null
}
