// Telegram CloudStorage sync for the device-independent client display preferences — theme,
// reduce-motion and board labels — so they follow the user across their Telegram devices. The
// interface language is intentionally excluded: it has its own server-side sync
// (Profile.preferredLanguage) plus an on-launch reconciler, and mixing it in here would fight that.
// The pure encode/decode is kept free of the SDK and the DOM so it unit-tests in the node
// environment; the CloudStorage transport wrappers live in telegram.ts and the wiring (mirror on
// save, reconcile on launch) in app.svelte.ts.

import type { ThemePref } from './theme';
import type { BoardLabelMode } from './boardlabels';

/** ClientPrefs is the subset of preferences synced across devices via Telegram CloudStorage. */
export interface ClientPrefs {
  theme: ThemePref;
  reduceMotion: boolean;
  boardLabels: BoardLabelMode;
}

/** CLOUD_PREFS_KEY is the Telegram CloudStorage key holding the JSON-encoded ClientPrefs. */
export const CLOUD_PREFS_KEY = 'prefs';

/** encodeClientPrefs serialises the synced client prefs (and only those — never the locale). */
export function encodeClientPrefs(p: ClientPrefs): string {
  return JSON.stringify({ theme: p.theme, reduceMotion: p.reduceMotion, boardLabels: p.boardLabels });
}

/**
 * decodeClientPrefs parses a CloudStorage payload into a partial ClientPrefs, keeping only valid
 * fields and dropping anything unknown, mistyped or malformed — so a value written by a newer or
 * older build, or a corrupt entry, never throws and never applies a bad setting. A missing field
 * stays absent, so the caller leaves the corresponding local value untouched.
 */
export function decodeClientPrefs(raw: string | null | undefined): Partial<ClientPrefs> {
  if (!raw) return {};
  let o: Record<string, unknown>;
  try {
    o = JSON.parse(raw) as Record<string, unknown>;
  } catch {
    return {};
  }
  if (!o || typeof o !== 'object') return {};
  const out: Partial<ClientPrefs> = {};
  if (o.theme === 'auto' || o.theme === 'light' || o.theme === 'dark') out.theme = o.theme;
  if (typeof o.reduceMotion === 'boolean') out.reduceMotion = o.reduceMotion;
  if (o.boardLabels === 'beginner' || o.boardLabels === 'classic' || o.boardLabels === 'none') {
    out.boardLabels = o.boardLabels;
  }
  return out;
}
