/**
 * Svelte 5 rune-based font store.
 * Manages UI font and terminal font state.
 * Applies CSS custom properties instantly; persists via settings RPC.
 * Exposes a callback registry so terminal instances can react to font changes.
 *
 * Usage:
 *   import { fontStore } from './font-store.svelte';
 *   fontStore.setUIFont('Inter', 14);
 *   fontStore.setTermFont('JetBrains Mono', 13);
 *   const unsub = fontStore.onTermFontChange((family, size) => terminal.options.fontFamily = family);
 *   await fontStore.initFonts(rpc);
 */

// ── Minimal RPC interface ─────────────────────────────────────────────────────

interface SettingsRpc {
  request: {
    "settings.set"(p: { key: string; value: string }): Promise<{ ok: boolean }>;
    "settings.getAll"(p: Record<string, never>): Promise<{ settings: Record<string, string> }>;
  };
}

// ── Types ─────────────────────────────────────────────────────────────────────

type TermFontCallback = (family: string, size: number) => void;

// ── Defaults ──────────────────────────────────────────────────────────────────

const DEFAULTS = {
  uiFontFamily:   "",   // empty = CSS fallback (system-ui)
  uiFontSize:     14,
  termFontFamily: "",   // empty = CSS fallback (JetBrains Mono, monospace)
  termFontSize:   13,
} as const;

// ── Store ─────────────────────────────────────────────────────────────────────

function createFontStore() {
  let uiFontFamily   = $state<string>(DEFAULTS.uiFontFamily);
  let uiFontSize     = $state<number>(DEFAULTS.uiFontSize);
  let termFontFamily = $state<string>(DEFAULTS.termFontFamily);
  let termFontSize   = $state<number>(DEFAULTS.termFontSize);

  let rpc: SettingsRpc | null = null;
  const termCallbacks = new Set<TermFontCallback>();

  // ── CSS helpers ────────────────────────────────────────────────────────────

  function applyUICss(family: string, size: number): void {
    const style = document.documentElement.style;
    style.setProperty("--ui-font-family", family || "system-ui, -apple-system, sans-serif");
    style.setProperty("--ui-font-size",   `${size}px`);
    uiFontFamily = family;
    uiFontSize   = size;
  }

  function applyTermCss(family: string, size: number): void {
    const style = document.documentElement.style;
    style.setProperty("--term-font-family", family || "JetBrains Mono, Consolas, monospace");
    style.setProperty("--term-font-size",   `${size}px`);
    termFontFamily = family;
    termFontSize   = size;
    for (const cb of termCallbacks) {
      try { cb(family, size); }
      catch (err) { console.error("[font-store] termFont callback error:", err); }
    }
  }

  // ── Public API ─────────────────────────────────────────────────────────────

  function setUIFont(family: string, size: number): void {
    applyUICss(family, size);
    if (rpc) {
      rpc.request["settings.set"]({ key: "ui_font_family", value: family  }).catch(console.error);
      rpc.request["settings.set"]({ key: "ui_font_size",   value: String(size) }).catch(console.error);
    }
  }

  function setTermFont(family: string, size: number): void {
    applyTermCss(family, size);
    if (rpc) {
      rpc.request["settings.set"]({ key: "term_font_family", value: family  }).catch(console.error);
      rpc.request["settings.set"]({ key: "term_font_size",   value: String(size) }).catch(console.error);
    }
  }

  /** Register a callback invoked whenever the terminal font changes. Returns unsubscribe fn. */
  function onTermFontChange(cb: TermFontCallback): () => void {
    termCallbacks.add(cb);
    return () => termCallbacks.delete(cb);
  }

  /** Load all persisted font settings on startup. Call once in App.svelte onMount. */
  async function initFonts(rpcInstance: SettingsRpc): Promise<void> {
    rpc = rpcInstance;
    try {
      const { settings } = await rpc.request["settings.getAll"]({});

      const family  = settings["ui_font_family"]   ?? DEFAULTS.uiFontFamily;
      const rawSize = parseInt(settings["ui_font_size"] ?? "", 10);
      const size    = isNaN(rawSize) ? DEFAULTS.uiFontSize : rawSize;

      const tFamily  = settings["term_font_family"] ?? DEFAULTS.termFontFamily;
      const rawTSize = parseInt(settings["term_font_size"] ?? "", 10);
      const tSize    = isNaN(rawTSize) ? DEFAULTS.termFontSize : rawTSize;

      applyUICss(family,  size);
      applyTermCss(tFamily, tSize);
    } catch (err) {
      console.error("[font-store] Failed to load font settings:", err);
      applyUICss(DEFAULTS.uiFontFamily, DEFAULTS.uiFontSize);
      applyTermCss(DEFAULTS.termFontFamily, DEFAULTS.termFontSize);
    }
  }

  return {
    get uiFontFamily()   { return uiFontFamily; },
    get uiFontSize()     { return uiFontSize; },
    get termFontFamily() { return termFontFamily; },
    get termFontSize()   { return termFontSize; },
    setUIFont,
    setTermFont,
    onTermFontChange,
    initFonts,
  };
}

export const fontStore = createFontStore();
