// Stable expert identity — each expert name maps to a consistent avatar/colour
// across rounds. Used to dedup board_speech messages and to provide friendly
// fallbacks when the YAML config has no avatar/colour (ExpertConfig defaults
// to ``#1890ff`` blue, which conflicts with the platform's "no blue" rule).
//
// ponytail: a small 12-colour palette is enough for board meetings
// (MAX_EXPERTS=10). Index is name-hash-mod-palette-length, so the same name
// always picks the same colour across reloads.

export interface ExpertIdentity {
  /** Single-character avatar glyph (CJK/ASCII first char of name). */
  avatar: string
  /** Background colour for the avatar circle and the expert badge. */
  color: string
}

/** Neutral slate palette (GitHub/professional style). Order is stable — do not reshuffle. */
const PALETTE: ReadonlyArray<string> = [
  "#4b5563", // slate 600
  "#6b7280", // gray 500
  "#9ca3af", // gray 400
  "#374151", // gray 800
  "#1f2937", // gray 900
  "#1e40af", // blue 800 (deep, non-vivid)
  "#166534", // green 800
  "#7c2d12", // orange 900
  "#581c87", // purple 900
  "#155e75", // cyan 800
  "#92400e", // amber 800
  "#78716c", // stone 500
]

/** djb2-style string hash — stable across JS engines and reloads. */
function hashName(name: string): number {
  let h = 5381
  for (let i = 0; i < name.length; i++) {
    h = ((h << 5) + h + name.charCodeAt(i)) >>> 0
  }
  return h
}

const DEFAULT_AVATAR = "?"

/** Derive a stable {avatar, color} for an expert name. */
export function pickExpertIdentity(name: string): ExpertIdentity {
  const trimmed = (name || "").trim()
  if (!trimmed) return { avatar: DEFAULT_AVATAR, color: PALETTE[0] }
  // First non-underscore char makes a more recognisable avatar.
  const avatar = trimmed
    .split(/[\s_-]+/)
    .map((p) => p[0])
    .filter(Boolean)
    .slice(0, 1)
    .join("")
    .toUpperCase() || trimmed[0].toUpperCase()
  return { avatar, color: PALETTE[hashName(trimmed) % PALETTE.length] }
}

/** Convenience: same identity regardless of which fields are missing in source. */
export function resolveExpertIdentity(
  name: string | undefined,
  avatar?: string,
  color?: string,
): ExpertIdentity {
  const fallback = pickExpertIdentity(name || "")
  return {
    avatar: avatar && avatar.trim() ? avatar : fallback.avatar,
    color: color && /^#[0-9a-fA-F]{3,8}$/.test(color) ? color : fallback.color,
  }
}
