/**
 * Per-browser persistence for guests: a random device id (no PII; the server only stores a salted
 * hash) and the guest tokens for each room. Storage can be unavailable (private mode, blocked site
 * data), so every access is guarded and falls back to memory for this tab.
 */
const DEVICE_KEY = 'pintrush:device';
const TOKENS_PREFIX = 'pintrush:tokens:';
const memory = new Map<string, string>();

function read(key: string): string | null {
  try {
    return window.localStorage.getItem(key) ?? memory.get(key) ?? null;
  } catch {
    return memory.get(key) ?? null;
  }
}

function write(key: string, value: string | null): void {
  if (value === null) memory.delete(key);
  else memory.set(key, value);
  try {
    if (value === null) window.localStorage.removeItem(key);
    else window.localStorage.setItem(key, value);
  } catch {
    // memory fallback already updated
  }
}

export function getDeviceId(): string {
  let id = read(DEVICE_KEY);
  if (!id || !/^[0-9a-f-]{36}$/i.test(id)) {
    id = crypto.randomUUID();
    write(DEVICE_KEY, id);
  }
  return id;
}

export interface StoredToken {
  token: string;
  gameSessionId: string;
  playerSessionId: string;
  expiresAt: number;
  nickname?: string;
}

export function loadTokens(roomId: string): StoredToken[] {
  const raw = read(TOKENS_PREFIX + roomId);
  if (!raw) return [];
  try {
    const list = JSON.parse(raw) as StoredToken[];
    const now = Date.now();
    return Array.isArray(list) ? list.filter((t) => t && typeof t.token === 'string' && t.expiresAt > now) : [];
  } catch {
    return [];
  }
}

/** Keep one token per game session; newest first; at most 4 per room. */
export function saveToken(roomId: string, token: StoredToken): void {
  const others = loadTokens(roomId).filter((t) => t.gameSessionId !== token.gameSessionId);
  const prev = loadTokens(roomId).find((t) => t.gameSessionId === token.gameSessionId);
  const merged: StoredToken = { ...token, ...(token.nickname ? {} : prev?.nickname ? { nickname: prev.nickname } : {}) };
  write(TOKENS_PREFIX + roomId, JSON.stringify([merged, ...others].slice(0, 4)));
}

export function removeToken(roomId: string, gameSessionId: string): void {
  write(TOKENS_PREFIX + roomId, JSON.stringify(loadTokens(roomId).filter((t) => t.gameSessionId !== gameSessionId)));
}

export function clearTokens(roomId: string): void {
  write(TOKENS_PREFIX + roomId, null);
}

export function lastNickname(roomId: string): string | null {
  return loadTokens(roomId)[0]?.nickname ?? null;
}
