// Game variants offered on New Game, and the gating of that choice by the
// languages the sign-in service supports. Kept out of the .svelte screen so the
// gating is unit-testable (the project's node-env Vitest layer).

import type { MessageKey } from './i18n/index.svelte';
import type { Variant } from './model';

// VariantOption is a selectable game variant with its i18n label key.
export interface VariantOption {
  id: Variant;
  label: MessageKey;
}

// ALL_VARIANTS lists every variant in display order (Erudit first — the default
// preference and the product's primary variant). The labels are display names keyed by
// the game's alphabet, not the interface language: the English-alphabet game is always
// "Scrabble" and the Russian-alphabet Scrabble always "Скрэббл" (both unlocalized, so the
// two never collide whatever the UI language); Erudit is localized "Erudite"/"Эрудит".
export const ALL_VARIANTS: VariantOption[] = [
  { id: 'erudit_ru', label: 'new.erudit' },
  { id: 'scrabble_ru', label: 'new.russian' },
  { id: 'scrabble_en', label: 'new.english' },
];

// variantNameKey returns the i18n key for a variant's display name (used by the in-game
// title and the lobby cards).
export function variantNameKey(v: Variant): MessageKey {
  return ALL_VARIANTS.find((o) => o.id === v)?.label ?? 'new.english';
}

// noRepeatWordsFor reports whether a new game of variant v takes the no-repeat-words rule (see
// lib/dict/norepeat): a word already on the board cannot be laid again. It is a rule of Erudit
// alone — both Scrabble variants let a word be played as often as a player can manage. It mirrors
// the server's noRepeatWordsFor and is only ever consulted when a game is created; an existing
// game carries its own pinned answer (GameView.noRepeatWords / LocalGameRecord.noRepeatWords).
export function noRepeatWordsFor(v: Variant): boolean {
  return v === 'erudit_ru';
}

// VARIANT_RULES is the i18n key for each variant's one-line rules summary on the New Game
// buttons (bag size, the ё rule, bonus differences), sourced from the engine rulesets.
export const VARIANT_RULES: Record<Variant, MessageKey> = {
  scrabble_en: 'new.rulesEnglish',
  scrabble_ru: 'new.rulesRussian',
  erudit_ru: 'new.rulesErudit',
};

// VARIANT_FLAG is the flag shown on a variant button: an emoji for the Scrabble variants;
// Erudit uses the bundled USSR flag SVG (public/flag-ussr.svg), so its entry is empty.
export const VARIANT_FLAG: Record<Variant, string> = {
  scrabble_en: '🇺🇸',
  scrabble_ru: '🇷🇺',
  erudit_ru: '',
};

// VARIANT_LANGUAGE maps each variant to its game language. en -> English;
// ru -> Russian + Эрудит.
export const VARIANT_LANGUAGE: Record<Variant, 'en' | 'ru'> = { scrabble_en: 'en', scrabble_ru: 'ru', erudit_ru: 'ru' };

// BLANK_STAR is the glyph drawn on an Эрудит blank tile: the variant's blank is the
// "звёздочка" (star) chip, so it carries a star rather than a bare face. U+273B HEAVY
// TEARDROP-SPOKED ASTERISK.
export const BLANK_STAR = '✻';

// usesStarBlank reports whether a variant marks its blank tiles with BLANK_STAR. Only
// Эрудит does: an empty rack blank shows the star centred, and a placed blank carries it
// in the value corner (the corner is free — a blank has no point value). The Scrabble
// variants leave the blank unmarked (an empty rack face; a placed blank shown by its
// designated letter alone).
export function usesStarBlank(v: Variant): boolean {
  return v === 'erudit_ru';
}

// DEFAULT_VARIANTS is the variant set a player sees before any preference is stored — a fresh
// or offline native client whose profile has not been synced yet (the device-local guest boots
// with no profile at all). Such a client is a guest, so it mirrors the backend's *guest* set
// (account.GuestVariantPreferences, Erudit alone) rather than the wider set a registered account
// is created with. Every dictionary is still bundled; the other variants are simply off until
// the player registers and turns them on in Settings.
export const DEFAULT_VARIANTS: Variant[] = ['erudit_ru'];

// availableVariants gates ALL_VARIANTS by the player's variant preferences (the set they
// enabled in Settings). An empty or absent set falls back to DEFAULT_VARIANTS rather than every
// variant: a real profile always carries at least one preference, and a profileless client (a
// fresh offline native launch) must match the server's guest default instead of exposing
// the other games before the player opts in.
export function availableVariants(preferences: Variant[] | undefined): VariantOption[] {
  const prefs = preferences ?? [];
  const effective = prefs.length === 0 ? DEFAULT_VARIANTS : prefs;
  return ALL_VARIANTS.filter((v) => effective.includes(v.id));
}

// showRegisterHint reports whether New Game invites the player to sign in in order to unlock the
// other games, given whether they are a guest (isGuest), how many variants they are offered
// (offered) and whether the app is in offline mode (offline). It is the guest's case alone: a
// guest is created with Erudit only, while signing in widens the account to both Russian-alphabet
// games. Offline it is suppressed — signing in needs the network, so the link would be dead.
export function showRegisterHint(isGuest: boolean, offered: number, offline: boolean): boolean {
  return isGuest && !offline && offered === 1;
}

// supportsMultipleWordsToggle reports whether the New Game "multiple words per turn" toggle
// applies to a variant. Only Russian games choose the rule; English is always standard, so
// its toggle is not shown.
export function supportsMultipleWordsToggle(v: Variant): boolean {
  return VARIANT_LANGUAGE[v] === 'ru';
}

// multipleWordsForRequest resolves the per-turn word rule sent when starting a game of the
// variant: Russian games carry the toggle's value, English games are silently standard
// (true), so matchmaking and game creation stay one uniform path.
export function multipleWordsForRequest(v: Variant, toggle: boolean): boolean {
  return supportsMultipleWordsToggle(v) ? toggle : true;
}
