const ADJECTIVES_FR = [
  "Agile",
  "Brave",
  "Calme",
  "Curieux",
  "Discret",
  "Elegant",
  "Fidele",
  "Gentil",
  "Habile",
  "Joyeux",
  "Leger",
  "Malin",
  "Noble",
  "Paisible",
  "Rapide",
  "Sage",
  "Timide",
  "Vif",
  "Zen",
  "Zeste",
] as const

const ANIMALS_FR = [
  "Lynx",
  "Panda",
  "Faucon",
  "Loutre",
  "Renard",
  "Heron",
  "Castor",
  "Koala",
  "Loup",
  "Ours",
  "Tigre",
  "Aigle",
  "Dauphin",
  "Phoque",
  "Ecureuil",
  "Chouette",
  "Cerf",
  "Lama",
  "Belette",
  "Pieuvre",
] as const

/** Background colors for caret labels (white text — WCAG AA 4.5:1+). */
const CURSOR_COLORS = [
  "#6D28D9", // violet
  "#BE123C", // rose
  "#C2410C", // orange
  "#A16207", // gold (not light yellow)
  "#1D4ED8", // blue
  "#0F766E", // teal
  "#15803D", // green
  "#A21CAF", // fuchsia
  "#4338CA", // indigo
  "#B45309", // amber
] as const

const MIN_CURSOR_CONTRAST_WITH_WHITE = 4.5

function hexLuminance(hex: string): number {
  const raw = hex.replace("#", "")
  if (raw.length !== 6) return 1
  const channel = (i: number) => {
    const c = parseInt(raw.slice(i, i + 2), 16) / 255
    return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4
  }
  return 0.2126 * channel(0) + 0.7152 * channel(2) + 0.0722 * channel(4)
}

function contrastWithWhite(bgHex: string): number {
  const bg = hexLuminance(bgHex)
  return (1 + 0.05) / (bg + 0.05)
}

export function isReadableCursorColor(hex: string): boolean {
  return contrastWithWhite(hex) >= MIN_CURSOR_CONTRAST_WITH_WHITE
}

function resolveCursorColor(id: string, stored?: string): string {
  if (stored && isReadableCursorColor(stored)) return stored
  return colorForGuestId(id)
}

export type GuestEditorIdentity = {
  guestId: string
  guestName: string
  color: string
}

const STORAGE_PREFIX = "ultidrive-guest-identity:"

function pick<T>(items: readonly T[]): T {
  return items[Math.floor(Math.random() * items.length)]!
}

function hashString(input: string): number {
  let hash = 0
  for (let i = 0; i < input.length; i++) {
    hash = (hash << 5) - hash + input.charCodeAt(i)
    hash |= 0
  }
  return Math.abs(hash)
}

export function generateGuestDisplayName(): string {
  return `${pick(ADJECTIVES_FR)} ${pick(ANIMALS_FR)}`
}

export function colorForGuestId(guestId: string): string {
  return CURSOR_COLORS[hashString(guestId) % CURSOR_COLORS.length]!
}

function newGuestId(): string {
  if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
    return crypto.randomUUID()
  }
  return `guest-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`
}

export function getGuestEditorIdentity(shareToken: string): GuestEditorIdentity {
  const key = `${STORAGE_PREFIX}${shareToken}`
  if (typeof sessionStorage !== "undefined") {
    const raw = sessionStorage.getItem(key)
    if (raw) {
      try {
        const parsed = JSON.parse(raw) as GuestEditorIdentity
        if (parsed.guestId && parsed.guestName) {
          const color = resolveCursorColor(parsed.guestId, parsed.color)
          return {
            guestId: parsed.guestId,
            guestName: parsed.guestName,
            color,
          }
        }
      } catch {
        /* regenerate */
      }
    }
  }
  const guestId = newGuestId()
  const identity: GuestEditorIdentity = {
    guestId,
    guestName: generateGuestDisplayName(),
    color: colorForGuestId(guestId),
  }
  if (typeof sessionStorage !== "undefined") {
    sessionStorage.setItem(key, JSON.stringify(identity))
  }
  return identity
}
