// Cross-platform OS info for the Svelte frontend. Single async fetch,
// cached in memory, exposes synchronous helpers after first await.
//
// Backed by the `get_os_info` Tauri command (commands/diagnostics.rs).
// In browser-preview mode (no Tauri runtime), falls back to a sensible
// default based on navigator.platform.
//
// Usage:
//   import { loadOsInfo, osInfo, modKeyLabel, isMac } from '$lib/utils/osInfo.js';
//   await loadOsInfo();          // call once at app startup
//   modKeyLabel();               // "Cmd" on macOS, "Ctrl" elsewhere
//   if (isMac()) { ... }
//
// The store version (osInfo) is reactive — Svelte components can read it
// directly with `$osInfo` once Svelte 5 runes are everywhere, or via
// destructuring on a non-reactive read.

import { invoke } from '@tauri-apps/api/core';
import { hasTauriRuntime } from './runtime.js';

interface OsInfo {
  os: string;
  arch: string;
  family: string;
  usesCmd: boolean;
  isWayland: boolean;
  customHotkeyBackend: boolean;
  primaryModifierLabel: string;
}

let cached: OsInfo | null = null;

const FALLBACK_BROWSER_INFO = {
  os: detectBrowserOs(),
  arch: 'unknown',
  family: detectBrowserFamily(),
  usesCmd: detectBrowserOs() === 'macos',
  isWayland: false,
  customHotkeyBackend: false,
  primaryModifierLabel: detectBrowserOs() === 'macos' ? 'Cmd' : 'Ctrl',
};

function detectBrowserOs() {
  if (typeof navigator === 'undefined') return 'unknown';
  const ua = (navigator.userAgent || '').toLowerCase();
  const platform = (navigator.platform || '').toLowerCase();
  if (platform.includes('mac') || ua.includes('mac os')) return 'macos';
  if (platform.includes('win') || ua.includes('windows')) return 'windows';
  if (platform.includes('linux') || ua.includes('linux')) return 'linux';
  return 'unknown';
}

function detectBrowserFamily() {
  switch (detectBrowserOs()) {
    case 'macos': return 'macOS';
    case 'windows': return 'Windows';
    case 'linux': return 'Linux';
    default: return 'Unknown';
  }
}

/** Fetch OS info from the Tauri backend. Idempotent — call multiple times,
 *  only the first does the round-trip. Browser-preview mode returns the
 *  navigator-detected fallback. */
export async function loadOsInfo(): Promise<OsInfo> {
  if (cached) return cached;
  if (!hasTauriRuntime()) {
    cached = FALLBACK_BROWSER_INFO;
    return cached;
  }
  try {
    cached = await invoke<OsInfo>("get_os_info");
  } catch (err) {
    console.warn('loadOsInfo: get_os_info failed, using browser fallback', err);
    cached = FALLBACK_BROWSER_INFO;
  }
  return cached;
}

/** Synchronous accessor. Returns null if loadOsInfo has not been awaited
 *  yet. Components that need the value at first render should await
 *  loadOsInfo() in onMount before reading. */
export function osInfo(): OsInfo | null {
  return cached;
}

export function isMac(): boolean {
  return cached?.os === 'macos';
}

export function isWindows(): boolean {
  return cached?.os === 'windows';
}

export function isLinux(): boolean {
  return cached?.os === 'linux';
}

/** Localised label for the primary keyboard modifier. "Cmd" on macOS,
 *  "Ctrl" everywhere else. Use in hotkey display strings:
 *      `${modKeyLabel()}+Shift+R` */
export function modKeyLabel(): string {
  return cached?.primaryModifierLabel ?? 'Ctrl';
}

/** True if the current Linux session is Wayland. False on Windows/macOS.
 *  Useful for Settings → Audio "PipeWire detected" status display. */
export function isWayland(): boolean {
  return !!cached?.isWayland;
}
